source: git/kernel/ring.cc @ fc5095

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