source: git/kernel/ring.cc @ f4adfcb

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