source: git/Singular/ring.cc @ 5ecf042

spielwiese
Last change on this file since 5ecf042 was 5ecf042, checked in by Olaf Bachmann <obachman@…>, 23 years ago
* LIB: some categoy changes * libparse: added -c option * reimplementation of reing dpenendent options (put to ring->options) git-svn-id: file:///usr/local/Singular/svn/trunk@4952 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 90.8 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: ring.cc,v 1.151 2000-12-19 18:31:45 obachman Exp $ */
5
6/*
7* ABSTRACT - the interpreter related ring operations
8*/
9
10/* includes */
11#include <math.h>
12#include "mod2.h"
13#include "structs.h"
14#include "omalloc.h"
15#include "tok.h"
16#include "ipid.h"
17#include "polys.h"
18#include "numbers.h"
19#include "febase.h"
20#include "ipshell.h"
21#include "ipconv.h"
22#include "intvec.h"
23#include "longalg.h"
24#include "ffields.h"
25#include "subexpr.h"
26#include "ideals.h"
27#include "lists.h"
28#include "ring.h"
29#include "prCopy.h"
30#include "p_Procs.h"
31
32#define BITS_PER_LONG 8*SIZEOF_LONG
33
34static const char * const ringorder_name[] =
35{
36  " ?", //ringorder_no = 0,
37  "a", //ringorder_a,
38  "c", //ringorder_c,
39  "C", //ringorder_C,
40  "M", //ringorder_M,
41  "S", //ringorder_S,
42  "s", //ringorder_s,
43  "lp", //ringorder_lp,
44  "dp", //ringorder_dp,
45  "rp", //ringorder_rp,
46  "Dp", //ringorder_Dp,
47  "wp", //ringorder_wp,
48  "Wp", //ringorder_Wp,
49  "ls", //ringorder_ls,
50  "ds", //ringorder_ds,
51  "Ds", //ringorder_Ds,
52  "ws", //ringorder_ws,
53  "Ws", //ringorder_Ws,
54  "L", //ringorder_L,
55  "aa", //ringorder_aa
56  " _" //ringorder_unspec
57};
58
59static inline const char * rSimpleOrdStr(int ord)
60{
61  return ringorder_name[ord];
62}
63
64// unconditionally deletes fields in r
65static void rDelete(ring r);
66// set r->VarL_Size, r->VarL_Offset, r->VarL_LowIndex
67static void rSetVarL(ring r);
68// get r->divmask depending on bits per exponent
69static unsigned long rGetDivMask(int bits);
70// right-adjust r->VarOffset
71static void rRightAdjustVarOffset(ring r);
72
73/*0 implementation*/
74//BOOLEAN rField_is_R(ring r=currRing)
75//{
76//  if (r->ch== -1)
77//  {
78//    if (r->ch_flags==(short)0) return TRUE;
79//  }
80//  return FALSE;
81//}
82
83// internally changes the gloabl ring and resets the relevant
84// global variables:
85// complete == FALSE : only delete operations are enabled
86// complete == TRUE  : full reset of all variables
87void rChangeCurrRing(ring r)
88{
89  /*------------ set global ring vars --------------------------------*/
90  currRing = r;
91  currQuotient=NULL;
92  if (r != NULL)
93  {
94    rTest(r);
95    /*------------ set global ring vars --------------------------------*/
96    currQuotient=r->qideal;
97
98    /*------------ global variables related to coefficients ------------*/
99    nSetChar(r);
100
101    /*------------ global variables related to polys -------------------*/
102    pSetGlobals(r);
103
104    /*------------ set naMinimalPoly -----------------------------------*/
105    if (r->minpoly!=NULL)
106    {
107      naMinimalPoly=((lnumber)r->minpoly)->z;
108    }
109  }
110}
111
112void rSetHdl(idhdl h)
113{
114  int i;
115  ring rg = NULL;
116  if (h!=NULL)
117  {
118    rg = IDRING(h);
119    omCheckAddrSize((ADDRESS)h,sizeof(idrec));
120    if (IDID(h))  // OB: ????
121      omCheckAddr((ADDRESS)IDID(h));
122    rTest(rg);
123  }
124
125  // clean up history
126    if (((sLastPrinted.rtyp>BEGIN_RING) && (sLastPrinted.rtyp<END_RING))
127        || ((sLastPrinted.rtyp==LIST_CMD)&&(lRingDependend((lists)sLastPrinted.data))))
128    {
129      sLastPrinted.CleanUp();
130      memset(&sLastPrinted,0,sizeof(sleftv));
131    }
132
133   /*------------ change the global ring -----------------------*/
134  rChangeCurrRing(rg);
135  currRingHdl = h;
136}
137
138idhdl rDefault(char *s)
139{
140  idhdl tmp=NULL;
141
142  if (s!=NULL) tmp = enterid(s, myynest, RING_CMD, &IDROOT);
143  if (tmp==NULL) return NULL;
144
145  if (ppNoether!=NULL) pDelete(&ppNoether);
146  if (((sLastPrinted.rtyp>BEGIN_RING) && (sLastPrinted.rtyp<END_RING)) ||
147      ((sLastPrinted.rtyp==LIST_CMD)&&(lRingDependend((lists)sLastPrinted.data))))
148
149  {
150    sLastPrinted.CleanUp();
151    memset(&sLastPrinted,0,sizeof(sleftv));
152  }
153
154  ring r = IDRING(tmp);
155
156  r->ch    = 32003;
157  r->N     = 3;
158  /*r->P     = 0; Alloc0 in idhdl::set, ipid.cc*/
159  /*names*/
160  r->names = (char **) omAlloc0(3 * sizeof(char_ptr));
161  r->names[0]  = omStrDup("x");
162  r->names[1]  = omStrDup("y");
163  r->names[2]  = omStrDup("z");
164  /*weights: entries for 3 blocks: NULL*/
165  r->wvhdl = (int **)omAlloc0(3 * sizeof(int_ptr));
166  /*order: dp,C,0*/
167  r->order = (int *) omAlloc(3 * sizeof(int *));
168  r->block0 = (int *)omAlloc0(3 * sizeof(int *));
169  r->block1 = (int *)omAlloc0(3 * sizeof(int *));
170  /* ringorder dp for the first block: var 1..3 */
171  r->order[0]  = ringorder_dp;
172  r->block0[0] = 1;
173  r->block1[0] = 3;
174  /* ringorder C for the second block: no vars */
175  r->order[1]  = ringorder_C;
176  /* the last block: everything is 0 */
177  r->order[2]  = 0;
178  /*polynomial ring*/
179  r->OrdSgn    = 1;
180
181  /* complete ring intializations */
182  rComplete(r);
183  rSetHdl(tmp);
184  return currRingHdl;
185}
186
187ring rDefault(int ch, int N, char **n)
188{
189  ring r=(ring) omAlloc0Bin(sip_sring_bin);
190  r->ch    = ch;
191  r->N     = N;
192  /*r->P     = 0; Alloc0 */
193  /*names*/
194  r->names = (char **) omAlloc0(N * sizeof(char_ptr));
195  int i;
196  for(i=0;i<N;i++)
197  { 
198    r->names[i]  = omStrDup(n[i]);
199  } 
200  /*weights: entries for 2 blocks: NULL*/
201  r->wvhdl = (int **)omAlloc0(2 * sizeof(int_ptr));
202  /*order: lp,0*/
203  r->order = (int *) omAlloc(2* sizeof(int *));
204  r->block0 = (int *)omAlloc0(2 * sizeof(int *));
205  r->block1 = (int *)omAlloc0(2 * sizeof(int *));
206  /* ringorder dp for the first block: var 1..N */
207  r->order[0]  = ringorder_lp;
208  r->block0[0] = 1;
209  r->block1[0] = N;
210  /* the last block: everything is 0 */
211  r->order[1]  = 0;
212  /*polynomial ring*/
213  r->OrdSgn    = 1;
214
215  /* complete ring intializations */
216  rComplete(r);
217  return r;
218}
219
220///////////////////////////////////////////////////////////////////////////
221//
222// rInit: define a new ring from sleftv's
223//
224
225/////////////////////////////
226// Auxillary functions
227//
228
229// check intvec, describing the ordering
230static BOOLEAN rCheckIV(intvec *iv)
231{
232  if ((iv->length()!=2)&&(iv->length()!=3))
233  {
234    WerrorS("weights only for orderings wp,ws,Wp,Ws,a,M");
235    return TRUE;
236  }
237  return FALSE;
238}
239
240static int rTypeOfMatrixOrder(intvec * order)
241{
242  int i=0,j,typ=1;
243  int sz = (int)sqrt((double)(order->length()-2));
244
245  while ((i<sz) && (typ==1))
246  {
247    j=0;
248    while ((j<sz) && ((*order)[j*sz+i+2]==0)) j++;
249    if (j>=sz)
250    {
251      typ = 0;
252      WerrorS("Matrix order not complete");
253    }
254    else if ((*order)[j*sz+i+2]<0)
255      typ = -1;
256    else
257      i++;
258  }
259  return typ;
260}
261
262// set R->order, R->block, R->wvhdl, r->OrdSgn from sleftv
263static BOOLEAN rSleftvOrdering2Ordering(sleftv *ord, ring R)
264{
265  int last = 0, o=0, n = 1, i=0, typ = 1, j;
266  sleftv *sl = ord;
267
268  // determine nBlocks
269  while (sl!=NULL)
270  {
271    intvec *iv = (intvec *)(sl->data);
272    if (((*iv)[1]==ringorder_c)||((*iv)[1]==ringorder_C)) i++;
273    else if ((*iv)[1]==ringorder_L)
274    {
275      R->bitmask=(*iv)[2];
276      n--;
277    }
278    else if ((*iv)[1]!=ringorder_a) o++;
279    n++;
280    sl=sl->next;
281  }
282  // check whether at least one real ordering
283  if (o==0)
284  {
285    WerrorS("invalid combination of orderings");
286    return TRUE;
287  }
288  // if no c/C ordering is given, increment n
289  if (i==0) n++;
290  else if (i != 1)
291  {
292    // throw error if more than one is given
293    WerrorS("more than one ordering c/C specified");
294    return TRUE;
295  }
296
297  // initialize fields of R
298  R->order=(int *)omAlloc0(n*sizeof(int));
299  R->block0=(int *)omAlloc0(n*sizeof(int));
300  R->block1=(int *)omAlloc0(n*sizeof(int));
301  R->wvhdl=(int**)omAlloc0(n*sizeof(int_ptr));
302
303  // init order, so that rBlocks works correctly
304  for (j=0; j < n-1; j++)
305    R->order[j] = (int) ringorder_unspec;
306  // set last _C order, if no c/C order was given
307  if (i == 0) R->order[n-2] = ringorder_C;
308
309  /* init orders */
310  sl=ord;
311  n=-1;
312  while (sl!=NULL)
313  {
314    intvec *iv;
315    iv = (intvec *)(sl->data);
316    if ((*iv)[1]!=ringorder_L)
317    {
318      n++;
319
320      /* the format of an ordering:
321       *  iv[0]: factor
322       *  iv[1]: ordering
323       *  iv[2..end]: weights
324       */
325      R->order[n] = (*iv)[1];
326      switch ((*iv)[1])
327      {
328          case ringorder_ws:
329          case ringorder_Ws:
330            typ=-1;
331          case ringorder_wp:
332          case ringorder_Wp:
333            R->wvhdl[n]=(int*)omAlloc((iv->length()-1)*sizeof(int));
334            for (i=2; i<iv->length(); i++)
335              R->wvhdl[n][i-2] = (*iv)[i];
336            R->block0[n] = last+1;
337            last += iv->length()-2;
338            R->block1[n] = last;
339            break;
340          case ringorder_ls:
341          case ringorder_ds:
342          case ringorder_Ds:
343            typ=-1;
344          case ringorder_lp:
345          case ringorder_dp:
346          case ringorder_Dp:
347          case ringorder_rp:
348            R->block0[n] = last+1;
349            if (iv->length() == 3) last+=(*iv)[2];
350            else last += (*iv)[0];
351            R->block1[n] = last;
352            if (rCheckIV(iv)) return TRUE;
353            break;
354          case ringorder_S:
355          case ringorder_c:
356          case ringorder_C:
357            if (rCheckIV(iv)) return TRUE;
358            break;
359          case ringorder_aa:
360          case ringorder_a:
361            R->block0[n] = last+1;
362            R->block1[n] = last + iv->length() - 2;
363            R->wvhdl[n] = (int*)omAlloc((iv->length()-1)*sizeof(int));
364            for (i=2; i<iv->length(); i++)
365            {
366              R->wvhdl[n][i-2]=(*iv)[i];
367              if ((*iv)[i]<0) typ=-1;
368            }
369            break;
370          case ringorder_M:
371          {
372            int Mtyp=rTypeOfMatrixOrder(iv);
373            if (Mtyp==0) return TRUE;
374            if (Mtyp==-1) typ = -1;
375
376            R->wvhdl[n] =( int *)omAlloc((iv->length()-1)*sizeof(int));
377            for (i=2; i<iv->length();i++)
378              R->wvhdl[n][i-2]=(*iv)[i];
379
380            R->block0[n] = last+1;
381            last += (int)sqrt((double)(iv->length()-2));
382            R->block1[n] = last;
383            break;
384          }
385
386          case ringorder_no:
387            R->order[n] = ringorder_unspec;
388            return TRUE;
389
390          default:
391            Werror("Internal Error: Unknown ordering %d", (*iv)[1]);
392            R->order[n] = ringorder_unspec;
393            return TRUE;
394      }
395    }
396    sl=sl->next;
397  }
398
399  // check for complete coverage
400  if ((R->order[n]==ringorder_c) ||  (R->order[n]==ringorder_C)) n--;
401  if (R->block1[n] != R->N)
402  {
403    if (((R->order[n]==ringorder_dp) ||
404         (R->order[n]==ringorder_ds) ||
405         (R->order[n]==ringorder_Dp) ||
406         (R->order[n]==ringorder_Ds) ||
407         (R->order[n]==ringorder_rp) ||
408         (R->order[n]==ringorder_lp) ||
409         (R->order[n]==ringorder_ls))
410        &&
411        R->block0[n] <= R->N)
412    {
413      R->block1[n] = R->N;
414    }
415    else
416    {
417      Werror("mismatch of number of vars (%d) and ordering (%d vars)",
418             R->N,R->block1[n]);
419      return TRUE;
420    }
421  }
422  R->OrdSgn = typ;
423  return FALSE;
424}
425
426// get array of strings from list of sleftv's
427static BOOLEAN rSleftvList2StringArray(sleftv* sl, char** p)
428{
429
430  while(sl!=NULL)
431  {
432    if (sl->Name() == sNoName)
433    {
434      if (sl->Typ()==POLY_CMD)
435      {
436        sleftv s_sl;
437        iiConvert(POLY_CMD,ANY_TYPE,-1,sl,&s_sl);
438        if (s_sl.Name() != sNoName)
439          *p = omStrDup(s_sl.Name());
440        else
441          *p = NULL;
442        sl->next = s_sl.next;
443        s_sl.next = NULL;
444        s_sl.CleanUp();
445        if (*p == NULL) return TRUE;
446      }
447      else
448        return TRUE;
449    }
450    else
451      *p = omStrDup(sl->Name());
452    p++;
453    sl=sl->next;
454  }
455  return FALSE;
456}
457
458
459////////////////////
460//
461// rInit itself:
462//
463// INPUT:  s: name, pn: ch & parameter (names), rv: variable (names)
464//         ord: ordering
465// RETURN: currRingHdl on success
466//         NULL        on error
467// NOTE:   * makes new ring to current ring, on success
468//         * considers input sleftv's as read-only
469//idhdl rInit(char *s, sleftv* pn, sleftv* rv, sleftv* ord)
470ring rInit(sleftv* pn, sleftv* rv, sleftv* ord)
471{
472  int ch;
473  int float_len=0;
474  ring R = NULL;
475  idhdl tmp = NULL;
476  BOOLEAN ffChar=FALSE;
477  int typ = 1;
478
479  /* ch -------------------------------------------------------*/
480  // get ch of ground field
481  int numberOfAllocatedBlocks;
482
483  if (pn->Typ()==INT_CMD)
484  {
485    ch=(int)pn->Data();
486  }
487  else if ((pn->name != NULL)
488  && ((strcmp(pn->name,"real")==0) || (strcmp(pn->name,"complex")==0)))
489  {
490    BOOLEAN complex_flag=(strcmp(pn->name,"complex")==0);
491    ch=-1;
492    if ((pn->next!=NULL) && (pn->next->Typ()==INT_CMD))
493    {
494      float_len=(int)pn->next->Data();
495      pn=pn->next;
496    }
497    if ((pn->next==NULL) && complex_flag)
498    {
499      pn->next=(leftv)omAlloc0Bin(sleftv_bin);
500      pn->next->name=omStrDup("i");
501    }
502  }
503  else
504  {
505    Werror("Wrong ground field specification");
506    goto rInitError;
507  }
508  pn=pn->next;
509
510  int l, last;
511  sleftv * sl;
512  /*every entry in the new ring is initialized to 0*/
513
514  /* characteristic -----------------------------------------------*/
515  /* input: 0 ch=0 : Q     parameter=NULL    ffChar=FALSE   ch_flags
516   *         0    1 : Q(a,...)        *names         FALSE
517   *         0   -1 : R               NULL           FALSE  0
518   *         0   -1 : R               NULL           FALSE  prec. >6
519   *         0   -1 : C               *names         FALSE  prec. 0..?
520   *         p    p : Fp              NULL           FALSE
521   *         p   -p : Fp(a)           *names         FALSE
522   *         q    q : GF(q=p^n)       *names         TRUE
523  */
524  if (ch!=-1)
525  {
526    int l = 0;
527
528    if (ch!=0 && (ch<2) || (ch > 32003))
529    {
530      Warn("%d is invalid characteristic of ground field. 32003 is used.", ch);
531      ch=32003;
532    }
533    // load fftable, if necessary
534    if (pn!=NULL)
535    {
536      while ((ch!=fftable[l]) && (fftable[l])) l++;
537      if (fftable[l]==0) ch = IsPrime(ch);
538      else
539      {
540        char *m[1]={(char *)sNoName};
541        nfSetChar(ch,m);
542        if (errorreported) goto rInitError;
543        else ffChar=TRUE;
544      }
545    }
546    else
547      ch = IsPrime(ch);
548  }
549  // allocated ring and set ch
550  R = (ring) omAlloc0Bin(sip_sring_bin);
551  R->ch = ch;
552  if (ch == -1)
553  {
554    R->ch_flags= min(float_len,32767);
555  }
556
557  /* parameter -------------------------------------------------------*/
558  if (pn!=NULL)
559  {
560    R->P=pn->listLength();
561    //if ((ffChar|| (ch == 1)) && (R->P > 1))
562    if ((R->P > 1) && (ffChar || (ch == -1)))
563    {
564      WerrorS("too many parameters");
565      goto rInitError;
566    }
567    R->parameter=(char**)omAlloc0(R->P*sizeof(char_ptr));
568    if (rSleftvList2StringArray(pn, R->parameter))
569    {
570      WerrorS("parameter expected");
571      goto rInitError;
572    }
573    if (ch>1 && !ffChar) R->ch=-ch;
574    else if (ch==0) R->ch=1;
575  }
576  else if (ffChar)
577  {
578    WerrorS("need one parameter");
579    goto rInitError;
580  }
581  /* post-processing of field description */
582  // we have short reals, but no short complex
583  if ((R->ch == - 1)
584  && (R->parameter !=NULL)
585  && (R->ch_flags < SHORT_REAL_LENGTH))
586    R->ch_flags = SHORT_REAL_LENGTH;
587
588  /* names and number of variables-------------------------------------*/
589  R->N = rv->listLength();
590  R->names   = (char **)omAlloc0(R->N * sizeof(char_ptr));
591  if (rSleftvList2StringArray(rv, R->names))
592  {
593    WerrorS("name of ring variable expected");
594    goto rInitError;
595  }
596
597  /* check names and parameters for conflicts ------------------------- */
598  {
599    int i,j;
600    for(i=0;i<R->P; i++)
601    {
602      for(j=0;j<R->N;j++)
603      {
604        if (strcmp(R->parameter[i],R->names[j])==0)
605        {
606          Werror("parameter %d conflicts with variable %d",i+1,j+1);
607          goto rInitError;
608        }
609      }
610    }
611  }
612  /* ordering -------------------------------------------------------------*/
613  if (rSleftvOrdering2Ordering(ord, R))
614    goto rInitError;
615
616  // Complete the initialization
617  if (rComplete(R,1))
618    goto rInitError;
619
620  rTest(R);
621
622  // try to enter the ring into the name list
623  // need to clean up sleftv here, before this ring can be set to
624  // new currRing or currRing can be killed beacuse new ring has
625  // same name
626  if (pn != NULL) pn->CleanUp();
627  if (rv != NULL) rv->CleanUp();
628  if (ord != NULL) ord->CleanUp();
629  //if ((tmp = enterid(s, myynest, RING_CMD, &IDROOT))==NULL)
630  //  goto rInitError;
631
632  //memcpy(IDRING(tmp),R,sizeof(*R));
633  // set current ring
634  //omFreeBin(R,  ip_sring_bin);
635  //return tmp;
636  return R;
637
638  // error case:
639  rInitError:
640  if  (R != NULL) rDelete(R);
641  if (pn != NULL) pn->CleanUp();
642  if (rv != NULL) rv->CleanUp();
643  if (ord != NULL) ord->CleanUp();
644  return NULL;
645}
646
647/*2
648 * set a new ring from the data:
649 s: name, chr: ch, varnames: rv, ordering: ord, typ: typ
650 */
651
652int r_IsRingVar(char *n, ring r)
653{
654  if ((r!=NULL) && (r->names!=NULL))
655  {
656    for (int i=0; i<r->N; i++)
657    {
658      if (r->names[i]==NULL) return -1;
659      if (strcmp(n,r->names[i]) == 0) return (int)i;
660    }
661  }
662  return -1;
663}
664
665
666void rWrite(ring r)
667{
668  if ((r==NULL)||(r->order==NULL))
669    return; /*to avoid printing after errors....*/
670
671  int nblocks=rBlocks(r);
672
673  // omCheckAddrSize(r,sizeof(ip_sring));
674  omCheckAddrSize(r->order,nblocks*sizeof(int));
675  omCheckAddrSize(r->block0,nblocks*sizeof(int));
676  omCheckAddrSize(r->block1,nblocks*sizeof(int));
677  omCheckAddrSize(r->wvhdl,nblocks*sizeof(int_ptr));
678  omCheckAddrSize(r->names,r->N*sizeof(char_ptr));
679
680
681  nblocks--;
682
683
684  if (rField_is_GF(r))
685  {
686    Print("//   # ground field : %d\n",rInternalChar(r));
687    Print("//   primitive element : %s\n", r->parameter[0]);
688    if (r==currRing)
689    {
690      StringSetS("//   minpoly        : ");
691      nfShowMipo();PrintS(StringAppendS("\n"));
692    }
693  }
694  else
695  {
696    PrintS("//   characteristic : ");
697    if ( rField_is_R(r) )             PrintS("0 (real)\n");  /* R */
698    else if ( rField_is_long_R(r) )
699      Print("0 (real:%d digits)\n",r->ch_flags);  /* long R */
700    else if ( rField_is_long_C(r) )
701      Print("0 (complex:%d digits)\n",r->ch_flags);  /* long C */
702    else
703      Print ("%d\n",rChar(r)); /* Fp(a) */
704    if (r->parameter!=NULL)
705    {
706      Print ("//   %d parameter    : ",rPar(r));
707      char **sp=r->parameter;
708      int nop=0;
709      while (nop<rPar(r))
710      {
711        PrintS(*sp);
712        PrintS(" ");
713        sp++; nop++;
714      }
715      PrintS("\n//   minpoly        : ");
716      if ( rField_is_long_C(r) )
717      {
718        // i^2+1:
719        Print("(%s^2+1)\n",r->parameter[0]);
720      }
721      else if (r->minpoly==NULL)
722      {
723        PrintS("0\n");
724      }
725      else if (r==currRing)
726      {
727        StringSetS(""); nWrite(r->minpoly); PrintS(StringAppendS("\n"));
728      }
729      else
730      {
731        PrintS("...\n");
732      }
733    }
734  }
735  Print("//   number of vars : %d",r->N);
736
737  //for (nblocks=0; r->order[nblocks]; nblocks++);
738  nblocks=rBlocks(r)-1;
739
740  for (int l=0, nlen=0 ; l<nblocks; l++)
741  {
742    int i;
743    Print("\n//        block %3d : ",l+1);
744
745    Print("ordering %s", rSimpleOrdStr(r->order[l]));
746
747    if ((r->order[l] >= ringorder_lp)
748    ||(r->order[l] == ringorder_M)
749    ||(r->order[l] == ringorder_a)   
750    ||(r->order[l] == ringorder_aa))
751    {
752      PrintS("\n//                  : names    ");
753      for (i = r->block0[l]-1; i<r->block1[l]; i++)
754      {
755        nlen = strlen(r->names[i]);
756        Print("%s ",r->names[i]);
757      }
758    }
759#ifndef NDEBUG
760    else if (r->order[l] == ringorder_s)
761    {
762      Print("  syzcomp at %d",r->typ[l].data.syz.limit);
763    }
764#endif
765
766    if (r->wvhdl[l]!=NULL)
767    {
768      for (int j= 0;
769           j<(r->block1[l]-r->block0[l]+1)*(r->block1[l]-r->block0[l]+1);
770           j+=i)
771      {
772        PrintS("\n//                  : weights  ");
773        for (i = 0; i<=r->block1[l]-r->block0[l]; i++)
774        {
775          Print("%*d " ,nlen,r->wvhdl[l][i+j],i+j);
776        }
777        if (r->order[l]!=ringorder_M) break;
778      }
779    }
780  }
781  if (r->qideal!=NULL)
782  {
783    PrintS("\n// quotient ring from ideal");
784    if (r==currRing)
785    {
786      PrintLn();
787      iiWriteMatrix((matrix)r->qideal,"_",1);
788    }
789    else PrintS(" ...");
790  }
791}
792
793static void rDelete(ring r)
794{
795  int i, j;
796
797  if (r == NULL) return;
798
799  rUnComplete(r);
800  // delete order stuff
801  if (r->order != NULL)
802  {
803    i=rBlocks(r);
804    assume(r->block0 != NULL && r->block1 != NULL && r->wvhdl != NULL);
805    // delete order
806    omFreeSize((ADDRESS)r->order,i*sizeof(int));
807    omFreeSize((ADDRESS)r->block0,i*sizeof(int));
808    omFreeSize((ADDRESS)r->block1,i*sizeof(int));
809    // delete weights
810    for (j=0; j<i; j++)
811    {
812      if (r->wvhdl[j]!=NULL)
813        omFree(r->wvhdl[j]);
814    }
815    omFreeSize((ADDRESS)r->wvhdl,i*sizeof(short *));
816  }
817  else
818  {
819    assume(r->block0 == NULL && r->block1 == NULL && r->wvhdl == NULL);
820  }
821
822  // delete varnames
823  if(r->names!=NULL)
824  {
825    for (i=0; i<r->N; i++)
826    {
827      if (r->names[i] != NULL) omFree((ADDRESS)r->names[i]);
828    }
829    omFreeSize((ADDRESS)r->names,r->N*sizeof(char_ptr));
830  }
831
832  // delete parameter
833  if (r->parameter!=NULL)
834  {
835    char **s=r->parameter;
836    j = 0;
837    while (j < rPar(r))
838    {
839      if (*s != NULL) omFree((ADDRESS)*s);
840      s++;
841      j++;
842    }
843    omFreeSize((ADDRESS)r->parameter,rPar(r)*sizeof(char_ptr));
844  }
845  omFreeBin(r, ip_sring_bin);
846}
847
848void rKill(ring r)
849{
850  if ((r->ref<=0)&&(r->order!=NULL))
851  {
852#ifdef RDEBUG
853    if (traceit &TRACE_SHOW_RINGS) Print("kill ring %x\n",r);
854#endif
855    if (r==currRing)
856    {
857      if (r->qideal!=NULL)
858      {
859        idDelete(&r->qideal);
860        r->qideal=NULL;
861        currQuotient=NULL;
862      }
863      if (ppNoether!=NULL) pDelete(&ppNoether);
864      if (((sLastPrinted.rtyp>BEGIN_RING) && (sLastPrinted.rtyp<END_RING)) ||
865          ((sLastPrinted.rtyp==LIST_CMD)&&(lRingDependend((lists)sLastPrinted.data))))
866      {
867        sLastPrinted.CleanUp();
868        memset(&sLastPrinted,0,sizeof(sleftv));
869      }
870      currRing=NULL;
871      currRingHdl=NULL;
872    }
873    else if (r->qideal!=NULL)
874    {
875      id_Delete(&r->qideal, r);
876      r->qideal = NULL;
877    }
878    nKillChar(r);
879    int i=1;
880    int j;
881    int *pi=r->order;
882#ifdef USE_IILOCALRING
883    for (j=0;j<iiRETURNEXPR_len;j++)
884    {
885      if (iiLocalRing[j]==r)
886      {
887        if (j<myynest) Warn("killing the basering for level %d",j);
888        iiLocalRing[j]=NULL;
889      }
890    }
891#else /* USE_IILOCALRING */
892    {
893      namehdl nshdl = namespaceroot;
894
895      for(nshdl=namespaceroot; nshdl->isroot != TRUE; nshdl = nshdl->next) {
896        //Print("NSstack: %s:%d, nesting=%d\n", nshdl->name, nshdl->lev, nshdl->myynest);
897        if (nshdl->currRing==r)
898        {
899          if (nshdl->myynest<myynest)
900//            Warn("killing the basering for level %d/%d",nshdl->lev,nshdl->myynest);
901          Warn("killing the basering for level %d",nshdl->myynest);
902          nshdl->currRing=NULL;
903        }
904      }
905      if (nshdl->currRing==r)
906      {
907        //Print("NSstack: %s:%d, nesting=%d\n", nshdl->name, nshdl->lev, nshdl->myynest);
908        if (nshdl->myynest<myynest)
909//          Warn("killing the basering for level %d/%d",nshdl->lev,nshdl->myynest);
910          Warn("killing the basering for level %d",nshdl->myynest);
911        nshdl->currRing=NULL;
912      }
913    }
914#endif /* USE_IILOCALRING */
915
916    rDelete(r);
917    return;
918  }
919  r->ref--;
920}
921
922void rKill(idhdl h)
923{
924#ifndef HAVE_NAMESPACES1
925  ring r = IDRING(h);
926  if (r!=NULL) rKill(r);
927  if (h==currRingHdl)
928  {
929#ifdef HAVE_NAMESPACES
930    namehdl nsHdl = namespaceroot;
931    while(nsHdl!=NULL) {
932      currRingHdl=NSROOT(nsHdl);
933#else /* HAVE_NAMESPACES */
934      currRingHdl=IDROOT;
935#endif /* HAVE_NAMESPACES */
936      while (currRingHdl!=NULL)
937      {
938        if ((currRingHdl!=h)
939            && (IDTYP(currRingHdl)==IDTYP(h))
940            && (h->data.uring==currRingHdl->data.uring))
941          break;
942        currRingHdl=IDNEXT(currRingHdl);
943      }
944#ifdef HAVE_NAMESPACES
945      if ((currRingHdl != NULL) && (currRingHdl!=h)
946          && (IDTYP(currRingHdl)==IDTYP(h))
947          && (h->data.uring==currRingHdl->data.uring))
948        break;
949      nsHdl = nsHdl->next;
950    }
951#endif /* HAVE_NAMESPACES */
952  }
953#else
954    if(currRingHdl==NULL)
955    {
956      namehdl ns = namespaceroot;
957      BOOLEAN found=FALSE;
958
959      while(!ns->isroot)
960      {
961        currRingHdl=NSROOT(namespaceroot->next);
962        while (currRingHdl!=NULL)
963        {
964          if ((currRingHdl!=h)
965              && (IDTYP(currRingHdl)==IDTYP(h))
966              && (h->data.uring==currRingHdl->data.uring))
967          { found=TRUE; break; }
968
969          currRingHdl=IDNEXT(currRingHdl);
970        }
971        if(found) break;
972        ns=IDNEXT(ns);
973      }
974    }
975    if(currRingHdl == NULL || IDRING(h) != IDRING(currRingHdl))
976    {
977      currRingHdl = namespaceroot->currRingHdl;
978
979/*      PrintS("Running rFind()\n");
980      currRingHdl = rFindHdl(IDRING(h), NULL, NULL);
981      if(currRingHdl == NULL)
982      {
983        PrintS("rFind()return 0\n");
984      }
985      else
986      {
987        PrintS("Huppi rfind return an currRingHDL\n");
988        Print("%x, %x\n", IDRING(h),IDRING(currRingHdl) );
989      }
990*/
991    }
992    else
993    {
994      //PrintS("Huppi found an currRingHDL\n");
995      //Print("%x, %x\n", IDRING(h),IDRING(currRingHdl) );
996
997    }
998#endif /* HAVE_NAMESPACES */
999}
1000
1001idhdl rFindHdl(ring r, idhdl n, idhdl w)
1002{
1003#ifdef HAVE_NAMESPACES
1004  idhdl h;
1005  namehdl ns = namespaceroot;
1006
1007  while(!ns->isroot) {
1008    h = NSROOT(ns);
1009    if(w != NULL) h = w;
1010    while (h!=NULL)
1011    {
1012      if (((IDTYP(h)==RING_CMD)||(IDTYP(h)==QRING_CMD))
1013          && (h->data.uring==r)
1014          && (h!=n))
1015        return h;
1016      h=IDNEXT(h);
1017    }
1018    ns = ns->next;
1019  }
1020  h = NSROOT(ns);
1021  if(w != NULL) h = w;
1022  while (h!=NULL)
1023  {
1024    if (((IDTYP(h)==RING_CMD)||(IDTYP(h)==QRING_CMD))
1025        && (h->data.uring==r)
1026        && (h!=n))
1027      return h;
1028    h=IDNEXT(h);
1029  }
1030#if 0
1031  if(namespaceroot->isroot) h = IDROOT;
1032  else h = NSROOT(namespaceroot->next);
1033  if(w != NULL) h = w;
1034  while (h!=NULL)
1035  {
1036    if (((IDTYP(h)==RING_CMD)||(IDTYP(h)==QRING_CMD))
1037        && (h->data.uring==r)
1038        && (h!=n))
1039      return h;
1040    h=IDNEXT(h);
1041  }
1042#endif
1043#else
1044  idhdl h=IDROOT;
1045  if(w != NULL) h = w;
1046  while (h!=NULL)
1047  {
1048    if (((IDTYP(h)==RING_CMD)||(IDTYP(h)==QRING_CMD))
1049        && (h->data.uring==r)
1050        && (h!=n))
1051      return h;
1052    h=IDNEXT(h);
1053  }
1054#endif
1055  return NULL;
1056}
1057
1058int rOrderName(char * ordername)
1059{
1060  int order=ringorder_unspec;
1061  while (order!= 0)
1062  {
1063    if (strcmp(ordername,rSimpleOrdStr(order))==0)
1064      break;
1065    order--;
1066  }
1067  if (order==0) Werror("wrong ring order `%s`",ordername);
1068  omFree((ADDRESS)ordername);
1069  return order;
1070}
1071
1072char * rOrdStr(ring r)
1073{
1074  int nblocks,l,i;
1075
1076  for (nblocks=0; r->order[nblocks]; nblocks++);
1077  nblocks--;
1078
1079  StringSetS("");
1080  for (l=0; ; l++)
1081  {
1082    StringAppend((char *)rSimpleOrdStr(r->order[l]));
1083    if ((r->order[l] != ringorder_c) && (r->order[l] != ringorder_C))
1084    {
1085      if (r->wvhdl[l]!=NULL)
1086      {
1087        StringAppendS("(");
1088        for (int j= 0;
1089             j<(r->block1[l]-r->block0[l]+1)*(r->block1[l]-r->block0[l]+1);
1090             j+=i+1)
1091        {
1092          char c=',';
1093          for (i = 0; i<r->block1[l]-r->block0[l]; i++)
1094          {
1095            StringAppend("%d," ,r->wvhdl[l][i+j]);
1096          }
1097          if (r->order[l]!=ringorder_M)
1098          {
1099            StringAppend("%d)" ,r->wvhdl[l][i+j]);
1100            break;
1101          }
1102          if (j+i+1==(r->block1[l]-r->block0[l]+1)*(r->block1[l]-r->block0[l]+1))
1103            c=')';
1104          StringAppend("%d%c" ,r->wvhdl[l][i+j],c);
1105        }
1106      }
1107      else
1108        StringAppend("(%d)",r->block1[l]-r->block0[l]+1);
1109    }
1110    if (l==nblocks) return omStrDup(StringAppendS(""));
1111    StringAppendS(",");
1112  }
1113}
1114
1115char * rVarStr(ring r)
1116{
1117  int i;
1118  int l=2;
1119  char *s;
1120
1121  for (i=0; i<r->N; i++)
1122  {
1123    l+=strlen(r->names[i])+1;
1124  }
1125  s=(char *)omAlloc(l);
1126  s[0]='\0';
1127  for (i=0; i<r->N-1; i++)
1128  {
1129    strcat(s,r->names[i]);
1130    strcat(s,",");
1131  }
1132  strcat(s,r->names[i]);
1133  return s;
1134}
1135
1136char * rCharStr(ring r)
1137{
1138  char *s;
1139  int i;
1140
1141  if (r->parameter==NULL)
1142  {
1143    i=r->ch;
1144    if(i==-1)
1145      s=omStrDup("real");                    /* R */
1146    else
1147    {
1148      s=(char *)omAlloc(6);
1149      sprintf(s,"%d",i);                   /* Q, Z/p */
1150    }
1151    return s;
1152  }
1153  int l=0;
1154  for(i=0; i<rPar(r);i++)
1155  {
1156    l+=(strlen(r->parameter[i])+1);
1157  }
1158  s=(char *)omAlloc(l+6);
1159  s[0]='\0';
1160  if (r->ch<0)       sprintf(s,"%d",-r->ch); /* Fp(a) */
1161  else if (r->ch==1) sprintf(s,"0");         /* Q(a)  */
1162  else
1163  {
1164    sprintf(s,"%d,%s",r->ch,r->parameter[0]); /* Fq  */
1165    return s;
1166  }
1167  char tt[2];
1168  tt[0]=',';
1169  tt[1]='\0';
1170  for(i=0; i<rPar(r);i++)
1171  {
1172    strcat(s,tt);
1173    strcat(s,r->parameter[i]);
1174  }
1175  return s;
1176}
1177
1178char * rParStr(ring r)
1179{
1180  if (r->parameter==NULL) return omStrDup("");
1181
1182  int i;
1183  int l=2;
1184
1185  for (i=0; i<rPar(r); i++)
1186  {
1187    l+=strlen(r->parameter[i])+1;
1188  }
1189  char *s=(char *)omAlloc(l);
1190  s[0]='\0';
1191  for (i=0; i<rPar(r)-1; i++)
1192  {
1193    strcat(s,r->parameter[i]);
1194    strcat(s,",");
1195  }
1196  strcat(s,r->parameter[i]);
1197  return s;
1198}
1199
1200char * rString(ring r)
1201{
1202  char *ch=rCharStr(r);
1203  char *var=rVarStr(r);
1204  char *ord=rOrdStr(r);
1205  char *res=(char *)omAlloc(strlen(ch)+strlen(var)+strlen(ord)+9);
1206  sprintf(res,"(%s),(%s),(%s)",ch,var,ord);
1207  omFree((ADDRESS)ch);
1208  omFree((ADDRESS)var);
1209  omFree((ADDRESS)ord);
1210  return res;
1211}
1212
1213int rChar(ring r)
1214{
1215  if (r->ch==-1)
1216    return 0;
1217  if (r->parameter==NULL) /* Q, Fp */
1218    return r->ch;
1219  if (r->ch<0)           /* Fp(a)  */
1220    return -r->ch;
1221  if (r->ch==1)          /* Q(a)  */
1222    return 0;
1223  /*else*/               /* GF(p,n) */
1224  {
1225    if ((r->ch & 1)==0) return 2;
1226    int i=3;
1227    while ((r->ch % i)!=0) i+=2;
1228    return i;
1229  }
1230}
1231
1232int    rIsExtension(ring r)
1233{
1234  if (r->parameter==NULL) /* Q, Fp */
1235    return FALSE;
1236  else
1237    return TRUE;
1238}
1239
1240int    rIsExtension()
1241{
1242  return rIsExtension( currRing );
1243}
1244
1245/*2
1246 *returns -1 for not compatible, (sum is undefined)
1247 *         0 for equal, (and sum)
1248 *         1 for compatible (and sum)
1249 */
1250int rSum(ring r1, ring r2, ring &sum)
1251{
1252  if (r1==r2)
1253  {
1254    sum=r1;
1255    r1->ref++;
1256    return 0;
1257  }
1258  ip_sring tmpR;
1259  memset(&tmpR,0,sizeof(tmpR));
1260  /* check coeff. field =====================================================*/
1261  if (rInternalChar(r1)==rInternalChar(r2))
1262  {
1263    tmpR.ch=rInternalChar(r1);
1264    if (rField_is_Q(r1)||rField_is_Zp(r1)||rField_is_GF(r1)) /*Q, Z/p, GF(p,n)*/
1265    {
1266      if (r1->parameter!=NULL)
1267      {
1268        if (strcmp(r1->parameter[0],r2->parameter[0])==0) /* 1 char */
1269        {
1270          tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
1271          tmpR.parameter[0]=omStrDup(r1->parameter[0]);
1272          tmpR.P=1;
1273        }
1274        else
1275        {
1276          WerrorS("GF(p,n)+GF(p,n)");
1277          return -1;
1278        }
1279      }
1280    }
1281    else if ((r1->ch==1)||(r1->ch<-1)) /* Q(a),Z/p(a) */
1282    {
1283      if (r1->minpoly!=NULL)
1284      {
1285        if (r2->minpoly!=NULL)
1286        {
1287          nSetChar(r1);
1288          if ((strcmp(r1->parameter[0],r2->parameter[0])==0) /* 1 char */
1289              && naEqual(r1->minpoly,r2->minpoly))
1290          {
1291            tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
1292            tmpR.parameter[0]=omStrDup(r1->parameter[0]);
1293            tmpR.minpoly=naCopy(r1->minpoly);
1294            tmpR.P=1;
1295            nSetChar(currRing);
1296          }
1297          else
1298          {
1299            nSetChar(currRing);
1300            WerrorS("different minpolys");
1301            return -1;
1302          }
1303        }
1304        else
1305        {
1306          if ((strcmp(r1->parameter[0],r2->parameter[0])==0) /* 1 char */
1307              && (rPar(r2)==1))
1308          {
1309            tmpR.parameter=(char **)omAlloc0Bin(char_ptr_bin);
1310            tmpR.parameter[0]=omStrDup(r1->parameter[0]);
1311            tmpR.P=1;
1312            nSetChar(r1);
1313            tmpR.minpoly=naCopy(r1->minpoly);
1314            nSetChar(currRing);
1315          }
1316          else
1317          {
1318            WerrorS("different parameters and minpoly!=0");
1319            return -1;
1320          }
1321        }
1322      }
1323      else /* r1->minpoly==NULL */
1324      {
1325        if (r2->minpoly!=NULL)
1326        {
1327          if ((strcmp(r1->parameter[0],r2->parameter[0])==0) /* 1 char */
1328              && (rPar(r1)==1))
1329          {
1330            tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
1331            tmpR.parameter[0]=omStrDup(r1->parameter[0]);
1332            tmpR.P=1;
1333            nSetChar(r2);
1334            tmpR.minpoly=naCopy(r2->minpoly);
1335            nSetChar(currRing);
1336          }
1337          else
1338          {
1339            WerrorS("different parameters and minpoly!=0");
1340            return -1;
1341          }
1342        }
1343        else
1344        {
1345          int len=rPar(r1)+rPar(r2);
1346          tmpR.parameter=(char **)omAlloc(len*sizeof(char_ptr));
1347          int i;
1348          for (i=0;i<rPar(r1);i++)
1349          {
1350            tmpR.parameter[i]=omStrDup(r1->parameter[i]);
1351          }
1352          int j,l;
1353          for(j=0;j<rPar(r2);j++)
1354          {
1355            for(l=0;l<i;l++)
1356            {
1357              if(strcmp(tmpR.parameter[l],r2->parameter[j])==0)
1358                break;
1359            }
1360            if (l==i)
1361            {
1362              tmpR.parameter[i]=omStrDup(r2->parameter[j]);
1363              i++;
1364            }
1365          }
1366          if (i!=len)
1367          {
1368            omReallocSize(tmpR.parameter,len*sizeof(char_ptr),i*sizeof(char_ptr));
1369          }
1370        }
1371      }
1372    }
1373  }
1374  else /* r1->ch!=r2->ch */
1375  {
1376    if (r1->ch<-1) /* Z/p(a) */
1377    {
1378      if ((r2->ch==0) /* Q */
1379          || (r2->ch==-r1->ch)) /* Z/p */
1380      {
1381        tmpR.ch=rInternalChar(r1);
1382        tmpR.parameter=(char **)omAlloc(rPar(r1)*sizeof(char_ptr));
1383        tmpR.P=rPar(r1);
1384        memcpy(tmpR.parameter,r1->parameter,rPar(r1)*sizeof(char_ptr));
1385        if (r1->minpoly!=NULL)
1386        {
1387          nSetChar(r1);
1388          tmpR.minpoly=naCopy(r1->minpoly);
1389          nSetChar(currRing);
1390        }
1391      }
1392      else  /* R, Q(a),Z/q,Z/p(a),GF(p,n) */
1393      {
1394        WerrorS("Z/p(a)+(R,Q(a),Z/q(a),GF(q,n))");
1395        return -1;
1396      }
1397    }
1398    else if (r1->ch==-1) /* R */
1399    {
1400      WerrorS("R+..");
1401      return -1;
1402    }
1403    else if (r1->ch==0) /* Q */
1404    {
1405      if ((r2->ch<-1)||(r2->ch==1)) /* Z/p(a),Q(a) */
1406      {
1407        tmpR.ch=rInternalChar(r2);
1408        tmpR.P=rPar(r2);
1409        tmpR.parameter=(char **)omAlloc(rPar(r2)*sizeof(char_ptr));
1410        memcpy(tmpR.parameter,r2->parameter,rPar(r2)*sizeof(char_ptr));
1411        if (r2->minpoly!=NULL)
1412        {
1413          nSetChar(r1);
1414          tmpR.minpoly=naCopy(r2->minpoly);
1415          nSetChar(currRing);
1416        }
1417      }
1418      else if (r2->ch>1) /* Z/p,GF(p,n) */
1419      {
1420        tmpR.ch=r2->ch;
1421        if (r2->parameter!=NULL)
1422        {
1423          tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
1424          tmpR.P=1;
1425          tmpR.parameter[0]=omStrDup(r2->parameter[0]);
1426        }
1427      }
1428      else
1429      {
1430        WerrorS("Q+R");
1431        return -1; /* R */
1432      }
1433    }
1434    else if (r1->ch==1) /* Q(a) */
1435    {
1436      if (r2->ch==0) /* Q */
1437      {
1438        tmpR.ch=rInternalChar(r1);
1439        tmpR.P=rPar(r1);
1440        tmpR.parameter=(char **)omAlloc0(rPar(r1)*sizeof(char_ptr));
1441        int i;
1442        for(i=0;i<rPar(r1);i++)
1443        {
1444          tmpR.parameter[i]=omStrDup(r1->parameter[i]);
1445        }
1446        if (r1->minpoly!=NULL)
1447        {
1448          nSetChar(r1);
1449          tmpR.minpoly=naCopy(r1->minpoly);
1450          nSetChar(currRing);
1451        }
1452      }
1453      else  /* R, Z/p,GF(p,n) */
1454      {
1455        WerrorS("Q(a)+(R,Z/p,GF(p,n))");
1456        return -1;
1457      }
1458    }
1459    else /* r1->ch >=2 , Z/p */
1460    {
1461      if (r2->ch==0) /* Q */
1462      {
1463        tmpR.ch=r1->ch;
1464      }
1465      else if (r2->ch==-r1->ch) /* Z/p(a) */
1466      {
1467        tmpR.ch=rInternalChar(r2);
1468        tmpR.P=rPar(r2);
1469        tmpR.parameter=(char **)omAlloc(rPar(r2)*sizeof(char_ptr));
1470        int i;
1471        for(i=0;i<rPar(r2);i++)
1472        {
1473          tmpR.parameter[i]=omStrDup(r2->parameter[i]);
1474        }
1475        if (r2->minpoly!=NULL)
1476        {
1477          nSetChar(r2);
1478          tmpR.minpoly=naCopy(r2->minpoly);
1479          nSetChar(currRing);
1480        }
1481      }
1482      else
1483      {
1484        WerrorS("Z/p+(GF(q,n),Z/q(a),R,Q(a))");
1485        return -1; /* GF(p,n),Z/q(a),R,Q(a) */
1486      }
1487    }
1488  }
1489  /* variable names ========================================================*/
1490  int i,j,k;
1491  int l=r1->N+r2->N;
1492  char **names=(char **)omAlloc0(l*sizeof(char_ptr));
1493  k=0;
1494
1495  // collect all varnames from r1, except those which are parameters
1496  // of r2, or those which are the empty string
1497  for (i=0;i<r1->N;i++)
1498  {
1499    BOOLEAN b=TRUE;
1500
1501    if (*(r1->names[i]) == '\0')
1502      b = FALSE;
1503    else if ((r2->parameter!=NULL) && (strlen(r1->names[i])==1))
1504    {
1505      for(j=0;j<rPar(r2);j++)
1506      {
1507        if (strcmp(r1->names[i],r2->parameter[j])==0)
1508        {
1509          b=FALSE;
1510          break;
1511        }
1512      }
1513    }
1514
1515    if (b)
1516    {
1517      //Print("name : %d: %s\n",k,r1->names[i]);
1518      names[k]=omStrDup(r1->names[i]);
1519      k++;
1520    }
1521    //else
1522    //  Print("no name (par1) %s\n",r1->names[i]);
1523  }
1524  // Add variables from r2, except those which are parameters of r1
1525  // those which are empty strings, and those which equal a var of r1
1526  for(i=0;i<r2->N;i++)
1527  {
1528    BOOLEAN b=TRUE;
1529
1530    if (*(r2->names[i]) == '\0')
1531      b = FALSE;
1532    else if ((r1->parameter!=NULL) && (strlen(r2->names[i])==1))
1533    {
1534      for(j=0;j<rPar(r1);j++)
1535      {
1536        if (strcmp(r2->names[i],r1->parameter[j])==0)
1537        {
1538          b=FALSE;
1539          break;
1540        }
1541      }
1542    }
1543
1544    if (b)
1545    {
1546      for(j=0;j<r1->N;j++)
1547      {
1548        if (strcmp(r1->names[j],r2->names[i])==0)
1549        {
1550          b=FALSE;
1551          break;
1552        }
1553      }
1554      if (b)
1555      {
1556        //Print("name : %d : %s\n",k,r2->names[i]);
1557        names[k]=omStrDup(r2->names[i]);
1558        k++;
1559      }
1560      //else
1561      //  Print("no name (var): %s\n",r2->names[i]);
1562    }
1563    //else
1564    //  Print("no name (par): %s\n",r2->names[i]);
1565  }
1566  // check whether we found any vars at all
1567  if (k == 0)
1568  {
1569    names[k]=omStrDup("");
1570    k=1;
1571  }
1572  tmpR.N=k;
1573  tmpR.names=names;
1574  /* ordering *======================================================== */
1575  tmpR.OrdSgn=1;
1576  if ((r1->order[0]==ringorder_unspec)
1577      && (r2->order[0]==ringorder_unspec))
1578  {
1579    tmpR.order=(int*)omAlloc(3*sizeof(int));
1580    tmpR.block0=(int*)omAlloc(3*sizeof(int));
1581    tmpR.block1=(int*)omAlloc(3*sizeof(int));
1582    tmpR.wvhdl=(int**)omAlloc0(3*sizeof(int_ptr));
1583    tmpR.order[0]=ringorder_unspec;
1584    tmpR.order[1]=ringorder_C;
1585    tmpR.order[2]=0;
1586    tmpR.block0[0]=1;
1587    tmpR.block1[0]=tmpR.N;
1588  }
1589  else if (l==k) /* r3=r1+r2 */
1590  {
1591    int b;
1592    ring rb;
1593    if (r1->order[0]==ringorder_unspec)
1594    {
1595      /* extend order of r2 to r3 */
1596      b=rBlocks(r2);
1597      rb=r2;
1598      tmpR.OrdSgn=r2->OrdSgn;
1599    }
1600    else if (r2->order[0]==ringorder_unspec)
1601    {
1602      /* extend order of r1 to r3 */
1603      b=rBlocks(r1);
1604      rb=r1;
1605      tmpR.OrdSgn=r1->OrdSgn;
1606    }
1607    else
1608    {
1609      b=rBlocks(r1)+rBlocks(r2)-2; /* for only one order C, only one 0 */
1610      rb=NULL;
1611    }
1612    tmpR.order=(int*)omAlloc0(b*sizeof(int));
1613    tmpR.block0=(int*)omAlloc0(b*sizeof(int));
1614    tmpR.block1=(int*)omAlloc0(b*sizeof(int));
1615    tmpR.wvhdl=(int**)omAlloc0(b*sizeof(int_ptr));
1616    /* weights not implemented yet ...*/
1617    if (rb!=NULL)
1618    {
1619      for (i=0;i<b;i++)
1620      {
1621        tmpR.order[i]=rb->order[i];
1622        tmpR.block0[i]=rb->block0[i];
1623        tmpR.block1[i]=rb->block1[i];
1624        if (rb->wvhdl[i]!=NULL)
1625          WarnS("rSum: weights not implemented");
1626      }
1627      tmpR.block0[0]=1;
1628    }
1629    else /* ring sum for complete rings */
1630    {
1631      for (i=0;r1->order[i]!=0;i++)
1632      {
1633        tmpR.order[i]=r1->order[i];
1634        tmpR.block0[i]=r1->block0[i];
1635        tmpR.block1[i]=r1->block1[i];
1636        if (r1->wvhdl[i]!=NULL)
1637          tmpR.wvhdl[i] = (int*) omMemDup(r1->wvhdl[i]);
1638      }
1639      j=i;
1640      i--;
1641      if ((r1->order[i]==ringorder_c)
1642          ||(r1->order[i]==ringorder_C))
1643      {
1644        j--;
1645        tmpR.order[b-2]=r1->order[i];
1646      }
1647      for (i=0;r2->order[i]!=0;i++)
1648      {
1649        if ((r2->order[i]!=ringorder_c)
1650            &&(r2->order[i]!=ringorder_C))
1651        {
1652          tmpR.order[j]=r2->order[i];
1653          tmpR.block0[j]=r2->block0[i]+r1->N;
1654          tmpR.block1[j]=r2->block1[i]+r1->N;
1655          if (r2->wvhdl[i]!=NULL)
1656          {
1657            tmpR.wvhdl[j] = (int*) omMemDup(r2->wvhdl[i]);
1658          }
1659          j++;
1660        }
1661      }
1662      if((r1->OrdSgn==-1)||(r2->OrdSgn==-1))
1663        tmpR.OrdSgn=-1;
1664    }
1665  }
1666  else if ((k==r1->N) && (k==r2->N)) /* r1 and r2 are "quite" the same ring */
1667    /* copy r1, because we have the variables from r1 */
1668  {
1669    int b=rBlocks(r1);
1670
1671    tmpR.order=(int*)omAlloc0(b*sizeof(int));
1672    tmpR.block0=(int*)omAlloc0(b*sizeof(int));
1673    tmpR.block1=(int*)omAlloc0(b*sizeof(int));
1674    tmpR.wvhdl=(int**)omAlloc0(b*sizeof(int_ptr));
1675    /* weights not implemented yet ...*/
1676    for (i=0;i<b;i++)
1677    {
1678      tmpR.order[i]=r1->order[i];
1679      tmpR.block0[i]=r1->block0[i];
1680      tmpR.block1[i]=r1->block1[i];
1681      if (r1->wvhdl[i]!=NULL)
1682      {
1683        tmpR.wvhdl[i] = (int*) omMemDup(r1->wvhdl[i]);
1684      }
1685    }
1686    tmpR.OrdSgn=r1->OrdSgn;
1687  }
1688  else
1689  {
1690    for(i=0;i<k;i++) omFree((ADDRESS)tmpR.names[i]);
1691    omFreeSize((ADDRESS)names,tmpR.N*sizeof(char_ptr));
1692    Werror("difficulties with variables: %d,%d -> %d",r1->N,r2->N,k);
1693    return -1;
1694  }
1695  sum=(ring)omAllocBin(ip_sring_bin);
1696  memcpy(sum,&tmpR,sizeof(ip_sring));
1697  rComplete(sum);
1698  return 1;
1699}
1700
1701/*2
1702 * create a copy of the ring r, which must be equivalent to currRing
1703 * used for qring definition,..
1704 * (i.e.: normal rings: same nCopy as currRing;
1705 *        qring:        same nCopy, same idCopy as currRing)
1706 * DOES NOT CALL rComplete
1707 */
1708static ring rCopy0(ring r, BOOLEAN copy_qideal = TRUE,
1709                   BOOLEAN copy_ordering = TRUE)
1710{
1711  if (r == NULL) return NULL;
1712  int i,j;
1713  ring res=(ring)omAllocBin(ip_sring_bin);
1714
1715  memcpy4(res,r,sizeof(ip_sring));
1716  res->VarOffset = NULL;
1717  res->ref=0;
1718  if (r->parameter!=NULL)
1719  {
1720    res->minpoly=nCopy(r->minpoly);
1721    int l=rPar(r);
1722    res->parameter=(char **)omAlloc(l*sizeof(char_ptr));
1723    int i;
1724    for(i=0;i<rPar(r);i++)
1725    {
1726      res->parameter[i]=omStrDup(r->parameter[i]);
1727    }
1728  }
1729  if (copy_ordering == TRUE)
1730  {
1731    i=rBlocks(r);
1732    res->wvhdl   = (int **)omAlloc(i * sizeof(int_ptr));
1733    res->order   = (int *) omAlloc(i * sizeof(int));
1734    res->block0  = (int *) omAlloc(i * sizeof(int));
1735    res->block1  = (int *) omAlloc(i * sizeof(int));
1736    for (j=0; j<i; j++)
1737    {
1738      if (r->wvhdl[j]!=NULL)
1739      {
1740        res->wvhdl[j] = (int*) omMemDup(r->wvhdl[j]);
1741      }
1742      else
1743        res->wvhdl[j]=NULL;
1744    }
1745    memcpy4(res->order,r->order,i * sizeof(int));
1746    memcpy4(res->block0,r->block0,i * sizeof(int));
1747    memcpy4(res->block1,r->block1,i * sizeof(int));
1748  }
1749  else
1750  {
1751    res->wvhdl = NULL;
1752    res->order = NULL;
1753    res->block0 = NULL;
1754    res->block1 = NULL;
1755  }
1756
1757  res->names   = (char **)omAlloc0(r->N * sizeof(char_ptr));
1758  for (i=0; i<res->N; i++)
1759  {
1760    res->names[i] = omStrDup(r->names[i]);
1761  }
1762  res->idroot = NULL;
1763  if (r->qideal!=NULL)
1764  {
1765    if (copy_qideal) res->qideal= idrCopyR_NoSort(r->qideal, r);
1766    else res->qideal = NULL;
1767  }
1768  return res;
1769}
1770
1771/*2
1772 * create a copy of the ring r, which must be equivalent to currRing
1773 * used for qring definition,..
1774 * (i.e.: normal rings: same nCopy as currRing;
1775 *        qring:        same nCopy, same idCopy as currRing)
1776 */
1777ring rCopy(ring r)
1778{
1779  if (r == NULL) return NULL;
1780  ring res=rCopy0(r);
1781  rComplete(res, 1);
1782  return res;
1783}
1784
1785// returns TRUE, if r1 equals r2 FALSE, otherwise Equality is
1786// determined componentwise, if qr == 1, then qrideal equality is
1787// tested, as well
1788BOOLEAN rEqual(ring r1, ring r2, BOOLEAN qr)
1789{
1790  int i, j;
1791
1792  if (r1 == r2) return 1;
1793
1794  if (r1 == NULL || r2 == NULL) return 0;
1795
1796  if ((rInternalChar(r1) != rInternalChar(r2))
1797  || (r1->ch_flags != r2->ch_flags)
1798  || (r1->N != r2->N)
1799  || (r1->OrdSgn != r2->OrdSgn)
1800  || (rPar(r1) != rPar(r2)))
1801    return 0;
1802
1803  for (i=0; i<r1->N; i++)
1804  {
1805    if (r1->names[i] != NULL && r2->names[i] != NULL)
1806    {
1807      if (strcmp(r1->names[i], r2->names[i])) return 0;
1808    }
1809    else if ((r1->names[i] != NULL) ^ (r2->names[i] != NULL))
1810    {
1811      return 0;
1812    }
1813  }
1814
1815  i=0;
1816  while (r1->order[i] != 0)
1817  {
1818    if (r2->order[i] == 0) return 0;
1819    if ((r1->order[i] != r2->order[i]) ||
1820        (r1->block0[i] != r2->block0[i]) || (r2->block0[i] != r1->block0[i]))
1821      return 0;
1822    if (r1->wvhdl[i] != NULL)
1823    {
1824      if (r2->wvhdl[i] == NULL)
1825        return 0;
1826      for (j=0; j<r1->block1[i]-r1->block0[i]+1; j++)
1827        if (r2->wvhdl[i][j] != r1->wvhdl[i][j])
1828          return 0;
1829    }
1830    else if (r2->wvhdl[i] != NULL) return 0;
1831    i++;
1832  }
1833
1834  for (i=0; i<rPar(r1);i++)
1835  {
1836      if (strcmp(r1->parameter[i], r2->parameter[i])!=0)
1837        return 0;
1838  }
1839
1840  if (r1->minpoly != NULL)
1841  {
1842    if (r2->minpoly == NULL) return 0;
1843    if (currRing == r1 || currRing == r2)
1844    {
1845      if (! nEqual(r1->minpoly, r2->minpoly)) return 0;
1846    }
1847  }
1848  else if (r2->minpoly != NULL) return 0;
1849
1850  if (qr)
1851  {
1852    if (r1->qideal != NULL)
1853    {
1854      ideal id1 = r1->qideal, id2 = r2->qideal;
1855      int i, n;
1856      poly *m1, *m2;
1857
1858      if (id2 == NULL) return 0;
1859      if ((n = IDELEMS(id1)) != IDELEMS(id2)) return 0;
1860
1861      if (currRing == r1 || currRing == r2)
1862      {
1863        m1 = id1->m;
1864        m2 = id2->m;
1865        for (i=0; i<n; i++)
1866          if (! pEqualPolys(m1[i],m2[i])) return 0;
1867      }
1868    }
1869    else if (r2->qideal != NULL) return 0;
1870  }
1871
1872  return 1;
1873}
1874
1875rOrderType_t rGetOrderType(ring r)
1876{
1877  // check for simple ordering
1878  if (rHasSimpleOrder(r))
1879  {
1880    if ((r->order[1] == ringorder_c) || (r->order[1] == ringorder_C))
1881    {
1882      switch(r->order[0])
1883      {
1884          case ringorder_dp:
1885          case ringorder_wp:
1886          case ringorder_ds:
1887          case ringorder_ws:
1888          case ringorder_ls:
1889          case ringorder_unspec:
1890            if (r->order[1] == ringorder_C ||  r->order[0] == ringorder_unspec)
1891              return rOrderType_ExpComp;
1892            return rOrderType_Exp;
1893
1894          default:
1895            assume(r->order[0] == ringorder_lp ||
1896                   r->order[0] == ringorder_rp ||
1897                   r->order[0] == ringorder_Dp ||
1898                   r->order[0] == ringorder_Wp ||
1899                   r->order[0] == ringorder_Ds ||
1900                   r->order[0] == ringorder_Ws);
1901
1902            if (r->order[1] == ringorder_c) return rOrderType_ExpComp;
1903            return rOrderType_Exp;
1904      }
1905    }
1906    else
1907    {
1908      assume((r->order[0]==ringorder_c)||(r->order[0]==ringorder_C));
1909      return rOrderType_CompExp;
1910    }
1911  }
1912  else
1913    return rOrderType_General;
1914}
1915
1916BOOLEAN rHasSimpleOrder(ring r)
1917{
1918  if (r->order[0] == ringorder_unspec) return TRUE;
1919  int blocks = rBlocks(r) - 1;
1920  assume(blocks >= 1);
1921  if (blocks == 1) return TRUE;
1922  if (blocks > 2)  return FALSE;
1923  if (r->order[0] != ringorder_c && r->order[0] != ringorder_C &&
1924      r->order[1] != ringorder_c && r->order[1] != ringorder_C)
1925    return FALSE;
1926  if (r->order[1] == ringorder_M || r->order[0] == ringorder_M)
1927    return FALSE;
1928  return TRUE;
1929}
1930
1931// returns TRUE, if simple lp or ls ordering
1932BOOLEAN rHasSimpleLexOrder(ring r)
1933{
1934  return rHasSimpleOrder(r) &&
1935    (r->order[0] == ringorder_ls ||
1936     r->order[0] == ringorder_lp ||
1937     r->order[1] == ringorder_ls ||
1938     r->order[1] == ringorder_lp);
1939}
1940
1941BOOLEAN rOrder_is_DegOrdering(rRingOrder_t order)
1942{
1943  switch(order)
1944  {
1945      case ringorder_dp:
1946      case ringorder_Dp:
1947      case ringorder_ds:
1948      case ringorder_Ds:
1949      case ringorder_Ws:
1950      case ringorder_Wp:
1951      case ringorder_ws:
1952      case ringorder_wp:
1953        return TRUE;
1954
1955      default:
1956        return FALSE;
1957  }
1958}
1959
1960BOOLEAN rOrder_is_WeightedOrdering(rRingOrder_t order)
1961{
1962  switch(order)
1963  {
1964      case ringorder_Ws:
1965      case ringorder_Wp:
1966      case ringorder_ws:
1967      case ringorder_wp:
1968        return TRUE;
1969
1970      default:
1971        return FALSE;
1972  }
1973}
1974
1975BOOLEAN rHasSimpleOrderAA(ring r)
1976{
1977  int blocks = rBlocks(r) - 1;
1978  if (blocks != 3) return FALSE;
1979  return ((r->order[0] == ringorder_aa && r->order[1] != ringorder_M) ||
1980          (r->order[1] == ringorder_aa && r->order[2] != ringorder_M));
1981}
1982
1983// return TRUE if p->exp[r->pOrdIndex] holds total degree of p */
1984BOOLEAN rOrd_is_Totaldegree_Ordering(ring r =currRing)
1985{
1986  // Hmm.... what about Syz orderings?
1987  return (r->N > 1 &&
1988          ((rHasSimpleOrder(r) &&
1989           (rOrder_is_DegOrdering((rRingOrder_t)r->order[0]) ||
1990            rOrder_is_DegOrdering(( rRingOrder_t)r->order[1]))) ||
1991           (rHasSimpleOrderAA(r) &&
1992            (rOrder_is_DegOrdering((rRingOrder_t)r->order[1]) ||
1993             rOrder_is_DegOrdering((rRingOrder_t)r->order[2])))));
1994}
1995
1996// return TRUE if p->exp[r->pOrdIndex] holds a weighted degree of p */
1997BOOLEAN rOrd_is_WeightedDegree_Ordering(ring r =currRing)
1998{
1999  // Hmm.... what about Syz orderings?
2000  return (r->N > 1 &&
2001          rHasSimpleOrder(r) &&
2002          (rOrder_is_WeightedOrdering((rRingOrder_t)r->order[0]) ||
2003           rOrder_is_WeightedOrdering(( rRingOrder_t)r->order[1])));
2004}
2005
2006BOOLEAN rIsPolyVar(int v, ring r)
2007{
2008  int  i=0;
2009  while(r->order[i]!=0)
2010  {
2011    if((r->block0[i]<=v)
2012    && (r->block1[i]>=v))
2013    {
2014      switch(r->order[i])
2015      {
2016        case ringorder_a:
2017          return (r->wvhdl[i][v-r->block0[i]]>0);
2018        case ringorder_M:
2019          return 2; /*don't know*/
2020        case ringorder_lp:
2021        case ringorder_rp:
2022        case ringorder_dp:
2023        case ringorder_Dp:
2024        case ringorder_wp:
2025        case ringorder_Wp:
2026          return TRUE;
2027        case ringorder_ls:
2028        case ringorder_ds:
2029        case ringorder_Ds:
2030        case ringorder_ws:
2031        case ringorder_Ws:
2032          return FALSE;
2033        default:
2034          break;
2035      }
2036    }
2037    i++;
2038  }
2039  return 3; /* could not find var v*/
2040}
2041
2042#ifdef RDEBUG
2043// This should eventually become a full-fledge ring check, like pTest
2044BOOLEAN rDBTest(ring r, char* fn, int l)
2045{
2046  int i,j;
2047
2048  if (r == NULL)
2049  {
2050    dReportError("Null ring in %s:%d", fn, l);
2051    return FALSE;
2052  }
2053
2054
2055  if (r->N == 0) return TRUE;
2056
2057//  omCheckAddrSize(r,sizeof(ip_sring));
2058#if OM_CHECK > 0
2059  i=rBlocks(r);
2060  omCheckAddrSize(r->order,i*sizeof(int));
2061  omCheckAddrSize(r->block0,i*sizeof(int));
2062  omCheckAddrSize(r->block1,i*sizeof(int));
2063  omCheckAddrSize(r->wvhdl,i*sizeof(int *));
2064  for (j=0;j<i; j++)
2065  {
2066    if (r->wvhdl[j] != NULL) omCheckAddr(r->wvhdl[j]);
2067  }
2068#endif
2069  if (r->VarOffset == NULL)
2070  {
2071    dReportError("Null ring VarOffset -- no rComplete (?) in n %s:%d", fn, l);
2072    return FALSE;
2073  }
2074  omCheckAddrSize(r->VarOffset,(r->N+1)*sizeof(int));
2075
2076  if ((r->OrdSize==0)!=(r->typ==NULL))
2077  {
2078    dReportError("mismatch OrdSize and typ-pointer in %s:%d");
2079    return FALSE;
2080  }
2081  omcheckAddrSize(r->typ,r->OrdSize*sizeof(*(r->typ)));
2082  omCheckAddrSize(r->VarOffset,(r->N+1)*sizeof(*(r->VarOffset)));
2083  // test assumptions:
2084  for(i=0;i<=r->N;i++)
2085  {
2086    if(r->typ!=NULL)
2087    {
2088      for(j=0;j<r->OrdSize;j++)
2089      {
2090        if (r->typ[j].ord_typ==ro_cp)
2091        {
2092          if(((short)r->VarOffset[i]) == r->typ[j].data.cp.place)
2093            dReportError("ordrec %d conflicts with var %d",j,i);
2094        }
2095        else
2096          if ((r->typ[j].ord_typ!=ro_syzcomp)
2097          && (r->VarOffset[i] == r->typ[j].data.dp.place))
2098            dReportError("ordrec %d conflicts with var %d",j,i);
2099      }
2100    }
2101    int tmp;
2102      tmp=r->VarOffset[i] & 0xffffff;
2103      #if SIZEOF_LONG == 8
2104        if ((r->VarOffset[i] >> 24) >63)
2105      #else
2106        if ((r->VarOffset[i] >> 24) >31)
2107      #endif
2108          dReportError("bit_start out of range:%d",r->VarOffset[i] >> 24);
2109      if (i > 0 && ((tmp<0) ||(tmp>r->ExpL_Size-1)))
2110      {
2111        dReportError("varoffset out of range for var %d: %d",i,tmp);
2112      }
2113  }
2114  if(r->typ!=NULL)
2115  {
2116    for(j=0;j<r->OrdSize;j++)
2117    {
2118      if ((r->typ[j].ord_typ==ro_dp)
2119      || (r->typ[j].ord_typ==ro_wp)
2120      || (r->typ[j].ord_typ==ro_wp_neg))
2121      {
2122        if (r->typ[j].data.dp.start > r->typ[j].data.dp.end)
2123          dReportError("in ordrec %d: start(%d) > end(%d)",j,
2124            r->typ[j].data.dp.start, r->typ[j].data.dp.end);
2125        if ((r->typ[j].data.dp.start < 1)
2126        || (r->typ[j].data.dp.end > r->N))
2127          dReportError("in ordrec %d: start(%d)<1 or end(%d)>vars(%d)",j,
2128            r->typ[j].data.dp.start, r->typ[j].data.dp.end,r->N);
2129      }
2130    }
2131  }
2132  //assume(r->cf!=NULL);
2133
2134  return TRUE;
2135}
2136#endif
2137
2138static void rO_Align(int &place, int &bitplace)
2139{
2140  // increment place to the next aligned one
2141  // (count as Exponent_t,align as longs)
2142  if (bitplace!=BITS_PER_LONG)
2143  {
2144    place++;
2145    bitplace=BITS_PER_LONG;
2146  }
2147}
2148
2149static void rO_TDegree(int &place, int &bitplace, int start, int end,
2150    long *o, sro_ord &ord_struct)
2151{
2152  // degree (aligned) of variables v_start..v_end, ordsgn 1
2153  rO_Align(place,bitplace);
2154  ord_struct.ord_typ=ro_dp;
2155  ord_struct.data.dp.start=start;
2156  ord_struct.data.dp.end=end;
2157  ord_struct.data.dp.place=place;
2158  o[place]=1;
2159  place++;
2160  rO_Align(place,bitplace);
2161}
2162
2163static void rO_TDegree_neg(int &place, int &bitplace, int start, int end,
2164    long *o, sro_ord &ord_struct)
2165{
2166  // degree (aligned) of variables v_start..v_end, ordsgn -1
2167  rO_Align(place,bitplace);
2168  ord_struct.ord_typ=ro_dp;
2169  ord_struct.data.dp.start=start;
2170  ord_struct.data.dp.end=end;
2171  ord_struct.data.dp.place=place;
2172  o[place]=-1;
2173  place++;
2174  rO_Align(place,bitplace);
2175}
2176
2177static void rO_WDegree(int &place, int &bitplace, int start, int end,
2178    long *o, sro_ord &ord_struct, int *weights)
2179{
2180  // weighted degree (aligned) of variables v_start..v_end, ordsgn 1
2181  rO_Align(place,bitplace);
2182  ord_struct.ord_typ=ro_wp;
2183  ord_struct.data.wp.start=start;
2184  ord_struct.data.wp.end=end;
2185  ord_struct.data.wp.place=place;
2186  ord_struct.data.wp.weights=weights;
2187  o[place]=1;
2188  place++;
2189  rO_Align(place,bitplace);
2190  int i;
2191  for(i=start;i<=end;i++)
2192  {
2193    if(weights[i-start]<0)
2194    {
2195      ord_struct.ord_typ=ro_wp_neg;
2196      break;
2197    }
2198  }
2199}
2200
2201static void rO_WDegree_neg(int &place, int &bitplace, int start, int end,
2202    long *o, sro_ord &ord_struct, int *weights)
2203{
2204  // weighted degree (aligned) of variables v_start..v_end, ordsgn -1
2205  rO_Align(place,bitplace);
2206  ord_struct.ord_typ=ro_wp;
2207  ord_struct.data.wp.start=start;
2208  ord_struct.data.wp.end=end;
2209  ord_struct.data.wp.place=place;
2210  ord_struct.data.wp.weights=weights;
2211  o[place]=-1;
2212  place++;
2213  rO_Align(place,bitplace);
2214  int i;
2215  for(i=start;i<=end;i++)
2216  {
2217    if(weights[i-start]<0)
2218    {
2219      ord_struct.ord_typ=ro_wp_neg;
2220      break;
2221    }
2222  }
2223}
2224
2225static void rO_LexVars(int &place, int &bitplace, int start, int end,
2226  int &prev_ord, long *o,int *v, int bits, int opt_var)
2227{
2228  // a block of variables v_start..v_end with lex order, ordsgn 1
2229  int k;
2230  int incr=1;
2231  if(prev_ord==-1) rO_Align(place,bitplace);
2232
2233  if (start>end)
2234  {
2235    incr=-1;
2236  }
2237  for(k=start;;k+=incr)
2238  {
2239    bitplace-=bits;
2240    if (bitplace < 0) { bitplace=BITS_PER_LONG-bits; place++; }
2241    o[place]=1;
2242    v[k]= place | (bitplace << 24);
2243    if (k==end) break;
2244  }
2245  prev_ord=1;
2246  if (opt_var!= -1)
2247  {
2248    assume((opt_var == end+1) ||(opt_var == end-1));
2249    if((opt_var != end+1) &&(opt_var != end-1)) WarnS("hier-2");
2250    int save_bitplace=bitplace;
2251    bitplace-=bits;
2252    if (bitplace < 0)
2253    {
2254      bitplace=save_bitplace;
2255      return;
2256    }
2257    // there is enough space for the optional var
2258    v[opt_var]=place | (bitplace << 24);
2259  }
2260}
2261
2262static void rO_LexVars_neg(int &place, int &bitplace, int start, int end,
2263  int &prev_ord, long *o,int *v, int bits, int opt_var)
2264{
2265  // a block of variables v_start..v_end with lex order, ordsgn -1
2266  int k;
2267  int incr=1;
2268  if(prev_ord==1) rO_Align(place,bitplace);
2269
2270  if (start>end)
2271  {
2272    incr=-1;
2273  }
2274  for(k=start;;k+=incr)
2275  {
2276    bitplace-=bits;
2277    if (bitplace < 0) { bitplace=BITS_PER_LONG-bits; place++; }
2278    o[place]=-1;
2279    v[k]=place | (bitplace << 24);
2280    if (k==end) break;
2281  }
2282  prev_ord=-1;
2283//  #if 0
2284  if (opt_var!= -1)
2285  {
2286    assume((opt_var == end+1) ||(opt_var == end-1));
2287    if((opt_var != end+1) &&(opt_var != end-1)) WarnS("hier-1");
2288    int save_bitplace=bitplace;
2289    bitplace-=bits;
2290    if (bitplace < 0)
2291    {
2292      bitplace=save_bitplace;
2293      return;
2294    }
2295    // there is enough space for the optional var
2296    v[opt_var]=place | (bitplace << 24);
2297  }
2298//  #endif
2299}
2300
2301static void rO_Syzcomp(int &place, int &bitplace, int &prev_ord,
2302    long *o, sro_ord &ord_struct)
2303{
2304  // ordering is derived from component number
2305  rO_Align(place,bitplace);
2306  ord_struct.ord_typ=ro_syzcomp;
2307  ord_struct.data.syzcomp.place=place;
2308  ord_struct.data.syzcomp.Components=NULL;
2309  ord_struct.data.syzcomp.ShiftedComponents=NULL;
2310  o[place]=1;
2311  prev_ord=1;
2312  place++;
2313  rO_Align(place,bitplace);
2314}
2315
2316static void rO_Syz(int &place, int &bitplace, int &prev_ord,
2317    long *o, sro_ord &ord_struct)
2318{
2319  // ordering is derived from component number
2320  // let's reserve one Exponent_t for it
2321  if ((prev_ord== 1) || (bitplace!=BITS_PER_LONG))
2322    rO_Align(place,bitplace);
2323  ord_struct.ord_typ=ro_syz;
2324  ord_struct.data.syz.place=place;
2325  ord_struct.data.syz.limit=0;
2326  ord_struct.data.syz.syz_index = NULL;
2327  ord_struct.data.syz.curr_index = 1;
2328  o[place]= -1;
2329  prev_ord=-1;
2330  place++;
2331}
2332
2333static unsigned long rGetExpSize(unsigned long bitmask, int & bits)
2334{
2335  if (bitmask == 0)
2336  {
2337    bits=16; bitmask=0xffff;
2338  }
2339  else if (bitmask <= 1)
2340  {
2341    bits=1; bitmask = 1;
2342  }
2343  else if (bitmask <= 3)
2344  {
2345    bits=2; bitmask = 3;
2346  }
2347  else if (bitmask <= 7)
2348  {
2349    bits=3; bitmask=7;
2350  }
2351  else if (bitmask <= 0xf)
2352  {
2353    bits=4; bitmask=0xf;
2354  }
2355  else if (bitmask <= 0x1f)
2356  {
2357    bits=5; bitmask=0x1f;
2358  }
2359  else if (bitmask <= 0x3f)
2360  {
2361    bits=6; bitmask=0x3f;
2362  }
2363#if SIZEOF_LONG == 8
2364  else if (bitmask <= 0x7f)
2365  {
2366    bits=7; bitmask=0x7f; /* 64 bit longs only */
2367  }
2368#endif
2369  else if (bitmask <= 0xff)
2370  {
2371    bits=8; bitmask=0xff;
2372  }
2373#if SIZEOF_LONG == 8
2374  else if (bitmask <= 0x1ff)
2375  {
2376    bits=9; bitmask=0x1ff; /* 64 bit longs only */
2377  }
2378#endif
2379  else if (bitmask <= 0x3ff)
2380  {
2381    bits=10; bitmask=0x3ff;
2382  }
2383#if SIZEOF_LONG == 8
2384  else if (bitmask <= 0xfff)
2385  {
2386    bits=12; bitmask=0xfff; /* 64 bit longs only */
2387  }
2388#endif
2389  else if (bitmask <= 0xffff)
2390  {
2391    bits=16; bitmask=0xffff;
2392  }
2393#if SIZEOF_LONG == 8
2394  else if (bitmask <= 0xfffff)
2395  {
2396    bits=20; bitmask=0xfffff; /* 64 bit longs only */
2397  }
2398  else if (bitmask <= 0xffffffff)
2399  {
2400    bits=32; bitmask=0xffffffff;
2401  }
2402  else
2403  {
2404    bits=64; bitmask=0xffffffffffffffff;
2405  }
2406#else
2407  else
2408  {
2409    bits=32; bitmask=0xffffffff;
2410  }
2411#endif
2412  return bitmask;
2413}
2414
2415/*2
2416* optimize rGetExpSize for a block of N variables, exp <=bitmask
2417*/
2418static unsigned long rGetExpSize(unsigned long bitmask, int & bits, int N)
2419{
2420  bitmask =rGetExpSize(bitmask, bits);
2421  int vars_per_long=BIT_SIZEOF_LONG/bits;
2422  int bits1;
2423  loop
2424  {
2425    if (bits == BIT_SIZEOF_LONG)
2426    {
2427      bits =  BIT_SIZEOF_LONG - 1;
2428      return LONG_MAX;
2429    }
2430    unsigned long bitmask1 =rGetExpSize(bitmask+1, bits1);
2431    int vars_per_long1=BIT_SIZEOF_LONG/bits1;
2432    if ((((N+vars_per_long-1)/vars_per_long) ==
2433         ((N+vars_per_long1-1)/vars_per_long1)))
2434    {
2435      vars_per_long=vars_per_long1;
2436      bits=bits1;
2437      bitmask=bitmask1;
2438    }
2439    else
2440    {
2441      return bitmask; /* and bits */
2442    }
2443  }
2444}
2445
2446/*2
2447 * create a copy of the ring r, which must be equivalent to currRing
2448 * used for std computations
2449 * may share data structures with currRing
2450 * DOES CALL rComplete
2451 */
2452ring rModifyRing(ring r, BOOLEAN omit_degree,
2453                         BOOLEAN omit_comp,
2454                         unsigned long exp_limit)
2455{
2456  assume (r != NULL );
2457  assume (exp_limit > 1);
2458  BOOLEAN need_other_ring;
2459  int bits;
2460
2461  exp_limit=rGetExpSize(exp_limit, bits, r->N);
2462  need_other_ring = (exp_limit != r->bitmask);
2463
2464  int nblocks=rBlocks(r);
2465  int *order=(int*)omAlloc0((nblocks+1)*sizeof(int));
2466  int *block0=(int*)omAlloc0((nblocks+1)*sizeof(int));
2467  int *block1=(int*)omAlloc0((nblocks+1)*sizeof(int));
2468  int **wvhdl=(int**)omAlloc0((nblocks+1)*sizeof(int_ptr));
2469
2470  int i=0;
2471  int j=0; /*  i index in r, j index in res */
2472  loop
2473  {
2474    BOOLEAN copy_block_index=TRUE;
2475    int r_ord=r->order[i];
2476    if (r->block0[i]==r->block1[i])
2477    {
2478      switch(r_ord)
2479      {
2480        case ringorder_wp:
2481        case ringorder_dp:
2482        case ringorder_Wp:
2483        case ringorder_Dp:
2484          r_ord=ringorder_lp;
2485          break;
2486        case ringorder_Ws:
2487        case ringorder_Ds:
2488        case ringorder_ws:
2489        case ringorder_ds:
2490          r_ord=ringorder_ls;
2491          break;
2492        default:
2493          break;
2494      }
2495    }
2496    switch(r_ord)
2497    {
2498      case ringorder_C:
2499      case ringorder_c:
2500        if (!omit_comp)
2501        {
2502          order[j]=r_ord; /*r->order[i]*/;
2503        }
2504        else
2505        {
2506          j--;
2507          need_other_ring=TRUE;
2508          omit_comp=FALSE;
2509          copy_block_index=FALSE;
2510        }
2511        break;
2512      case ringorder_wp:
2513      case ringorder_dp:
2514      case ringorder_ws:
2515      case ringorder_ds:
2516        if(!omit_degree)
2517        {
2518          order[j]=r_ord; /*r->order[i]*/;
2519        }
2520        else
2521        {
2522          order[j]=ringorder_rp;
2523          need_other_ring=TRUE;
2524          omit_degree=FALSE;
2525        }
2526        break;
2527      case ringorder_Wp:
2528      case ringorder_Dp:
2529      case ringorder_Ws:
2530      case ringorder_Ds:
2531        if(!omit_degree)
2532        {
2533          order[j]=r_ord; /*r->order[i];*/
2534        }
2535        else
2536        {
2537          order[j]=ringorder_lp;
2538          need_other_ring=TRUE;
2539          omit_degree=FALSE;
2540        }
2541        break;
2542      default:
2543        order[j]=r_ord; /*r->order[i];*/
2544        break;
2545    }
2546    if (copy_block_index)
2547    {
2548      block0[j]=r->block0[i];
2549      block1[j]=r->block1[i];
2550      wvhdl[j]=r->wvhdl[i];
2551    }
2552    i++;j++;
2553    // order[j]=ringorder_no; //  done by omAlloc0
2554    if (i==nblocks) break;
2555  }
2556  if(!need_other_ring)
2557  {
2558    omFreeSize(order,(nblocks+1)*sizeof(int));
2559    omFreeSize(block0,(nblocks+1)*sizeof(int));
2560    omFreeSize(block1,(nblocks+1)*sizeof(int));
2561    omFreeSize(wvhdl,(nblocks+1)*sizeof(int_ptr));
2562    return r;
2563  }
2564  ring res=(ring)omAlloc0Bin(ip_sring_bin);
2565  *res = *r;
2566  // res->qideal, res->idroot ???
2567  res->wvhdl=wvhdl;
2568  res->order=order;
2569  res->block0=block0;
2570  res->block1=block1;
2571  res->bitmask=exp_limit;
2572  rComplete(res, 1);
2573
2574  // adjust res->pFDeg: if it was changed globaly, then
2575  // it must also be changed for new ring
2576  if (pFDeg != r->pFDeg)
2577    res->pFDeg = pFDeg;
2578  else if (r->pFDeg != res->pFDeg &&
2579           rOrd_is_WeightedDegree_Ordering(r))
2580    // still might need adjustment
2581  {
2582    res->firstwv = r->firstwv;
2583    res->firstBlockEnds = r->firstBlockEnds;
2584    res->pFDeg = pWFirstTotalDegree;
2585  }
2586
2587  // set syzcomp
2588  if (res->typ != NULL && res->typ[0].ord_typ == ro_syz)
2589  {
2590    res->typ[0] = r->typ[0];
2591    if (r->typ[0].data.syz.limit > 0)
2592    {
2593      res->typ[0].data.syz.syz_index
2594        = (int*) omAlloc((r->typ[0].data.syz.limit +1)*sizeof(int));
2595      memcpy(res->typ[0].data.syz.syz_index, r->typ[0].data.syz.syz_index,
2596             (r->typ[0].data.syz.limit +1)*sizeof(int));
2597    }
2598  }
2599  return res;
2600}
2601
2602void rKillModifiedRing(ring r)
2603{
2604  rUnComplete(r);
2605  omFree(r->order);
2606  omFree(r->block0);
2607  omFree(r->block1);
2608  omFree(r->wvhdl);
2609  omFreeBin(r,ip_sring_bin);
2610}
2611
2612static void rSetOutParams(ring r)
2613{
2614  r->VectorOut = (r->order[0] == ringorder_c);
2615  r->ShortOut = TRUE;
2616#ifdef HAVE_TCL
2617  if (tcllmode)
2618  {
2619    r->ShortOut = FALSE;
2620  }
2621  else
2622#endif
2623  {
2624    int i;
2625    if ((r->parameter!=NULL) && (r->ch<2))
2626    {
2627      for (i=0;i<rPar(r);i++)
2628      {
2629        if(strlen(r->parameter[i])>1)
2630        {
2631          r->ShortOut=FALSE;
2632          break;
2633        }
2634      }
2635    }
2636    if (r->ShortOut)
2637    {
2638      // Hmm... sometimes (e.g., from maGetPreimage) new variables
2639      // are intorduced, but their names are never set
2640      // hence, we do the following awkward trick
2641      int N = omSizeWOfAddr(r->names);
2642      if (r->N < N) N = r->N;
2643
2644      for (i=(N-1);i>=0;i--)
2645      {
2646        if(r->names[i] != NULL && strlen(r->names[i])>1)
2647        {
2648          r->ShortOut=FALSE;
2649          break;
2650        }
2651      }
2652    }
2653  }
2654  r->CanShortOut = r->ShortOut;
2655}
2656
2657/*2
2658* sets pMixedOrder and pComponentOrder for orderings with more than one block
2659* block of variables (ip is the block number, o_r the number of the ordering)
2660*/
2661static void rHighSet(ring r, int o_r)
2662{
2663  switch(o_r)
2664  {
2665    case ringorder_lp:
2666    case ringorder_dp:
2667    case ringorder_Dp:
2668    case ringorder_wp:
2669    case ringorder_Wp:
2670    case ringorder_rp:
2671    case ringorder_a:
2672    case ringorder_aa:
2673      if (r->OrdSgn==-1) r->MixedOrder=TRUE;
2674      break;
2675    case ringorder_ls:
2676    case ringorder_ds:
2677    case ringorder_Ds:
2678    case ringorder_ws:
2679    case ringorder_Ws:
2680    case ringorder_s:
2681      break;
2682    case ringorder_c:
2683      r->ComponentOrder=1;
2684      break;
2685    case ringorder_C:
2686    case ringorder_S:
2687      r->ComponentOrder=-1;
2688      break;
2689    case ringorder_M:
2690      r->MixedOrder=TRUE;
2691      break;
2692    default:
2693      dReportError("wrong internal ordering:%d at %s, l:%d\n",o_r,__FILE__,__LINE__);
2694  }
2695}
2696
2697static void rSetFirstWv(ring r, int i, int* order, int* block1, int** wvhdl)
2698{
2699  // cheat for ringorder_aa
2700  if (order[i] == ringorder_aa)
2701    i++;
2702  if(block1[i]!=r->N) r->LexOrder=TRUE;
2703  r->firstBlockEnds=block1[i];
2704  r->firstwv = wvhdl[i];
2705}
2706 
2707// set pFDeg, pLDeg, MixOrder, ComponentOrder, etc
2708static void rSetDegStuff(ring r)
2709{
2710  int* order = r->order;
2711  int* block0 = r->block0;
2712  int* block1 = r->block1;
2713  int** wvhdl = r->wvhdl;
2714
2715  if (order[0]==ringorder_S ||order[0]==ringorder_s)
2716  {
2717    order++;
2718    block0++;
2719    block1++;
2720    wvhdl++;
2721  }
2722  r->LexOrder = FALSE;
2723  r->MixedOrder = FALSE;
2724  r->ComponentOrder = 1;
2725  r->pFDeg = pTotaldegree;
2726  r->pLDeg = (r->OrdSgn == 1 ? pLDegb : pLDeg0);
2727
2728  /*======== ordering type is (_,c) =========================*/
2729  if ((order[0]==ringorder_unspec) || (order[1] == 0)
2730      ||(
2731    ((order[1]==ringorder_c)||(order[1]==ringorder_C)
2732     ||(order[1]==ringorder_S)
2733     ||(order[1]==ringorder_s))
2734    && (order[0]!=ringorder_M)
2735    && (order[2]==0))
2736    )
2737  {
2738    if ((order[0]!=ringorder_unspec)
2739    && ((order[1]==ringorder_C)||(order[1]==ringorder_S)||
2740        (order[1]==ringorder_s)))
2741      r->ComponentOrder=-1;
2742    if (r->OrdSgn == -1) r->pLDeg = pLDeg0c;
2743    if ((order[0] == ringorder_lp) || (order[0] == ringorder_ls))
2744    {
2745      r->LexOrder=TRUE;
2746      r->pLDeg = pLDeg1c;
2747    }
2748    if (order[0] == ringorder_wp || order[0] == ringorder_Wp ||
2749        order[0] == ringorder_ws || order[0] == ringorder_Ws)
2750      r->pFDeg = pWFirstTotalDegree;
2751    r->firstBlockEnds=block1[0];
2752    r->firstwv = wvhdl[0];
2753  }
2754  /*======== ordering type is (c,_) =========================*/
2755  else if (((order[0]==ringorder_c)
2756            ||(order[0]==ringorder_C)
2757            ||(order[0]==ringorder_S)
2758            ||(order[0]==ringorder_s))
2759  && (order[1]!=ringorder_M)
2760  &&  (order[2]==0))
2761  {
2762    if ((order[0]==ringorder_C)||(order[0]==ringorder_S)||
2763        order[0]==ringorder_s)
2764      r->ComponentOrder=-1;
2765    if ((order[1] == ringorder_lp) || (order[1] == ringorder_ls))
2766    {
2767      r->LexOrder=TRUE;
2768      r->pLDeg = pLDeg1c;
2769    }
2770    r->firstBlockEnds=block1[1];
2771    r->firstwv = wvhdl[1];
2772    if (order[1] == ringorder_wp || order[1] == ringorder_Wp ||
2773        order[1] == ringorder_ws || order[1] == ringorder_Ws)
2774      r->pFDeg = pWFirstTotalDegree;
2775  }
2776  /*------- more than one block ----------------------*/
2777  else
2778  {
2779    if ((r->VectorOut)||(order[0]==ringorder_C)||(order[0]==ringorder_S)||(order[0]==ringorder_s))
2780    {
2781      rSetFirstWv(r, 1, order, block1, wvhdl);
2782    }
2783    else
2784      rSetFirstWv(r, 0, order, block1, wvhdl);
2785
2786    /*the number of orderings:*/
2787    int i = 0;
2788    while (order[++i] != 0);
2789    do
2790    {
2791      i--;
2792      rHighSet(r, order[i]);
2793    }
2794    while (i != 0);
2795
2796    if ((order[0]!=ringorder_c)
2797        && (order[0]!=ringorder_C)
2798        && (order[0]!=ringorder_S)
2799        && (order[0]!=ringorder_s))
2800    {
2801      r->pLDeg = pLDeg1c;
2802    }
2803    else
2804    {
2805      r->pLDeg = pLDeg1;
2806    }
2807    r->pFDeg = pWTotaldegree; // may be improved: pTotaldegree for lp/dp/ls/.. blocks
2808  }
2809  if (rOrd_is_Totaldegree_Ordering(r))
2810    r->pFDeg = pDeg;
2811}
2812
2813/*2
2814* set NegWeightL_Size, NegWeightL_Offset
2815*/
2816static void rSetNegWeight(ring r)
2817{
2818  int i,l;
2819  if (r->typ!=NULL)
2820  {
2821    l=0;
2822    for(i=0;i<r->OrdSize;i++)
2823    {
2824      if(r->typ[i].ord_typ==ro_wp_neg) l++;
2825    }
2826    if (l>0)
2827    {
2828      r->NegWeightL_Size=l;
2829      r->NegWeightL_Offset=(int *) omAlloc(l*sizeof(int));
2830      l=0;
2831      for(i=0;i<r->OrdSize;i++)
2832      {
2833        if(r->typ[i].ord_typ==ro_wp_neg)
2834        {
2835          r->NegWeightL_Offset[l]=r->typ[i].data.wp.place;
2836          l++;
2837        }
2838      }
2839    }
2840  }
2841}
2842
2843static void rSetOption(ring r)
2844{
2845  // set redthrough
2846  if (!TEST_OPT_OLDSTD && r->OrdSgn == 1 && ! r->LexOrder)
2847    r->options |= Sy_bit(OPT_REDTHROUGH);
2848  else
2849    r->options &= ~Sy_bit(OPT_REDTHROUGH);
2850
2851  // set intStrategy
2852  if (rField_is_Extension(r) || rField_is_Q(r))
2853    r->options |= Sy_bit(OPT_INTSTRATEGY);
2854  else
2855    r->options &= ~Sy_bit(OPT_INTSTRATEGY);
2856 
2857  // set redTail
2858  if (r->LexOrder || r->OrdSgn == -1 || rField_is_Extension(r))
2859    r->options &= ~Sy_bit(OPT_REDTAIL);
2860  else
2861    r->options |= Sy_bit(OPT_REDTAIL);
2862}
2863
2864BOOLEAN rComplete(ring r, int force)
2865{
2866  if (r->VarOffset!=NULL && force == 0) return FALSE;
2867  nInitChar(r);
2868  rSetOutParams(r);
2869  rSetDegStuff(r);
2870  rSetOption(r);
2871  int n=rBlocks(r)-1;
2872  int i;
2873  int bits;
2874  r->bitmask=rGetExpSize(r->bitmask,bits,r->N);
2875  r->BitsPerExp = bits;
2876  r->ExpPerLong = BIT_SIZEOF_LONG / bits;
2877  r->divmask=rGetDivMask(bits);
2878
2879  // will be used for ordsgn:
2880  long *tmp_ordsgn=(long *)omAlloc0(2*(n+r->N)*sizeof(long));
2881  // will be used for VarOffset:
2882  int *v=(int *)omAlloc((r->N+1)*sizeof(int));
2883  for(i=r->N; i>=0 ; i--)
2884  {
2885    v[i]=-1;
2886  }
2887  sro_ord *tmp_typ=(sro_ord *)omAlloc0(2*(n+r->N)*sizeof(sro_ord));
2888  int typ_i=0;
2889  int prev_ordsgn=0;
2890
2891  // fill in v, tmp_typ, tmp_ordsgn, determine typ_i (== ordSize)
2892  int j=0;
2893  int j_bits=BITS_PER_LONG;
2894  BOOLEAN need_to_add_comp=FALSE;
2895  for(i=0;i<n;i++)
2896  {
2897    tmp_typ[typ_i].order_index=i;
2898    switch (r->order[i])
2899    {
2900      case ringorder_a:
2901      case ringorder_aa:
2902        rO_WDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,tmp_typ[typ_i],
2903                   r->wvhdl[i]);
2904        typ_i++;
2905        break;
2906
2907      case ringorder_c:
2908        rO_Align(j, j_bits);
2909        rO_LexVars_neg(j, j_bits, 0,0, prev_ordsgn,tmp_ordsgn,v,BITS_PER_LONG, -1);
2910        break;
2911
2912      case ringorder_C:
2913        rO_Align(j, j_bits);
2914        rO_LexVars(j, j_bits, 0,0, prev_ordsgn,tmp_ordsgn,v,BITS_PER_LONG, -1);
2915        break;
2916
2917      case ringorder_M:
2918        {
2919          int k,l;
2920          k=r->block1[i]-r->block0[i]+1; // number of vars
2921          for(l=0;l<k;l++)
2922          {
2923            rO_WDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
2924                       tmp_typ[typ_i],
2925                       r->wvhdl[i]+(r->block1[i]-r->block0[i]+1)*l);
2926            typ_i++;
2927          }
2928          break;
2929        }
2930
2931      case ringorder_lp:
2932        rO_LexVars(j, j_bits, r->block0[i],r->block1[i], prev_ordsgn,
2933                   tmp_ordsgn,v,bits, -1);
2934        break;
2935
2936      case ringorder_ls:
2937        rO_LexVars_neg(j, j_bits, r->block0[i],r->block1[i], prev_ordsgn,
2938                       tmp_ordsgn,v, bits, -1);
2939        break;
2940
2941      case ringorder_rp:
2942        rO_LexVars_neg(j, j_bits, r->block1[i],r->block0[i], prev_ordsgn,
2943                       tmp_ordsgn,v, bits, -1);
2944        break;
2945
2946      case ringorder_dp:
2947        if (r->block0[i]==r->block1[i])
2948        {
2949          rO_LexVars(j, j_bits, r->block0[i],r->block0[i], prev_ordsgn,
2950                     tmp_ordsgn,v, bits, -1);
2951        }
2952        else
2953        {
2954          rO_TDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
2955                     tmp_typ[typ_i]);
2956          typ_i++;
2957          rO_LexVars_neg(j, j_bits, r->block1[i],r->block0[i]+1,
2958                         prev_ordsgn,tmp_ordsgn,v,bits, r->block0[i]);
2959        }
2960        break;
2961
2962      case ringorder_Dp:
2963        if (r->block0[i]==r->block1[i])
2964        {
2965          rO_LexVars(j, j_bits, r->block0[i],r->block0[i], prev_ordsgn,
2966                     tmp_ordsgn,v, bits, -1);
2967        }
2968        else
2969        {
2970          rO_TDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
2971                     tmp_typ[typ_i]);
2972          typ_i++;
2973          rO_LexVars(j, j_bits, r->block0[i],r->block1[i]-1, prev_ordsgn,
2974                     tmp_ordsgn,v, bits, r->block1[i]);
2975        }
2976        break;
2977
2978      case ringorder_ds:
2979        if (r->block0[i]==r->block1[i])
2980        {
2981          rO_LexVars_neg(j, j_bits,r->block0[i],r->block1[i],prev_ordsgn,
2982                         tmp_ordsgn,v,bits, -1);
2983        }
2984        else
2985        {
2986          rO_TDegree_neg(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
2987                         tmp_typ[typ_i]);
2988          typ_i++;
2989          rO_LexVars_neg(j, j_bits, r->block1[i],r->block0[i]+1,
2990                         prev_ordsgn,tmp_ordsgn,v,bits, r->block0[i]);
2991        }
2992        break;
2993
2994      case ringorder_Ds:
2995        if (r->block0[i]==r->block1[i])
2996        {
2997          rO_LexVars_neg(j, j_bits, r->block0[i],r->block0[i],prev_ordsgn,
2998                         tmp_ordsgn,v, bits, -1);
2999        }
3000        else
3001        {
3002          rO_TDegree_neg(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3003                         tmp_typ[typ_i]);
3004          typ_i++;
3005          rO_LexVars(j, j_bits, r->block0[i],r->block1[i]-1, prev_ordsgn,
3006                     tmp_ordsgn,v, bits, r->block1[i]);
3007        }
3008        break;
3009
3010      case ringorder_wp:
3011        rO_WDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3012                   tmp_typ[typ_i], r->wvhdl[i]);
3013        typ_i++;
3014        if (r->block1[i]!=r->block0[i])
3015        {
3016          rO_LexVars_neg(j, j_bits,r->block1[i],r->block0[i]+1, prev_ordsgn,
3017                         tmp_ordsgn, v,bits, r->block0[i]);
3018        }
3019        break;
3020
3021      case ringorder_Wp:
3022        rO_WDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3023                   tmp_typ[typ_i], r->wvhdl[i]);
3024        typ_i++;
3025        if (r->block1[i]!=r->block0[i])
3026        {
3027          rO_LexVars(j, j_bits,r->block0[i],r->block1[i]-1, prev_ordsgn,
3028                     tmp_ordsgn,v, bits, r->block1[i]);
3029        }
3030        break;
3031
3032      case ringorder_ws:
3033        rO_WDegree_neg(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3034                       tmp_typ[typ_i], r->wvhdl[i]);
3035        typ_i++;
3036        if (r->block1[i]!=r->block0[i])
3037        {
3038          rO_LexVars_neg(j, j_bits,r->block1[i],r->block0[i]+1, prev_ordsgn,
3039                         tmp_ordsgn, v,bits, r->block0[i]);
3040        }
3041        break;
3042
3043      case ringorder_Ws:
3044        rO_WDegree_neg(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3045                       tmp_typ[typ_i], r->wvhdl[i]);
3046        typ_i++;
3047        if (r->block1[i]!=r->block0[i])
3048        {
3049          rO_LexVars(j, j_bits,r->block0[i],r->block1[i]-1, prev_ordsgn,
3050                     tmp_ordsgn,v, bits, r->block1[i]);
3051        }
3052        break;
3053
3054      case ringorder_S:
3055        rO_Syzcomp(j, j_bits,prev_ordsgn, tmp_ordsgn,tmp_typ[typ_i]);
3056        need_to_add_comp=TRUE;
3057        typ_i++;
3058        break;
3059
3060      case ringorder_s:
3061        rO_Syz(j, j_bits,prev_ordsgn, tmp_ordsgn,tmp_typ[typ_i]);
3062        need_to_add_comp=TRUE;
3063        typ_i++;
3064        break;
3065
3066      case ringorder_unspec:
3067      case ringorder_no:
3068        default:
3069          dReportError("undef. ringorder used\n");
3070          break;
3071    }
3072  }
3073
3074  int j0=j; // save j
3075  int j_bits0=j_bits; // save jbits
3076  rO_Align(j,j_bits);
3077  r->CmpL_Size = j;
3078
3079  j_bits=j_bits0; j=j0;
3080
3081  // fill in some empty slots with variables not already covered
3082  // v0 is special, is therefore normally already covered
3083  // now we do have rings without comp...
3084  if((need_to_add_comp) && (v[0]== -1))
3085  {
3086    if (prev_ordsgn==1)
3087    {
3088      rO_Align(j, j_bits);
3089      rO_LexVars(j, j_bits, 0,0, prev_ordsgn,tmp_ordsgn,v,BITS_PER_LONG, -1);
3090    }
3091    else
3092    {
3093      rO_Align(j, j_bits);
3094      rO_LexVars_neg(j, j_bits, 0,0, prev_ordsgn,tmp_ordsgn,v,BITS_PER_LONG, -1);
3095    }
3096  }
3097  // the variables
3098  for(i=1 ; i<r->N+1 ; i++)
3099  {
3100    if(v[i]==(-1))
3101    {
3102      if (prev_ordsgn==1)
3103      {
3104        rO_LexVars(j, j_bits, i,i, prev_ordsgn,tmp_ordsgn,v,bits, -1);
3105      }
3106      else
3107      {
3108        rO_LexVars_neg(j,j_bits,i,i, prev_ordsgn,tmp_ordsgn,v,bits, -1);
3109      }
3110    }
3111  }
3112
3113  rO_Align(j,j_bits);
3114  // ----------------------------
3115  // finished with constructing the monomial, computing sizes:
3116
3117  r->ExpL_Size=j;
3118  r->PolyBin = omGetSpecBin(POLYSIZE + (r->ExpL_Size)*sizeof(long));
3119  assume(r->PolyBin != NULL);
3120
3121  // ----------------------------
3122  // indices and ordsgn vector for comparison
3123  //
3124  // r->pCompHighIndex already set
3125  r->ordsgn=(long *)omAlloc0(r->ExpL_Size*sizeof(long));
3126
3127  for(j=0;j<r->CmpL_Size;j++)
3128  {
3129    r->ordsgn[j] = tmp_ordsgn[j];
3130  }
3131
3132  omFreeSize((ADDRESS)tmp_ordsgn,(2*(n+r->N)*sizeof(long)));
3133
3134  // ----------------------------
3135  // description of orderings for setm:
3136  //
3137  r->OrdSize=typ_i;
3138  if (typ_i==0) r->typ=NULL;
3139  else
3140  {
3141    r->typ=(sro_ord*)omAlloc(typ_i*sizeof(sro_ord));
3142    memcpy(r->typ,tmp_typ,typ_i*sizeof(sro_ord));
3143  }
3144  omFreeSize((ADDRESS)tmp_typ,(2*(n+r->N)*sizeof(sro_ord)));
3145
3146  // ----------------------------
3147  // indices for (first copy of ) variable entries in exp.e vector (VarOffset):
3148  r->VarOffset=v;
3149
3150  // ----------------------------
3151  // other indicies
3152  r->pCompIndex=(r->VarOffset[0] & 0xffff); //r->VarOffset[0];
3153  i=0; // position
3154  j=0; // index in r->typ
3155  if (i==r->pCompIndex) i++;
3156  while ((j < r->OrdSize)
3157         && ((r->typ[j].ord_typ==ro_syzcomp) || 
3158             (r->typ[j].ord_typ==ro_syz) ||
3159             (r->order[r->typ[j].order_index] == ringorder_aa)))
3160  {
3161    i++; j++;
3162  }
3163  if (i==r->pCompIndex) i++;
3164  r->pOrdIndex=i;
3165
3166  // ----------------------------
3167  // r->p_Setm
3168  r->p_Setm = p_GetSetmProc(r);
3169
3170  // ----------------------------
3171  // set VarL_*
3172  rSetVarL(r);
3173
3174  //  ----------------------------
3175  // right-adjust VarOffset
3176  rRightAdjustVarOffset(r);
3177
3178  // ----------------------------
3179  // set NegWeightL*
3180  rSetNegWeight(r);
3181
3182  // ----------------------------
3183  // p_Procs: call AFTER NegWeightL
3184  r->p_Procs = (p_Procs_s*)omAlloc(sizeof(p_Procs_s));
3185  p_ProcsSet(r, r->p_Procs);
3186
3187  return FALSE;
3188}
3189
3190void rUnComplete(ring r)
3191{
3192  if (r == NULL) return;
3193  if (r->VarOffset != NULL)
3194  {
3195    if (r->PolyBin != NULL)
3196      omUnGetSpecBin(&(r->PolyBin));
3197
3198    omFreeSize((ADDRESS)r->VarOffset, (r->N +1)*sizeof(int));
3199    if (r->order != NULL)
3200    {
3201      if (r->order[0] == ringorder_s && r->typ[0].data.syz.limit > 0)
3202      {
3203        omFreeSize(r->typ[0].data.syz.syz_index,
3204             (r->typ[0].data.syz.limit +1)*sizeof(int));
3205      }
3206    }
3207    if (r->OrdSize!=0 && r->typ != NULL)
3208    {
3209      omFreeSize((ADDRESS)r->typ,r->OrdSize*sizeof(sro_ord));
3210    }
3211    if (r->ordsgn != NULL && r->CmpL_Size != 0)
3212      omFreeSize((ADDRESS)r->ordsgn,r->ExpL_Size*sizeof(long));
3213    if (r->p_Procs != NULL)
3214      omFreeSize(r->p_Procs, sizeof(p_Procs_s));
3215    omfreeSize(r->VarL_Offset, r->VarL_Size*sizeof(int));
3216  }
3217  if (r->NegWeightL_Offset!=NULL)
3218  {
3219    omFreeSize(r->NegWeightL_Offset, r->NegWeightL_Size*sizeof(int));
3220    r->NegWeightL_Offset=NULL;
3221  }
3222}
3223
3224// set r->VarL_Size, r->VarL_Offset, r->VarL_LowIndex
3225static void rSetVarL(ring r)
3226{
3227  int  min = INT_MAX, min_j = -1;
3228  int* VarL_Number = (int*) omAlloc0(r->ExpL_Size*sizeof(int));
3229
3230  int i,j;
3231
3232  // count how often a var long is occupied by an exponent
3233  for (i=1; i<=r->N; i++)
3234  {
3235    VarL_Number[r->VarOffset[i] & 0xffffff]++;
3236  }
3237
3238  // determine how many and min
3239  for (i=0, j=0; i<r->ExpL_Size; i++)
3240  {
3241    if (VarL_Number[i] != 0)
3242    {
3243      if (min > VarL_Number[i])
3244      {
3245        min = VarL_Number[i];
3246        min_j = j;
3247      }
3248      j++;
3249    }
3250  }
3251
3252  r->VarL_Size = j;
3253  r->VarL_Offset = (int*) omAlloc(r->VarL_Size*sizeof(int));
3254  r->VarL_LowIndex = 0;
3255
3256  // set VarL_Offset
3257  for (i=0, j=0; i<r->ExpL_Size; i++)
3258  {
3259    if (VarL_Number[i] != 0)
3260    {
3261      r->VarL_Offset[j] = i;
3262      if (j > 0 && r->VarL_Offset[j-1] != r->VarL_Offset[j] - 1)
3263        r->VarL_LowIndex = -1;
3264      j++;
3265    }
3266  }
3267  if (r->VarL_LowIndex >= 0)
3268    r->VarL_LowIndex = r->VarL_Offset[0];
3269
3270  r->MinExpPerLong = min;
3271  if (min_j != 0)
3272  {
3273    j = r->VarL_Offset[min_j];
3274    r->VarL_Offset[min_j] = r->VarL_Offset[0];
3275    r->VarL_Offset[0] = j;
3276  }
3277  omFree(VarL_Number);
3278}
3279
3280static void rRightAdjustVarOffset(ring r)
3281{
3282  int* shifts = (int*) omAlloc(r->ExpL_Size*sizeof(int));
3283  int i;
3284  // initialize shifts
3285  for (i=0;i<r->ExpL_Size;i++)
3286    shifts[i] = BIT_SIZEOF_LONG;
3287
3288  // find minimal bit in each long var
3289  for (i=1;i<=r->N;i++)
3290  {
3291    if (shifts[r->VarOffset[i] & 0xffffff] > r->VarOffset[i] >> 24)
3292      shifts[r->VarOffset[i] & 0xffffff] = r->VarOffset[i] >> 24;
3293  }
3294  // reset r->VarOffset
3295  for (i=1;i<=r->N;i++)
3296  {
3297    if (shifts[r->VarOffset[i] & 0xffffff] != 0)
3298      r->VarOffset[i]
3299        = (r->VarOffset[i] & 0xffffff) |
3300        (((r->VarOffset[i] >> 24) - shifts[r->VarOffset[i] & 0xffffff]) << 24);
3301  }
3302  omFree(shifts);
3303}
3304
3305// get r->divmask depending on bits per exponent
3306static unsigned long rGetDivMask(int bits)
3307{
3308  unsigned long divmask = 1;
3309  int i = bits;
3310
3311  while (i < BIT_SIZEOF_LONG)
3312  {
3313    divmask |= (((unsigned long) 1) << (unsigned long) i);
3314    i += bits;
3315  }
3316  return divmask;
3317}
3318
3319#ifdef RDEBUG
3320void rDebugPrint(ring r)
3321{
3322  if (r==NULL)
3323  {
3324    PrintS("NULL ?\n");
3325    return;
3326  }
3327  char *TYP[]={"ro_dp","ro_wp","ro_wp_neg","ro_cp",
3328               "ro_syzcomp", "ro_syz", "ro_none"};
3329  int i,j;
3330
3331  Print("ExpL_Size:%d ",r->ExpL_Size);
3332  Print("CmpL_Size:%d ",r->CmpL_Size);
3333  Print("VarL_Size:%d\n",r->VarL_Size);
3334  Print("bitmask=0x%x (expbound=%d) \n",r->bitmask, r->bitmask);
3335  Print("BitsPerExp=%d ExpPerLong=%d MinExpPerLong=%d at L[%d]\n", r->BitsPerExp, r->ExpPerLong, r->MinExpPerLong, r->VarL_Offset[0]);
3336  PrintS("varoffset:\n");
3337  for(j=0;j<=r->N;j++) Print("  v%d at e-pos %d, bit %d\n",
3338     j,r->VarOffset[j] & 0xffffff, r->VarOffset[j] >>24);
3339  Print("divmask=%p\n", r->divmask);
3340  PrintS("ordsgn:\n");
3341  for(j=0;j<r->CmpL_Size;j++)
3342    Print("  ordsgn %d at pos %d\n",r->ordsgn[j],j);
3343  Print("OrdSgn:%d\n",r->OrdSgn);
3344  PrintS("ordrec:\n");
3345  for(j=0;j<r->OrdSize;j++)
3346  {
3347    Print("  typ %s",TYP[r->typ[j].ord_typ]);
3348    Print("  place %d",r->typ[j].data.dp.place);
3349    if (r->typ[j].ord_typ!=ro_syzcomp)
3350    {
3351      Print("  start %d",r->typ[j].data.dp.start);
3352      Print("  end %d",r->typ[j].data.dp.end);
3353      if (r->typ[j].ord_typ==ro_wp)
3354      {
3355        Print(" w:");
3356        int l;
3357        for(l=r->typ[j].data.wp.start;l<=r->typ[j].data.wp.end;l++)
3358          Print(" %d",r->typ[j].data.wp.weights[l-r->typ[j].data.wp.start]);
3359      }
3360    }
3361    PrintLn();
3362  }
3363  Print("pOrdIndex:%d pCompIndex:%d\n", r->pOrdIndex, r->pCompIndex);
3364  Print("OrdSize:%d\n",r->OrdSize);
3365  PrintS("--------------------\n");
3366  for(j=0;j<r->ExpL_Size;j++)
3367  {
3368    Print("L[%d]: ",j);
3369    if (j< r->CmpL_Size)
3370      Print("ordsgn %d ", r->ordsgn[j]);
3371    else
3372      PrintS("no comp ");
3373    i=1;
3374    for(;i<=r->N;i++)
3375    {
3376      if( (r->VarOffset[i] & 0xffffff) == j )
3377      {  Print("v%d at e[%d], bit %d; ", i,r->VarOffset[i] & 0xffffff,
3378                                         r->VarOffset[i] >>24 ); }
3379    }
3380    if( r->pCompIndex==j ) PrintS("v0; ");
3381    for(i=0;i<r->OrdSize;i++)
3382    {
3383      if (r->typ[i].data.dp.place == j)
3384      {
3385        Print("ordrec:%s (start:%d, end:%d) ",TYP[r->typ[i].ord_typ],
3386          r->typ[i].data.dp.start, r->typ[i].data.dp.end);
3387      }
3388    }
3389
3390    if (j==r->pOrdIndex)
3391      PrintS("pOrdIndex\n");
3392    else
3393      PrintLn();
3394  }
3395
3396  // p_Procs stuff
3397  p_Procs_s proc_names;
3398  char* field;
3399  char* length;
3400  char* ord;
3401  p_Debug_GetProcNames(r, &proc_names);
3402  p_Debug_GetSpecNames(r, field, length, ord);
3403
3404  Print("p_Spec  : %s, %s, %s\n", field, length, ord);
3405  PrintS("p_Procs :\n");
3406  for (i=0; i<(int) (sizeof(p_Procs_s)/sizeof(void*)); i++)
3407  {
3408    Print(" %s,\n", ((char**) &proc_names)[i]);
3409  }
3410}
3411
3412void pDebugPrintR(poly p, ring r)
3413{
3414  int i,j;
3415  pWrite(p);
3416  j=2;
3417  while(p!=NULL)
3418  {
3419    Print("\nexp[0..%d]\n",r->ExpL_Size-1);
3420    for(i=0;i<r->ExpL_Size;i++)
3421      Print("%d ",p->exp[i]);
3422    PrintLn();
3423    Print("v0:%d ",p_GetComp(p, r));
3424    for(i=1;i<=r->N;i++) Print(" v%d:%d",i,p_GetExp(p,i, r));
3425    PrintLn();
3426    pIter(p);
3427    j--;
3428    if (j==0) { PrintS("...\n"); break; }
3429  }
3430}
3431
3432void pDebugPrint(poly p)
3433{
3434  pDebugPrintR(p, currRing);
3435}
3436#endif // RDEBUG
3437
3438
3439/*2
3440* asssume that rComplete was called with r
3441* assume that the first block ist ringorder_S
3442* change the block to reflect the sequence given by appending v
3443*/
3444
3445#ifdef PDEBUG
3446void rDBChangeSComps(int* currComponents,
3447                     long* currShiftedComponents,
3448                     int length,
3449                     ring r)
3450{
3451  r->typ[1].data.syzcomp.length = length;
3452  rNChangeSComps( currComponents, currShiftedComponents, r);
3453}
3454void rDBGetSComps(int** currComponents,
3455                 long** currShiftedComponents,
3456                 int *length,
3457                 ring r)
3458{
3459  *length = r->typ[1].data.syzcomp.length;
3460  rNGetSComps( currComponents, currShiftedComponents, r);
3461}
3462#endif
3463
3464void rNChangeSComps(int* currComponents, long* currShiftedComponents, ring r)
3465{
3466  assume(r->order[1]==ringorder_S);
3467
3468  r->typ[1].data.syzcomp.ShiftedComponents = currShiftedComponents;
3469  r->typ[1].data.syzcomp.Components = currComponents;
3470}
3471
3472void rNGetSComps(int** currComponents, long** currShiftedComponents, ring r)
3473{
3474  assume(r->order[1]==ringorder_S);
3475
3476  *currShiftedComponents = r->typ[1].data.syzcomp.ShiftedComponents;
3477  *currComponents =   r->typ[1].data.syzcomp.Components;
3478}
3479
3480/////////////////////////////////////////////////////////////////////////////
3481//
3482// The following routines all take as input a ring r, and return R
3483// where R has a certain property. P might be equal r in which case r
3484// had already this property
3485//
3486// Without argument, these functions work on currRing and change it,
3487// if necessary
3488
3489// for the time being, this is still here
3490static ring rAssure_SyzComp(ring r, BOOLEAN complete = TRUE);
3491ring rCurrRingAssure_SyzComp()
3492{
3493  ring r = rAssure_SyzComp(currRing);
3494  if (r != currRing)
3495  {
3496    ring old_ring = currRing;
3497    rChangeCurrRing(r);
3498    if (old_ring->qideal != NULL)
3499    {
3500      r->qideal = idrCopyR_NoSort(old_ring->qideal, old_ring);
3501      assume(idRankFreeModule(r->qideal) == 0);
3502      currQuotient = r->qideal;
3503    }
3504  }
3505  return r;
3506}
3507
3508static ring rAssure_SyzComp(ring r, BOOLEAN complete = TRUE)
3509{
3510  if (r->order[0] == ringorder_s) return r;
3511  ring res=rCopy0(r, FALSE, FALSE);
3512  int i=rBlocks(r);
3513  int j;
3514
3515  res->order=(int *)omAlloc0((i+1)*sizeof(int));
3516  for(j=i;j>0;j--) res->order[j]=r->order[j-1];
3517  res->order[0]=ringorder_s;
3518
3519  res->block0=(int *)omAlloc0((i+1)*sizeof(int));
3520  for(j=i;j>0;j--) res->block0[j]=r->block0[j-1];
3521
3522  res->block1=(int *)omAlloc0((i+1)*sizeof(int));
3523  for(j=i;j>0;j--) res->block1[j]=r->block1[j-1];
3524
3525  int ** wvhdl =(int **)omAlloc0((i+1)*sizeof(int**));
3526  for(j=i;j>0;j--)
3527  {
3528    if (r->wvhdl[j-1] != NULL)
3529    {
3530      wvhdl[j] = (int*) omMemDup(r->wvhdl[j-1]);
3531    }
3532  }
3533  res->wvhdl = wvhdl;
3534
3535  if (complete) rComplete(res, 1);
3536  return res;
3537}
3538
3539static ring rAssure_CompLastBlock(ring r, BOOLEAN complete = TRUE)
3540{
3541  int last_block = rBlocks(r) - 2;
3542  if (r->order[last_block] != ringorder_c &&
3543      r->order[last_block] != ringorder_C)
3544  {
3545    int c_pos = 0;
3546    int i;
3547
3548    for (i=0; i< last_block; i++)
3549    {
3550      if (r->order[i] == ringorder_c || r->order[i] == ringorder_C)
3551      {
3552        c_pos = i;
3553        break;
3554      }
3555    }
3556    if (c_pos != -1)
3557    {
3558      ring new_r = rCopy0(r, FALSE, TRUE);
3559      for (i=c_pos+1; i<=last_block; i++)
3560      {
3561        new_r->order[i-1] = new_r->order[i];
3562        new_r->block0[i-1] = new_r->block0[i];
3563        new_r->block1[i-1] = new_r->block1[i];
3564        new_r->wvhdl[i-1] = new_r->wvhdl[i];
3565      }
3566      new_r->order[last_block] = r->order[c_pos];
3567      new_r->block0[last_block] = r->block0[c_pos];
3568      new_r->block1[last_block] = r->block1[c_pos];
3569      new_r->wvhdl[last_block] = r->wvhdl[c_pos];
3570      if (complete) rComplete(new_r, 1);
3571      return new_r;
3572    }
3573  }
3574  return r;
3575}
3576
3577ring rCurrRingAssure_CompLastBlock()
3578{
3579  ring new_r = rAssure_CompLastBlock(currRing);
3580  if (currRing != new_r)
3581  {
3582    ring old_r = currRing;
3583    rChangeCurrRing(new_r);
3584    if (old_r->qideal != NULL)
3585    {
3586      new_r->qideal = idrCopyR(old_r->qideal, old_r);
3587      currQuotient = new_r->qideal;
3588    }
3589  }
3590  return new_r;
3591}
3592
3593ring rCurrRingAssure_SyzComp_CompLastBlock()
3594{
3595  ring new_r_1 = rAssure_CompLastBlock(currRing, FALSE);
3596  ring new_r = rAssure_SyzComp(new_r_1, FALSE);
3597
3598  if (new_r != currRing)
3599  {
3600    ring old_r = currRing;
3601    if (new_r_1 != new_r && new_r_1 != old_r) rDelete(new_r_1);
3602    rComplete(new_r, 1);
3603    rChangeCurrRing(new_r);
3604    if (old_r->qideal != NULL)
3605    {
3606      new_r->qideal = idrCopyR(old_r->qideal, old_r);
3607      currQuotient = new_r->qideal;
3608    }
3609    rTest(new_r);
3610    rTest(old_r);
3611  }
3612  return new_r;
3613}
3614
3615// use this for global orderings consisting of two blocks
3616static ring rCurrRingAssure_Global(rRingOrder_t b1, rRingOrder_t b2)
3617{
3618  int r_blocks = rBlocks(currRing);
3619  int i;
3620
3621  assume(b1 == ringorder_c || b1 == ringorder_C ||
3622         b2 == ringorder_c || b2 == ringorder_C ||
3623         b2 == ringorder_S);
3624  if ((r_blocks == 3) &&
3625      (currRing->order[0] == b1) &&
3626      (currRing->order[1] == b2) &&
3627      (currRing->order[2] == 0))
3628    return currRing;
3629  ring res = rCopy0(currRing, TRUE, FALSE);
3630  res->order = (int*)omAlloc0(3*sizeof(int));
3631  res->block0 = (int*)omAlloc0(3*sizeof(int));
3632  res->block1 = (int*)omAlloc0(3*sizeof(int));
3633  res->wvhdl = (int**)omAlloc0(3*sizeof(int*));
3634  res->order[0] = b1;
3635  res->order[1] = b2;
3636  if (b1 == ringorder_c || b1 == ringorder_C)
3637  {
3638    res->block0[1] = 1;
3639    res->block1[1] = currRing->N;
3640  }
3641  else
3642  {
3643    res->block0[0] = 1;
3644    res->block1[0] = currRing->N;
3645  }
3646  // HANNES: This sould be set in rComplete
3647  res->OrdSgn = 1;
3648  rComplete(res, 1);
3649  rChangeCurrRing(res);
3650  return res;
3651}
3652
3653
3654ring rCurrRingAssure_dp_S()
3655{
3656  return rCurrRingAssure_Global(ringorder_dp, ringorder_S);
3657}
3658
3659ring rCurrRingAssure_dp_C()
3660{
3661  return rCurrRingAssure_Global(ringorder_dp, ringorder_C);
3662}
3663
3664ring rCurrRingAssure_C_dp()
3665{
3666  return rCurrRingAssure_Global(ringorder_C, ringorder_dp);
3667}
3668
3669
3670void rSetSyzComp(int k)
3671{
3672  if (TEST_OPT_PROT) Print("{%d}", k);
3673  if ((currRing->typ!=NULL) && (currRing->typ[0].ord_typ==ro_syz))
3674  {
3675    assume(k > currRing->typ[0].data.syz.limit);
3676    int i;
3677    if (currRing->typ[0].data.syz.limit == 0)
3678    {
3679      currRing->typ[0].data.syz.syz_index = (int*) omAlloc0((k+1)*sizeof(int));
3680      currRing->typ[0].data.syz.syz_index[0] = 0;
3681      currRing->typ[0].data.syz.curr_index = 1;
3682    }
3683    else
3684    {
3685      currRing->typ[0].data.syz.syz_index = (int*)
3686        omReallocSize(currRing->typ[0].data.syz.syz_index,
3687                (currRing->typ[0].data.syz.limit+1)*sizeof(int),
3688                (k+1)*sizeof(int));
3689    }
3690    for (i=currRing->typ[0].data.syz.limit + 1; i<= k; i++)
3691    {
3692      currRing->typ[0].data.syz.syz_index[i] =
3693        currRing->typ[0].data.syz.curr_index;
3694    }
3695    currRing->typ[0].data.syz.limit = k;
3696    currRing->typ[0].data.syz.curr_index++;
3697  }
3698  else if ((currRing->order[0]!=ringorder_c) && (k!=0))
3699  {
3700    dReportError("syzcomp in incompatible ring");
3701  }
3702#ifdef PDEBUG
3703  extern int pDBsyzComp;
3704  pDBsyzComp=k;
3705#endif
3706}
3707
3708// return the max-comonent wchich has syzIndex i
3709int rGetMaxSyzComp(int i)
3710{
3711  if ((currRing->typ!=NULL) && (currRing->typ[0].ord_typ==ro_syz) &&
3712      currRing->typ[0].data.syz.limit > 0 && i > 0)
3713  {
3714    assume(i <= currRing->typ[0].data.syz.limit);
3715    int j;
3716    for (j=0; j<currRing->typ[0].data.syz.limit; j++)
3717    {
3718      if (currRing->typ[0].data.syz.syz_index[j] == i  &&
3719          currRing->typ[0].data.syz.syz_index[j+1] != i)
3720      {
3721        assume(currRing->typ[0].data.syz.syz_index[j+1] == i+1);
3722        return j;
3723      }
3724    }
3725    return currRing->typ[0].data.syz.limit;
3726  }
3727  else
3728  {
3729    return 0;
3730  }
3731}
3732
3733BOOLEAN rRing_is_Homog(ring r)
3734{
3735  if (r == NULL) return FALSE;
3736  int i, j, nb = rBlocks(r);
3737  for (i=0; i<nb; i++)
3738  {
3739    if (r->wvhdl[i] != NULL)
3740    {
3741      int length = r->block1[i] - r->block0[i];
3742      int* wvhdl = r->wvhdl[i];
3743      if (r->order[i] == ringorder_M) length *= length;
3744      assume(omSizeOfAddr(wvhdl) >= length*sizeof(int));
3745
3746      for (j=0; j< length; j++)
3747      {
3748        if (wvhdl[j] != 0 && wvhdl[j] != 1) return FALSE;
3749      }
3750    }
3751  }
3752  return TRUE;
3753}
3754
3755BOOLEAN rRing_has_CompLastBlock(ring r)
3756{
3757  assume(r != NULL);
3758  int lb = rBlocks(r) - 2;
3759  return (r->order[lb] == ringorder_c || r->order[lb] == ringorder_C);
3760}
3761
3762n_coeffType rFieldType(ring r)
3763{
3764  if (rField_is_Zp(r))     return n_Zp;
3765  if (rField_is_Q(r))      return n_Q;
3766  if (rField_is_R(r))      return n_R;
3767  if (rField_is_GF(r))     return n_GF;
3768  if (rField_is_long_R(r)) return n_long_R;
3769  if (rField_is_Zp_a(r))   return n_Zp_a;
3770  if (rField_is_Q_a(r))    return n_Q_a;
3771  if (rField_is_long_C(r)) return n_long_C;
3772  return n_unknown;
3773}
Note: See TracBrowser for help on using the repository browser.