source: git/libpolys/polys/simpleideals.cc @ 5f24ec

spielwiese
Last change on this file since 5f24ec was 5f24ec, checked in by Oleksandr Motsak <motsak@…>, 9 years ago
Reviewing 0-size ideals/modules ADD: added assume's, esp. concerning corner cases ADD: doxygen documentation for id* functions and sip_sideal structure CHG: minor improvements CHG: moved id_IsModule back to where it came from NOTE: id_Delete will also be used for dense matrices
  • Property mode set to 100644
File size: 36.7 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT - all basic methods to manipulate ideals
6*/
7
8
9/* includes */
10
11
12
13#include <misc/auxiliary.h>
14
15#include <omalloc/omalloc.h>
16
17#include <misc/options.h>
18#include <misc/intvec.h>
19
20// #include <coeffs/longrat.h>
21#include "matpol.h"
22
23#include "monomials/p_polys.h"
24#include "weight.h"
25#include "sbuckets.h"
26#include "clapsing.h"
27
28#include "simpleideals.h"
29
30omBin sip_sideal_bin = omGetSpecBin(sizeof(sip_sideal));
31
32static poly * idpower;
33/*collects the monomials in makemonoms, must be allocated befor*/
34static int idpowerpoint;
35/*index of the actual monomial in idpower*/
36
37/// initialise an ideal / module
38ideal idInit(int idsize, int rank)
39{
40  assume( idsize >= 0 && rank >= 0 );
41 
42  ideal hh = (ideal)omAllocBin(sip_sideal_bin);
43
44  IDELEMS(hh) = idsize; // ncols
45  hh->nrows = 1; // ideal/module!
46
47  hh->rank = rank; // ideal: 1, module: >= 0!
48 
49  if (idsize>0)
50    hh->m = (poly *)omAlloc0(idsize*sizeof(poly));
51  else
52    hh->m = NULL;
53 
54  return hh;
55}
56
57#ifdef PDEBUG
58// this is only for outputting an ideal within the debugger
59// therefor it accept the otherwise illegal id==NULL
60void idShow(const ideal id, const ring lmRing, const ring tailRing, const int debugPrint)
61{
62  assume( debugPrint >= 0 );
63
64  if( id == NULL )
65    PrintS("(NULL)");
66  else
67  {
68    Print("Module of rank %ld,real rank %ld and %d generators.\n",
69          id->rank,id_RankFreeModule(id, lmRing, tailRing),IDELEMS(id));
70
71    int j = (id->ncols*id->nrows) - 1;
72    while ((j > 0) && (id->m[j]==NULL)) j--;
73    for (int i = 0; i <= j; i++)
74    {
75      Print("generator %d: ",i); p_DebugPrint(id->m[i], lmRing, tailRing, debugPrint);
76    }
77  }
78}
79#endif
80
81/// index of generator with leading term in ground ring (if any);
82/// otherwise -1
83int id_PosConstant(ideal id, const ring r)
84{
85  id_Test(id, r);
86  const int N = IDELEMS(id) - 1;
87  const poly * m = id->m + N;
88
89  for (int k = N; k >= 0; --k, --m)
90  {
91    const poly p = *m;
92    if (p!=NULL)
93       if (p_LmIsConstantComp(p, r) == TRUE)
94         return k;
95  }
96
97  return -1;
98}
99
100/// initialise the maximal ideal (at 0)
101ideal id_MaxIdeal (const ring r)
102{
103  const int N = rVar(r);
104  ideal hh = idInit(N, 1);
105  for (int l=0; l < N; l++)
106  {
107    hh->m[l] = p_One(r);
108    p_SetExp(hh->m[l],l+1,1,r);
109    p_Setm(hh->m[l],r);
110  }
111  id_Test(hh, r);
112  return hh;
113}
114
115/// deletes an ideal/module/matrix
116void id_Delete (ideal * h, ring r)
117{
118  if (*h == NULL)
119    return;
120
121  id_Test(*h, r);
122 
123  const int elems = (*h)->nrows * (*h)->ncols;
124
125  if ( elems > 0 )
126  {
127    assume( (*h)->m != NULL );
128   
129    int j = elems;
130    do
131    {
132      j--;
133      poly pp=((*h)->m[j]);
134      if (pp!=NULL) p_Delete(&pp, r);
135    }
136    while (j>0);   
137   
138    omFreeSize((ADDRESS)((*h)->m),sizeof(poly)*elems);
139  }
140 
141  omFreeBin((ADDRESS)*h, sip_sideal_bin);
142  *h=NULL;
143}
144
145
146/// Shallowdeletes an ideal/matrix
147void id_ShallowDelete (ideal *h, ring r)
148{
149  id_Test(*h, r);
150 
151  if (*h == NULL)
152    return;
153 
154  int j,elems;
155  elems=j=(*h)->nrows*(*h)->ncols;
156  if (j>0)
157  {
158    assume( (*h)->m != NULL );
159    do
160    {
161      p_ShallowDelete(&((*h)->m[--j]), r);
162    }
163    while (j>0);
164    omFreeSize((ADDRESS)((*h)->m),sizeof(poly)*elems);
165  }
166  omFreeBin((ADDRESS)*h, sip_sideal_bin);
167  *h=NULL;
168}
169
170/// gives an ideal/module the minimal possible size
171void idSkipZeroes (ideal ide)
172{
173  assume (ide != NULL);
174 
175  int k;
176  int j = -1;
177  BOOLEAN change=FALSE; 
178 
179  for (k=0; k<IDELEMS(ide); k++)
180  {
181    if (ide->m[k] != NULL)
182    {
183      j++;
184      if (change)
185      {
186        ide->m[j] = ide->m[k];
187      }
188    }
189    else
190    {
191      change=TRUE;
192    }
193  }
194  if (change)
195  {
196    if (j == -1)
197      j = 0;
198    else
199    {
200      for (k=j+1; k<IDELEMS(ide); k++)
201        ide->m[k] = NULL;
202    }
203    pEnlargeSet(&(ide->m),IDELEMS(ide),j+1-IDELEMS(ide));
204    IDELEMS(ide) = j+1;
205  }
206}
207
208/// count non-zero elements
209int idElem(const ideal F)
210{
211  assume (F != NULL);
212 
213  int i=0,j=IDELEMS(F)-1;
214
215  while(j>=0)
216  {
217    if ((F->m)[j]!=NULL) i++;
218    j--;
219  }
220  return i;
221}
222
223/// copies the first k (>= 1) entries of the given ideal/module
224/// and returns these as a new ideal/module
225/// (Note that the copied entries may be zero.)
226ideal id_CopyFirstK (const ideal ide, const int k,const ring r)
227{
228  id_Test(ide, r);
229 
230  assume( ide != NULL );
231  assume( k <= IDELEMS(ide) );
232 
233  ideal newI = idInit(k, ide->rank);
234 
235  for (int i = 0; i < k; i++)
236    newI->m[i] = p_Copy(ide->m[i],r);
237 
238  return newI;
239}
240
241/// ideal id = (id[i]), result is leadcoeff(id[i]) = 1
242void id_Norm(ideal id, const ring r)
243{
244  id_Test(id, r);
245  for (int i=IDELEMS(id)-1; i>=0; i--)
246  {
247    if (id->m[i] != NULL)
248    {
249      p_Norm(id->m[i],r);
250    }
251  }
252}
253
254/// ideal id = (id[i]), c any unit
255/// if id[i] = c*id[j] then id[j] is deleted for j > i
256void id_DelMultiples(ideal id, const ring r)
257{
258  id_Test(id, r);
259
260  int i, j;
261  int k = IDELEMS(id)-1;
262  for (i=k; i>=0; i--)
263  {
264    if (id->m[i]!=NULL)
265    {
266      for (j=k; j>i; j--)
267      {
268        if (id->m[j]!=NULL)
269        {
270#ifdef HAVE_RINGS
271          if (rField_is_Ring(r))
272          {
273            /* if id[j] = c*id[i] then delete id[j].
274               In the below cases of a ground field, we
275               check whether id[i] = c*id[j] and, if so,
276               delete id[j] for historical reasons (so
277               that previous output does not change) */
278            if (p_ComparePolys(id->m[j], id->m[i],r)) p_Delete(&id->m[j],r);
279          }
280          else
281          {
282            if (p_ComparePolys(id->m[i], id->m[j],r)) p_Delete(&id->m[j],r);
283          }
284#else
285          if (p_ComparePolys(id->m[i], id->m[j],r)) p_Delete(&id->m[j],r);
286#endif
287        }
288      }
289    }
290  }
291}
292
293/// ideal id = (id[i])
294/// if id[i] = id[j] then id[j] is deleted for j > i
295void id_DelEquals(ideal id, const ring r)
296{
297  id_Test(id, r);
298
299  int i, j;
300  int k = IDELEMS(id)-1;
301  for (i=k; i>=0; i--)
302  {
303    if (id->m[i]!=NULL)
304    {
305      for (j=k; j>i; j--)
306      {
307        if ((id->m[j]!=NULL)
308        && (p_EqualPolys(id->m[i], id->m[j],r)))
309        {
310          p_Delete(&id->m[j],r);
311        }
312      }
313    }
314  }
315}
316
317/// Delete id[j], if Lm(j) == Lm(i) and both LC(j), LC(i) are units and j > i
318void id_DelLmEquals(ideal id, const ring r)
319{
320  id_Test(id, r);
321
322  int i, j;
323  int k = IDELEMS(id)-1;
324  for (i=k; i>=0; i--)
325  {
326    if (id->m[i] != NULL)
327    {
328      for (j=k; j>i; j--)
329      {
330        if ((id->m[j] != NULL)
331        && p_LmEqual(id->m[i], id->m[j],r)
332#ifdef HAVE_RINGS
333        && n_IsUnit(pGetCoeff(id->m[i]),r->cf) && n_IsUnit(pGetCoeff(id->m[j]),r->cf)
334#endif
335        )
336        {
337          p_Delete(&id->m[j],r);
338        }
339      }
340    }
341  }
342}
343
344/// delete id[j], if LT(j) == coeff*mon*LT(i) and vice versa, i.e.,
345/// delete id[i], if LT(i) == coeff*mon*LT(j)
346void id_DelDiv(ideal id, const ring r)
347{
348  id_Test(id, r);
349 
350  int i, j;
351  int k = IDELEMS(id)-1;
352  for (i=k; i>=0; i--)
353  {
354    if (id->m[i] != NULL)
355    {
356      for (j=k; j>i; j--)
357      {
358        if (id->m[j]!=NULL)
359        {
360#ifdef HAVE_RINGS
361          if (rField_is_Ring(r))
362          {
363            if (p_DivisibleByRingCase(id->m[i], id->m[j],r))
364            {
365              p_Delete(&id->m[j],r);
366            }
367            else if (p_DivisibleByRingCase(id->m[j], id->m[i],r))
368            {
369              p_Delete(&id->m[i],r);
370              break;
371            }
372          }
373          else
374          {
375#endif
376          /* the case of a ground field: */
377          if (p_DivisibleBy(id->m[i], id->m[j],r))
378          {
379            p_Delete(&id->m[j],r);
380          }
381          else if (p_DivisibleBy(id->m[j], id->m[i],r))
382          {
383            p_Delete(&id->m[i],r);
384            break;
385          }
386#ifdef HAVE_RINGS
387          }
388#endif
389        }
390      }
391    }
392  }
393}
394
395/// test if the ideal has only constant polynomials
396/// NOTE: zero ideal/module is also constant
397BOOLEAN id_IsConstant(ideal id, const ring r)
398{
399  id_Test(id, r);
400 
401  for (int k = IDELEMS(id)-1; k>=0; k--)
402  {
403    if (!p_IsConstantPoly(id->m[k],r))
404      return FALSE;
405  }
406  return TRUE;
407}
408
409/// copy an ideal
410ideal id_Copy(ideal h1, const ring r)
411{
412  id_Test(h1, r);
413
414  ideal h2 = idInit(IDELEMS(h1), h1->rank);
415  for (int i=IDELEMS(h1)-1; i>=0; i--)
416    h2->m[i] = p_Copy(h1->m[i],r);
417  return h2;
418}
419
420#ifdef PDEBUG
421/// Internal verification for ideals/modules and dense matrices!
422void id_DBTest(ideal h1, int level, const char *f,const int l, const ring r, const ring tailRing)
423{
424  if (h1 != NULL)
425  { 
426    // assume(IDELEMS(h1) > 0); for ideal/module, does not apply to matrix
427    omCheckAddrSize(h1,sizeof(*h1));
428
429    assume( h1->ncols >= 0 );
430    assume( h1->nrows >= 0 ); // matrix case!
431   
432    assume( h1->rank >= 0 );
433
434    const int n = (h1->ncols * h1->nrows);
435
436    assume( !( n > 0 && h1->m == NULL) );
437
438    if( h1->m != NULL && n > 0 )
439      omdebugAddrSize(h1->m, n * sizeof(poly));
440   
441    long new_rk = 0; // inlining id_RankFreeModule(h1, r, tailRing);
442
443    /* to be able to test matrices: */
444    for (int i=n - 1; i >= 0; i--)
445    {
446      _pp_Test(h1->m[i], r, tailRing, level);
447      const long k = p_MaxComp(h1->m[i], r, tailRing);
448      if (k > new_rk) new_rk = k;
449    }
450
451    // dense matrices only contain polynomials:
452    // h1->nrows == h1->rank > 1 && new_rk == 0!
453    assume( !( h1->nrows == h1->rank && h1->nrows > 1 && new_rk > 0 ) ); //
454   
455    if(new_rk > h1->rank)
456    {
457      dReportError("wrong rank %d (should be %d) in %s:%d\n",
458                   h1->rank, new_rk, f,l);
459      omPrintAddrInfo(stderr, h1, " for ideal");
460      h1->rank = new_rk;
461    }
462  }
463  else
464  {
465    Print("error: ideal==NULL in %s:%d\n",f,l);
466    assume( h1 != NULL );
467  }
468}
469#endif
470
471/// for idSort: compare a and b revlex inclusive module comp.
472static int p_Comp_RevLex(poly a, poly b,BOOLEAN nolex, const ring R)
473{
474  if (b==NULL) return 1;
475  if (a==NULL) return -1;
476
477  if (nolex)
478  {
479    int r=p_LmCmp(a,b,R);
480    if (r!=0) return r;
481    number h=n_Sub(pGetCoeff(a),pGetCoeff(b),R->cf);
482    r = -1+n_IsZero(h,R->cf)+2*n_GreaterZero(h,R->cf); /* -1: <, 0:==, 1: > */
483    n_Delete(&h, R->cf);
484    return r;
485  }
486  int l=rVar(R);
487  while ((l>0) && (p_GetExp(a,l,R)==p_GetExp(b,l,R))) l--;
488  if (l==0)
489  {
490    if (p_GetComp(a,R)==p_GetComp(b,R))
491    {
492      number h=n_Sub(pGetCoeff(a),pGetCoeff(b),R->cf);
493      int r = -1+n_IsZero(h,R->cf)+2*n_GreaterZero(h,R->cf); /* -1: <, 0:==, 1: > */
494      n_Delete(&h,R->cf);
495      return r;
496    }
497    if (p_GetComp(a,R)>p_GetComp(b,R)) return 1;
498  }
499  else if (p_GetExp(a,l,R)>p_GetExp(b,l,R))
500    return 1;
501  return -1;
502}
503
504// sorts the ideal w.r.t. the actual ringordering
505// uses lex-ordering when nolex = FALSE
506intvec *id_Sort(const ideal id, const BOOLEAN nolex, const ring r)
507{
508  id_Test(id, r);
509
510  intvec * result = new intvec(IDELEMS(id));
511  int i, j, actpos=0, newpos;
512  int diff, olddiff, lastcomp, newcomp;
513  BOOLEAN notFound;
514
515  for (i=0;i<IDELEMS(id);i++)
516  {
517    if (id->m[i]!=NULL)
518    {
519      notFound = TRUE;
520      newpos = actpos / 2;
521      diff = (actpos+1) / 2;
522      diff = (diff+1) / 2;
523      lastcomp = p_Comp_RevLex(id->m[i],id->m[(*result)[newpos]],nolex,r);
524      if (lastcomp<0)
525      {
526        newpos -= diff;
527      }
528      else if (lastcomp>0)
529      {
530        newpos += diff;
531      }
532      else
533      {
534        notFound = FALSE;
535      }
536      //while ((newpos>=0) && (newpos<actpos) && (notFound))
537      while (notFound && (newpos>=0) && (newpos<actpos))
538      {
539        newcomp = p_Comp_RevLex(id->m[i],id->m[(*result)[newpos]],nolex,r);
540        olddiff = diff;
541        if (diff>1)
542        {
543          diff = (diff+1) / 2;
544          if ((newcomp==1)
545          && (actpos-newpos>1)
546          && (diff>1)
547          && (newpos+diff>=actpos))
548          {
549            diff = actpos-newpos-1;
550          }
551          else if ((newcomp==-1)
552          && (diff>1)
553          && (newpos<diff))
554          {
555            diff = newpos;
556          }
557        }
558        if (newcomp<0)
559        {
560          if ((olddiff==1) && (lastcomp>0))
561            notFound = FALSE;
562          else
563            newpos -= diff;
564        }
565        else if (newcomp>0)
566        {
567          if ((olddiff==1) && (lastcomp<0))
568          {
569            notFound = FALSE;
570            newpos++;
571          }
572          else
573          {
574            newpos += diff;
575          }
576        }
577        else
578        {
579          notFound = FALSE;
580        }
581        lastcomp = newcomp;
582        if (diff==0) notFound=FALSE; /*hs*/
583      }
584      if (newpos<0) newpos = 0;
585      if (newpos>actpos) newpos = actpos;
586      while ((newpos<actpos) && (p_Comp_RevLex(id->m[i],id->m[(*result)[newpos]],nolex,r)==0))
587        newpos++;
588      for (j=actpos;j>newpos;j--)
589      {
590        (*result)[j] = (*result)[j-1];
591      }
592      (*result)[newpos] = i;
593      actpos++;
594    }
595  }
596  for (j=0;j<actpos;j++) (*result)[j]++;
597  return result;
598}
599
600/// concat the lists h1 and h2 without zeros
601ideal id_SimpleAdd (ideal h1,ideal h2, const ring R)
602{
603  id_Test(h1, R);
604  id_Test(h2, R);
605 
606  if ( idIs0(h1) ) return id_Copy(h2,R);
607  if ( idIs0(h2) ) return id_Copy(h1,R);
608
609  int j = IDELEMS(h1)-1;
610  while ((j >= 0) && (h1->m[j] == NULL)) j--;
611 
612  int i = IDELEMS(h2)-1;
613  while ((i >= 0) && (h2->m[i] == NULL)) i--;
614 
615  const int r = si_max(h1->rank, h2->rank);
616 
617  ideal result = idInit(i+j+2,r);
618
619  int l;
620 
621  for (l=j; l>=0; l--)
622    result->m[l] = p_Copy(h1->m[l],R);
623 
624  j = i+j+1;
625  for (l=i; l>=0; l--, j--)
626    result->m[j] = p_Copy(h2->m[l],R);
627 
628  return result;
629}
630
631/// insert h2 into h1 (if h2 is not the zero polynomial)
632/// return TRUE iff h2 was indeed inserted
633BOOLEAN idInsertPoly (ideal h1, poly h2)
634{
635  if (h2==NULL) return FALSE;
636  assume (h1 != NULL);
637 
638  int j = IDELEMS(h1) - 1;
639 
640  while ((j >= 0) && (h1->m[j] == NULL)) j--;
641  j++;
642  if (j==IDELEMS(h1))
643  {
644    pEnlargeSet(&(h1->m),IDELEMS(h1),16);
645    IDELEMS(h1)+=16;
646  }
647  h1->m[j]=h2;
648  return TRUE;
649}
650
651
652/*! insert h2 into h1 depending on the two boolean parameters:
653 * - if zeroOk is true, then h2 will also be inserted when it is zero
654 * - if duplicateOk is true, then h2 will also be inserted when it is
655 *   already present in h1
656 * return TRUE iff h2 was indeed inserted
657 */
658BOOLEAN id_InsertPolyWithTests (ideal h1, const int validEntries,
659  const poly h2, const bool zeroOk, const bool duplicateOk, const ring r)
660{
661  id_Test(h1, r);
662  p_Test(h2, r);
663
664  if ((!zeroOk) && (h2 == NULL)) return FALSE;
665  if (!duplicateOk)
666  {
667    bool h2FoundInH1 = false;
668    int i = 0;
669    while ((i < validEntries) && (!h2FoundInH1))
670    {
671      h2FoundInH1 = p_EqualPolys(h1->m[i], h2,r);
672      i++;
673    }
674    if (h2FoundInH1) return FALSE;
675  }
676  if (validEntries == IDELEMS(h1))
677  {
678    pEnlargeSet(&(h1->m), IDELEMS(h1), 16);
679    IDELEMS(h1) += 16;
680  }
681  h1->m[validEntries] = h2;
682  return TRUE;
683}
684
685/// h1 + h2
686ideal id_Add (ideal h1,ideal h2, const ring r)
687{
688  id_Test(h1, r);
689  id_Test(h2, r);
690
691  ideal result = id_SimpleAdd(h1,h2,r);
692  id_Compactify(result,r);
693  return result;
694}
695
696/// h1 * h2
697/// h1 must be an ideal (with at least one column)
698/// h2 may be a module (with no columns at all)
699ideal  id_Mult (ideal h1,ideal  h2, const ring r)
700{
701  id_Test(h1, r);
702  id_Test(h2, r);
703
704  assume( h1->rank == 1 );
705
706  int j = IDELEMS(h1);
707  while ((j > 0) && (h1->m[j-1] == NULL)) j--;
708 
709  int i = IDELEMS(h2);
710  while ((i > 0) && (h2->m[i-1] == NULL)) i--;
711
712  j = j * i;
713 
714  ideal  hh = idInit(j, si_max( h2->rank, h1->rank ));
715 
716  if (j==0) return hh;
717 
718  int k = 0;
719  for (i=0; i<IDELEMS(h1); i++)
720  {
721    if (h1->m[i] != NULL)
722    {
723      for (j=0; j<IDELEMS(h2); j++)
724      {
725        if (h2->m[j] != NULL)
726        {
727          hh->m[k] = pp_Mult_qq(h1->m[i],h2->m[j],r);
728          k++;
729        }
730      }
731    }
732  }
733 
734  id_Compactify(hh,r);
735  return hh;
736}
737
738/// returns true if h is the zero ideal
739BOOLEAN idIs0 (ideal h)
740{
741  assume (h != NULL); // will fail :(
742//  if (h == NULL) return TRUE;
743 
744  for( int i = IDELEMS(h)-1; i >= 0; i-- )   
745    if(h->m[i] != NULL)
746      return FALSE;
747
748  return TRUE;
749
750}
751
752/// return the maximal component number found in any polynomial in s
753long id_RankFreeModule (ideal s, ring lmRing, ring tailRing)
754{
755  id_TestTail(s, lmRing, tailRing);
756 
757  long j = 0;
758
759  if (rRing_has_Comp(tailRing) && rRing_has_Comp(lmRing))
760  {
761    poly *p=s->m;
762    for (unsigned int l=IDELEMS(s); l > 0; --l, ++p)
763      if (*p != NULL)
764      {
765        pp_Test(*p, lmRing, tailRing);
766        const long k = p_MaxComp(*p, lmRing, tailRing);
767        if (k>j) j = k;
768      }
769  }
770 
771  return j; //  return -1;
772}
773
774/*2
775*returns true if id is homogenous with respect to the aktual weights
776*/
777BOOLEAN id_HomIdeal (ideal id, ideal Q, const ring r)
778{
779  int i;
780  BOOLEAN b;
781  i = 0;
782  b = TRUE;
783  while ((i < IDELEMS(id)) && b)
784  {
785    b = p_IsHomogeneous(id->m[i],r);
786    i++;
787  }
788  if ((b) && (Q!=NULL) && (IDELEMS(Q)>0))
789  {
790    i=0;
791    while ((i < IDELEMS(Q)) && b)
792    {
793      b = p_IsHomogeneous(Q->m[i],r);
794      i++;
795    }
796  }
797  return b;
798}
799
800/*2
801*initialized a field with r numbers between beg and end for the
802*procedure idNextChoise
803*/
804void idInitChoise (int r,int beg,int end,BOOLEAN  *endch,int * choise)
805{
806  /*returns the first choise of r numbers between beg and end*/
807  int i;
808  for (i=0; i<r; i++)
809  {
810    choise[i] = 0;
811  }
812  if (r <= end-beg+1)
813    for (i=0; i<r; i++)
814    {
815      choise[i] = beg+i;
816    }
817  if (r > end-beg+1)
818    *endch = TRUE;
819  else
820    *endch = FALSE;
821}
822
823/*2
824*returns the next choise of r numbers between beg and end
825*/
826void idGetNextChoise (int r,int end,BOOLEAN  *endch,int * choise)
827{
828  int i = r-1,j;
829  while ((i >= 0) && (choise[i] == end))
830  {
831    i--;
832    end--;
833  }
834  if (i == -1)
835    *endch = TRUE;
836  else
837  {
838    choise[i]++;
839    for (j=i+1; j<r; j++)
840    {
841      choise[j] = choise[i]+j-i;
842    }
843    *endch = FALSE;
844  }
845}
846
847/*2
848*takes the field choise of d numbers between beg and end, cancels the t-th
849*entree and searches for the ordinal number of that d-1 dimensional field
850* w.r.t. the algorithm of construction
851*/
852int idGetNumberOfChoise(int t, int d, int begin, int end, int * choise)
853{
854  int * localchoise,i,result=0;
855  BOOLEAN b=FALSE;
856
857  if (d<=1) return 1;
858  localchoise=(int*)omAlloc((d-1)*sizeof(int));
859  idInitChoise(d-1,begin,end,&b,localchoise);
860  while (!b)
861  {
862    result++;
863    i = 0;
864    while ((i<t) && (localchoise[i]==choise[i])) i++;
865    if (i>=t)
866    {
867      i = t+1;
868      while ((i<d) && (localchoise[i-1]==choise[i])) i++;
869      if (i>=d)
870      {
871        omFreeSize((ADDRESS)localchoise,(d-1)*sizeof(int));
872        return result;
873      }
874    }
875    idGetNextChoise(d-1,end,&b,localchoise);
876  }
877  omFreeSize((ADDRESS)localchoise,(d-1)*sizeof(int));
878  return 0;
879}
880
881/*2
882*computes the binomial coefficient
883*/
884int binom (int n,int r)
885{
886  int i,result;
887
888  if (r==0) return 1;
889  if (n-r<r) return binom(n,n-r);
890  result = n-r+1;
891  for (i=2;i<=r;i++)
892  {
893    result *= n-r+i;
894    if (result<0)
895    {
896      WarnS("overflow in binomials");
897      return 0;
898    }
899    result /= i;
900  }
901  return result;
902}
903
904
905/// the free module of rank i
906ideal id_FreeModule (int i, const ring r)
907{
908  assume(i >= 0);
909  ideal h = idInit(i, i);
910 
911  for (int j=0; j<i; j++)
912  {
913    h->m[j] = p_One(r);
914    p_SetComp(h->m[j],j+1,r);
915    p_SetmComp(h->m[j],r);
916  }
917 
918  return h;
919}
920
921/*2
922*computes recursively all monomials of a certain degree
923*in every step the actvar-th entry in the exponential
924*vector is incremented and the other variables are
925*computed by recursive calls of makemonoms
926*if the last variable is reached, the difference to the
927*degree is computed directly
928*vars is the number variables
929*actvar is the actual variable to handle
930*deg is the degree of the monomials to compute
931*monomdeg is the actual degree of the monomial in consideration
932*/
933static void makemonoms(int vars,int actvar,int deg,int monomdeg, const ring r)
934{
935  poly p;
936  int i=0;
937
938  if ((idpowerpoint == 0) && (actvar ==1))
939  {
940    idpower[idpowerpoint] = p_One(r);
941    monomdeg = 0;
942  }
943  while (i<=deg)
944  {
945    if (deg == monomdeg)
946    {
947      p_Setm(idpower[idpowerpoint],r);
948      idpowerpoint++;
949      return;
950    }
951    if (actvar == vars)
952    {
953      p_SetExp(idpower[idpowerpoint],actvar,deg-monomdeg,r);
954      p_Setm(idpower[idpowerpoint],r);
955      p_Test(idpower[idpowerpoint],r);
956      idpowerpoint++;
957      return;
958    }
959    else
960    {
961      p = p_Copy(idpower[idpowerpoint],r);
962      makemonoms(vars,actvar+1,deg,monomdeg,r);
963      idpower[idpowerpoint] = p;
964    }
965    monomdeg++;
966    p_SetExp(idpower[idpowerpoint],actvar,p_GetExp(idpower[idpowerpoint],actvar,r)+1,r);
967    p_Setm(idpower[idpowerpoint],r);
968    p_Test(idpower[idpowerpoint],r);
969    i++;
970  }
971}
972
973/*2
974*returns the deg-th power of the maximal ideal of 0
975*/
976ideal id_MaxIdeal(int deg, const ring r)
977{
978  if (deg < 0)
979  {
980    WarnS("maxideal: power must be non-negative");
981  }
982  if (deg < 1)
983  {
984    ideal I=idInit(1,1);
985    I->m[0]=p_One(r);
986    return I;
987  }
988  if (deg == 1)
989  {
990    return id_MaxIdeal(r);
991  }
992
993  int vars = rVar(r);
994  int i = binom(vars+deg-1,deg);
995  if (i<=0) return idInit(1,1);
996  ideal id=idInit(i,1);
997  idpower = id->m;
998  idpowerpoint = 0;
999  makemonoms(vars,1,deg,0,r);
1000  idpower = NULL;
1001  idpowerpoint = 0;
1002  return id;
1003}
1004
1005static void id_NextPotence(ideal given, ideal result,
1006  int begin, int end, int deg, int restdeg, poly ap, const ring r)
1007{
1008  poly p;
1009  int i;
1010
1011  p = p_Power(p_Copy(given->m[begin],r),restdeg,r);
1012  i = result->nrows;
1013  result->m[i] = p_Mult_q(p_Copy(ap,r),p,r);
1014//PrintS(".");
1015  (result->nrows)++;
1016  if (result->nrows >= IDELEMS(result))
1017  {
1018    pEnlargeSet(&(result->m),IDELEMS(result),16);
1019    IDELEMS(result) += 16;
1020  }
1021  if (begin == end) return;
1022  for (i=restdeg-1;i>0;i--)
1023  {
1024    p = p_Power(p_Copy(given->m[begin],r),i,r);
1025    p = p_Mult_q(p_Copy(ap,r),p,r);
1026    id_NextPotence(given, result, begin+1, end, deg, restdeg-i, p,r);
1027    p_Delete(&p,r);
1028  }
1029  id_NextPotence(given, result, begin+1, end, deg, restdeg, ap,r);
1030}
1031
1032ideal id_Power(ideal given,int exp, const ring r)
1033{
1034  ideal result,temp;
1035  poly p1;
1036  int i;
1037
1038  if (idIs0(given)) return idInit(1,1);
1039  temp = id_Copy(given,r);
1040  idSkipZeroes(temp);
1041  i = binom(IDELEMS(temp)+exp-1,exp);
1042  result = idInit(i,1);
1043  result->nrows = 0;
1044//Print("ideal contains %d elements\n",i);
1045  p1=p_One(r);
1046  id_NextPotence(temp,result,0,IDELEMS(temp)-1,exp,exp,p1,r);
1047  p_Delete(&p1,r);
1048  id_Delete(&temp,r);
1049  result->nrows = 1;
1050  id_DelEquals(result,r);
1051  idSkipZeroes(result);
1052  return result;
1053}
1054
1055/*2
1056*skips all zeroes and double elements, searches also for units
1057*/
1058void id_Compactify(ideal id, const ring r)
1059{
1060  int i;
1061  BOOLEAN b=FALSE;
1062
1063  i = IDELEMS(id)-1;
1064  while ((! b) && (i>=0))
1065  {
1066    b=p_IsUnit(id->m[i],r);
1067    i--;
1068  }
1069  if (b)
1070  {
1071    for(i=IDELEMS(id)-1;i>=0;i--) p_Delete(&id->m[i],r);
1072    id->m[0]=p_One(r);
1073  }
1074  else
1075  {
1076    id_DelMultiples(id,r);
1077  }
1078  idSkipZeroes(id);
1079}
1080
1081/// returns the ideals of initial terms
1082ideal id_Head(ideal h,const ring r)
1083{
1084  ideal m = idInit(IDELEMS(h),h->rank);
1085
1086  for (int i=IDELEMS(h)-1;i>=0; i--)
1087    if (h->m[i]!=NULL)
1088      m->m[i]=p_Head(h->m[i],r);
1089 
1090  return m;
1091}
1092
1093ideal id_Homogen(ideal h, int varnum,const ring r)
1094{
1095  ideal m = idInit(IDELEMS(h),h->rank);
1096  int i;
1097
1098  for (i=IDELEMS(h)-1;i>=0; i--)
1099  {
1100    m->m[i]=p_Homogen(h->m[i],varnum,r);
1101  }
1102  return m;
1103}
1104
1105/*------------------type conversions----------------*/
1106ideal id_Vec2Ideal(poly vec, const ring R)
1107{
1108   ideal result=idInit(1,1);
1109   omFree((ADDRESS)result->m);
1110   result->m=NULL; // remove later
1111   p_Vec2Polys(vec, &(result->m), &(IDELEMS(result)),R);
1112   return result;
1113}
1114
1115
1116// converts mat to module, destroys mat
1117ideal id_Matrix2Module(matrix mat, const ring R)
1118{
1119  int mc=MATCOLS(mat);
1120  int mr=MATROWS(mat);
1121  ideal result = idInit(mc,mr);
1122  int i,j,l;
1123  poly h;
1124  sBucket_pt bucket = sBucketCreate(R);
1125
1126  for(j=0;j<mc /*MATCOLS(mat)*/;j++) /* j is also index in result->m */
1127  {
1128    for (i=1;i<=mr /*MATROWS(mat)*/;i++)
1129    {
1130      h = MATELEM(mat,i,j+1);
1131      if (h!=NULL)
1132      {
1133        l=pLength(h);
1134        MATELEM(mat,i,j+1)=NULL;
1135        p_SetCompP(h,i, R);
1136        sBucket_Merge_p(bucket, h, l);
1137      }
1138    }
1139    sBucketClearMerge(bucket, &(result->m[j]), &l);
1140  }
1141  sBucketDestroy(&bucket);
1142
1143  // obachman: need to clean this up
1144  id_Delete((ideal*) &mat,R);
1145  return result;
1146}
1147
1148/*2
1149* converts a module into a matrix, destroyes the input
1150*/
1151matrix id_Module2Matrix(ideal mod, const ring R)
1152{
1153  matrix result = mpNew(mod->rank,IDELEMS(mod));
1154  long i; long cp;
1155  poly p,h;
1156
1157  for(i=0;i<IDELEMS(mod);i++)
1158  {
1159    p=pReverse(mod->m[i]);
1160    mod->m[i]=NULL;
1161    while (p!=NULL)
1162    {
1163      h=p;
1164      pIter(p);
1165      pNext(h)=NULL;
1166      cp = si_max((long)1,p_GetComp(h, R));     // if used for ideals too
1167      //cp = p_GetComp(h,R);
1168      p_SetComp(h,0,R);
1169      p_SetmComp(h,R);
1170#ifdef TEST
1171      if (cp>mod->rank)
1172      {
1173        Print("## inv. rank %ld -> %ld\n",mod->rank,cp);
1174        int k,l,o=mod->rank;
1175        mod->rank=cp;
1176        matrix d=mpNew(mod->rank,IDELEMS(mod));
1177        for (l=1; l<=o; l++)
1178        {
1179          for (k=1; k<=IDELEMS(mod); k++)
1180          {
1181            MATELEM(d,l,k)=MATELEM(result,l,k);
1182            MATELEM(result,l,k)=NULL;
1183          }
1184        }
1185        id_Delete((ideal *)&result,R);
1186        result=d;
1187      }
1188#endif
1189      MATELEM(result,cp,i+1) = p_Add_q(MATELEM(result,cp,i+1),h,R);
1190    }
1191  }
1192  // obachman 10/99: added the following line, otherwise memory leack!
1193  id_Delete(&mod,R);
1194  return result;
1195}
1196
1197matrix id_Module2formatedMatrix(ideal mod,int rows, int cols, const ring R)
1198{
1199  matrix result = mpNew(rows,cols);
1200  int i,cp,r=id_RankFreeModule(mod,R),c=IDELEMS(mod);
1201  poly p,h;
1202
1203  if (r>rows) r = rows;
1204  if (c>cols) c = cols;
1205  for(i=0;i<c;i++)
1206  {
1207    p=pReverse(mod->m[i]);
1208    mod->m[i]=NULL;
1209    while (p!=NULL)
1210    {
1211      h=p;
1212      pIter(p);
1213      pNext(h)=NULL;
1214      cp = p_GetComp(h,R);
1215      if (cp<=r)
1216      {
1217        p_SetComp(h,0,R);
1218        p_SetmComp(h,R);
1219        MATELEM(result,cp,i+1) = p_Add_q(MATELEM(result,cp,i+1),h,R);
1220      }
1221      else
1222        p_Delete(&h,R);
1223    }
1224  }
1225  id_Delete(&mod,R);
1226  return result;
1227}
1228
1229/*2
1230* substitute the n-th variable by the monomial e in id
1231* destroy id
1232*/
1233ideal  id_Subst(ideal id, int n, poly e, const ring r)
1234{
1235  int k=MATROWS((matrix)id)*MATCOLS((matrix)id);
1236  ideal res=(ideal)mpNew(MATROWS((matrix)id),MATCOLS((matrix)id));
1237
1238  res->rank = id->rank;
1239  for(k--;k>=0;k--)
1240  {
1241    res->m[k]=p_Subst(id->m[k],n,e,r);
1242    id->m[k]=NULL;
1243  }
1244  id_Delete(&id,r);
1245  return res;
1246}
1247
1248BOOLEAN id_HomModule(ideal m, ideal Q, intvec **w, const ring R)
1249{
1250  if (w!=NULL) *w=NULL;
1251  if ((Q!=NULL) && (!id_HomIdeal(Q,NULL,R))) return FALSE;
1252  if (idIs0(m))
1253  {
1254    if (w!=NULL) (*w)=new intvec(m->rank);
1255    return TRUE;
1256  }
1257
1258  long cmax=1,order=0,ord,* diff,diffmin=32000;
1259  int *iscom;
1260  int i;
1261  poly p=NULL;
1262  pFDegProc d;
1263  if (R->pLexOrder && (R->order[0]==ringorder_lp))
1264     d=p_Totaldegree;
1265  else
1266     d=R->pFDeg;
1267  int length=IDELEMS(m);
1268  poly* P=m->m;
1269  poly* F=(poly*)omAlloc(length*sizeof(poly));
1270  for (i=length-1;i>=0;i--)
1271  {
1272    p=F[i]=P[i];
1273    cmax=si_max(cmax,(long)p_MaxComp(p,R));
1274  }
1275  cmax++;
1276  diff = (long *)omAlloc0(cmax*sizeof(long));
1277  if (w!=NULL) *w=new intvec(cmax-1);
1278  iscom = (int *)omAlloc0(cmax*sizeof(int));
1279  i=0;
1280  while (i<=length)
1281  {
1282    if (i<length)
1283    {
1284      p=F[i];
1285      while ((p!=NULL) && (iscom[p_GetComp(p,R)]==0)) pIter(p);
1286    }
1287    if ((p==NULL) && (i<length))
1288    {
1289      i++;
1290    }
1291    else
1292    {
1293      if (p==NULL) /* && (i==length) */
1294      {
1295        i=0;
1296        while ((i<length) && (F[i]==NULL)) i++;
1297        if (i>=length) break;
1298        p = F[i];
1299      }
1300      //if (pLexOrder && (currRing->order[0]==ringorder_lp))
1301      //  order=pTotaldegree(p);
1302      //else
1303      //  order = p->order;
1304      //  order = pFDeg(p,currRing);
1305      order = d(p,R) +diff[p_GetComp(p,R)];
1306      //order += diff[pGetComp(p)];
1307      p = F[i];
1308//Print("Actual p=F[%d]: ",i);pWrite(p);
1309      F[i] = NULL;
1310      i=0;
1311    }
1312    while (p!=NULL)
1313    {
1314      if (R->pLexOrder && (R->order[0]==ringorder_lp))
1315        ord=p_Totaldegree(p,R);
1316      else
1317      //  ord = p->order;
1318        ord = R->pFDeg(p,R);
1319      if (iscom[p_GetComp(p,R)]==0)
1320      {
1321        diff[p_GetComp(p,R)] = order-ord;
1322        iscom[p_GetComp(p,R)] = 1;
1323/*
1324*PrintS("new diff: ");
1325*for (j=0;j<cmax;j++) Print("%d ",diff[j]);
1326*PrintLn();
1327*PrintS("new iscom: ");
1328*for (j=0;j<cmax;j++) Print("%d ",iscom[j]);
1329*PrintLn();
1330*Print("new set %d, order %d, ord %d, diff %d\n",pGetComp(p),order,ord,diff[pGetComp(p)]);
1331*/
1332      }
1333      else
1334      {
1335/*
1336*PrintS("new diff: ");
1337*for (j=0;j<cmax;j++) Print("%d ",diff[j]);
1338*PrintLn();
1339*Print("order %d, ord %d, diff %d\n",order,ord,diff[pGetComp(p)]);
1340*/
1341        if (order != (ord+diff[p_GetComp(p,R)]))
1342        {
1343          omFreeSize((ADDRESS) iscom,cmax*sizeof(int));
1344          omFreeSize((ADDRESS) diff,cmax*sizeof(long));
1345          omFreeSize((ADDRESS) F,length*sizeof(poly));
1346          delete *w;*w=NULL;
1347          return FALSE;
1348        }
1349      }
1350      pIter(p);
1351    }
1352  }
1353  omFreeSize((ADDRESS) iscom,cmax*sizeof(int));
1354  omFreeSize((ADDRESS) F,length*sizeof(poly));
1355  for (i=1;i<cmax;i++) (**w)[i-1]=(int)(diff[i]);
1356  for (i=1;i<cmax;i++)
1357  {
1358    if (diff[i]<diffmin) diffmin=diff[i];
1359  }
1360  if (w!=NULL)
1361  {
1362    for (i=1;i<cmax;i++)
1363    {
1364      (**w)[i-1]=(int)(diff[i]-diffmin);
1365    }
1366  }
1367  omFreeSize((ADDRESS) diff,cmax*sizeof(long));
1368  return TRUE;
1369}
1370
1371ideal id_Jet(ideal i,int d, const ring R)
1372{
1373  ideal r=idInit((i->nrows)*(i->ncols),i->rank);
1374  r->nrows = i-> nrows;
1375  r->ncols = i-> ncols;
1376  //r->rank = i-> rank;
1377 
1378  for(int k=(i->nrows)*(i->ncols)-1;k>=0; k--)
1379    r->m[k]=pp_Jet(i->m[k],d,R);
1380 
1381  return r;
1382}
1383
1384ideal id_JetW(ideal i,int d, intvec * iv, const ring R)
1385{
1386  ideal r=idInit(IDELEMS(i),i->rank);
1387  if (ecartWeights!=NULL)
1388  {
1389    WerrorS("cannot compute weighted jets now");
1390  }
1391  else
1392  {
1393    short *w=iv2array(iv,R);
1394    int k;
1395    for(k=0; k<IDELEMS(i); k++)
1396    {
1397      r->m[k]=pp_JetW(i->m[k],d,w,R);
1398    }
1399    omFreeSize((ADDRESS)w,(rVar(R)+1)*sizeof(short));
1400  }
1401  return r;
1402}
1403
1404/*3
1405* searches for the next unit in the components of the module arg and
1406* returns the first one;
1407*/
1408int id_ReadOutPivot(ideal arg,int* comp, const ring r)
1409{
1410  if (idIs0(arg)) return -1;
1411  int i=0,j, generator=-1;
1412  int rk_arg=arg->rank; //idRankFreeModule(arg);
1413  int * componentIsUsed =(int *)omAlloc((rk_arg+1)*sizeof(int));
1414  poly p;
1415
1416  while ((generator<0) && (i<IDELEMS(arg)))
1417  {
1418    memset(componentIsUsed,0,(rk_arg+1)*sizeof(int));
1419    p = arg->m[i];
1420    while (p!=NULL)
1421    {
1422      j = p_GetComp(p,r);
1423      if (componentIsUsed[j]==0)
1424      {
1425#ifdef HAVE_RINGS
1426        if (p_LmIsConstantComp(p,r) &&
1427            (!rField_is_Ring(r) || n_IsUnit(pGetCoeff(p),r->cf)))
1428        {
1429#else
1430        if (p_LmIsConstantComp(p,r))
1431        {
1432#endif
1433          generator = i;
1434          componentIsUsed[j] = 1;
1435        }
1436        else
1437        {
1438          componentIsUsed[j] = -1;
1439        }
1440      }
1441      else if (componentIsUsed[j]>0)
1442      {
1443        (componentIsUsed[j])++;
1444      }
1445      pIter(p);
1446    }
1447    i++;
1448  }
1449  i = 0;
1450  *comp = -1;
1451  for (j=0;j<=rk_arg;j++)
1452  {
1453    if (componentIsUsed[j]>0)
1454    {
1455      if ((*comp==-1) || (componentIsUsed[j]<i))
1456      {
1457        *comp = j;
1458        i= componentIsUsed[j];
1459      }
1460    }
1461  }
1462  omFree(componentIsUsed);
1463  return generator;
1464}
1465
1466#if 0
1467static void idDeleteComp(ideal arg,int red_comp)
1468{
1469  int i,j;
1470  poly p;
1471
1472  for (i=IDELEMS(arg)-1;i>=0;i--)
1473  {
1474    p = arg->m[i];
1475    while (p!=NULL)
1476    {
1477      j = pGetComp(p);
1478      if (j>red_comp)
1479      {
1480        pSetComp(p,j-1);
1481        pSetm(p);
1482      }
1483      pIter(p);
1484    }
1485  }
1486  (arg->rank)--;
1487}
1488#endif
1489
1490intvec * id_QHomWeight(ideal id, const ring r)
1491{
1492  poly head, tail;
1493  int k;
1494  int in=IDELEMS(id)-1, ready=0, all=0,
1495      coldim=rVar(r), rowmax=2*coldim;
1496  if (in<0) return NULL;
1497  intvec *imat=new intvec(rowmax+1,coldim,0);
1498
1499  do
1500  {
1501    head = id->m[in--];
1502    if (head!=NULL)
1503    {
1504      tail = pNext(head);
1505      while (tail!=NULL)
1506      {
1507        all++;
1508        for (k=1;k<=coldim;k++)
1509          IMATELEM(*imat,all,k) = p_GetExpDiff(head,tail,k,r);
1510        if (all==rowmax)
1511        {
1512          ivTriangIntern(imat, ready, all);
1513          if (ready==coldim)
1514          {
1515            delete imat;
1516            return NULL;
1517          }
1518        }
1519        pIter(tail);
1520      }
1521    }
1522  } while (in>=0);
1523  if (all>ready)
1524  {
1525    ivTriangIntern(imat, ready, all);
1526    if (ready==coldim)
1527    {
1528      delete imat;
1529      return NULL;
1530    }
1531  }
1532  intvec *result = ivSolveKern(imat, ready);
1533  delete imat;
1534  return result;
1535}
1536
1537BOOLEAN id_IsZeroDim(ideal I, const ring r)
1538{
1539  BOOLEAN *UsedAxis=(BOOLEAN *)omAlloc0(rVar(r)*sizeof(BOOLEAN));
1540  int i,n;
1541  poly po;
1542  BOOLEAN res=TRUE;
1543  for(i=IDELEMS(I)-1;i>=0;i--)
1544  {
1545    po=I->m[i];
1546    if ((po!=NULL) &&((n=p_IsPurePower(po,r))!=0)) UsedAxis[n-1]=TRUE;
1547  }
1548  for(i=rVar(r)-1;i>=0;i--)
1549  {
1550    if(UsedAxis[i]==FALSE) {res=FALSE; break;} // not zero-dim.
1551  }
1552  omFreeSize(UsedAxis,rVar(r)*sizeof(BOOLEAN));
1553  return res;
1554}
1555
1556void id_Normalize(ideal I,const ring r) /* for ideal/matrix */
1557{
1558  if (rField_has_simple_inverse(r)) return; /* Z/p, GF(p,n), R, long R/C */
1559  int i;
1560  for(i=I->nrows*I->ncols-1;i>=0;i--)
1561  {
1562    p_Normalize(I->m[i],r);
1563  }
1564}
1565
1566int id_MinDegW(ideal M,intvec *w, const ring r)
1567{
1568  int d=-1;
1569  for(int i=0;i<IDELEMS(M);i++)
1570  {
1571    if (M->m[i]!=NULL)
1572    {
1573      int d0=p_MinDeg(M->m[i],w,r);
1574      if(-1<d0&&((d0<d)||(d==-1)))
1575        d=d0;
1576    }
1577  }
1578  return d;
1579}
1580
1581// #include <kernel/clapsing.h>
1582
1583/*2
1584* transpose a module
1585*/
1586ideal id_Transp(ideal a, const ring rRing)
1587{
1588  int r = a->rank, c = IDELEMS(a);
1589  ideal b =  idInit(r,c);
1590
1591  for (int i=c; i>0; i--)
1592  {
1593    poly p=a->m[i-1];
1594    while(p!=NULL)
1595    {
1596      poly h=p_Head(p, rRing);
1597      int co=p_GetComp(h, rRing)-1;
1598      p_SetComp(h, i, rRing);
1599      p_Setm(h, rRing);
1600      b->m[co] = p_Add_q(b->m[co], h, rRing);
1601      pIter(p);
1602    }
1603  }
1604  return b;
1605}
1606
1607
1608
1609/*2
1610* The following is needed to compute the image of certain map used in
1611* the computation of cohomologies via BGG
1612* let M = { w_1, ..., w_k }, k = size(M) == ncols(M), n = nvars(currRing).
1613* assuming that nrows(M) <= m*n; the procedure computes:
1614* transpose(M) * transpose( var(1) I_m | ... | var(n) I_m ) :== transpose(module{f_1, ... f_k}),
1615* where f_i = \sum_{j=1}^{m} (w_i, v_j) gen(j),  (w_i, v_j) is a `scalar` multiplication.
1616* that is, if w_i = (a^1_1, ... a^1_m) | (a^2_1, ..., a^2_m) | ... | (a^n_1, ..., a^n_m) then
1617
1618  (a^1_1, ... a^1_m) | (a^2_1, ..., a^2_m) | ... | (a^n_1, ..., a^n_m)
1619*  var_1  ... var_1  |  var_2  ...  var_2  | ... |  var_n  ...  var(n)
1620*  gen_1  ... gen_m  |  gen_1  ...  gen_m  | ... |  gen_1  ...  gen_m
1621+ =>
1622  f_i =
1623
1624   a^1_1 * var(1) * gen(1) + ... + a^1_m * var(1) * gen(m) +
1625   a^2_1 * var(2) * gen(1) + ... + a^2_m * var(2) * gen(m) +
1626                             ...
1627   a^n_1 * var(n) * gen(1) + ... + a^n_m * var(n) * gen(m);
1628
1629   NOTE: for every f_i we run only ONCE along w_i saving partial sums into a temporary array of polys of size m
1630*/
1631ideal id_TensorModuleMult(const int m, const ideal M, const ring rRing)
1632{
1633// #ifdef DEBU
1634//  WarnS("tensorModuleMult!!!!");
1635
1636  assume(m > 0);
1637  assume(M != NULL);
1638
1639  const int n = rRing->N;
1640
1641  assume(M->rank <= m * n);
1642
1643  const int k = IDELEMS(M);
1644
1645  ideal idTemp =  idInit(k,m); // = {f_1, ..., f_k }
1646
1647  for( int i = 0; i < k; i++ ) // for every w \in M
1648  {
1649    poly pTempSum = NULL;
1650
1651    poly w = M->m[i];
1652
1653    while(w != NULL) // for each term of w...
1654    {
1655      poly h = p_Head(w, rRing);
1656
1657      const int  gen = p_GetComp(h, rRing); // 1 ...
1658
1659      assume(gen > 0);
1660      assume(gen <= n*m);
1661
1662      // TODO: write a formula with %, / instead of while!
1663      /*
1664      int c = gen;
1665      int v = 1;
1666      while(c > m)
1667      {
1668        c -= m;
1669        v++;
1670      }
1671      */
1672
1673      int cc = gen % m;
1674      if( cc == 0) cc = m;
1675      int vv = 1 + (gen - cc) / m;
1676
1677//      assume( cc == c );
1678//      assume( vv == v );
1679
1680      //  1<= c <= m
1681      assume( cc > 0 );
1682      assume( cc <= m );
1683
1684      assume( vv > 0 );
1685      assume( vv <= n );
1686
1687      assume( (cc + (vv-1)*m) == gen );
1688
1689      p_IncrExp(h, vv, rRing); // h *= var(j) && //      p_AddExp(h, vv, 1, rRing);
1690      p_SetComp(h, cc, rRing);
1691
1692      p_Setm(h, rRing);         // addjust degree after the previous steps!
1693
1694      pTempSum = p_Add_q(pTempSum, h, rRing); // it is slow since h will be usually put to the back of pTempSum!!!
1695
1696      pIter(w);
1697    }
1698
1699    idTemp->m[i] = pTempSum;
1700  }
1701
1702  // simplify idTemp???
1703
1704  ideal idResult = id_Transp(idTemp, rRing);
1705
1706  id_Delete(&idTemp, rRing);
1707
1708  return(idResult);
1709}
1710
1711ideal id_ChineseRemainder(ideal *xx, number *q, int rl, const ring r)
1712{
1713  int cnt=IDELEMS(xx[0])*xx[0]->nrows;
1714  ideal result=idInit(cnt,xx[0]->rank);
1715  result->nrows=xx[0]->nrows; // for lifting matrices
1716  result->ncols=xx[0]->ncols; // for lifting matrices
1717  int i,j;
1718  number *x=(number *)omAlloc(rl*sizeof(number));
1719  poly *p=(poly *)omAlloc(rl*sizeof(poly));
1720  CFArray inv_cache(rl);;
1721  for(i=cnt-1;i>=0;i--)
1722  {
1723    for(j=rl-1;j>=0;j--)
1724    {
1725      p[j]=xx[j]->m[i];
1726    }
1727    result->m[i]=p_ChineseRemainder(p,x,q,rl,inv_cache,r);
1728    for(j=rl-1;j>=0;j--)
1729    {
1730      xx[j]->m[i]=p[j];
1731    }
1732  }
1733  omFreeSize(p,rl*sizeof(poly));
1734  omFreeSize(x,rl*sizeof(number));
1735  for(i=rl-1;i>=0;i--) id_Delete(&(xx[i]),r);
1736  omFreeSize(xx,rl*sizeof(ideal));
1737  return result;
1738}
1739
1740void id_Shift(ideal M, int s, const ring r)
1741{
1742//  id_Test( M, r );
1743
1744//  assume( s >= 0 ); // negative is also possible // TODO: verify input ideal in such a case!?
1745 
1746  for(int i=IDELEMS(M)-1; i>=0;i--)
1747    p_Shift(&(M->m[i]),s,r);
1748 
1749  M->rank += s;
1750 
1751//  id_Test( M, r );
1752}
Note: See TracBrowser for help on using the repository browser.