source: git/kernel/ring.cc @ 4c7d73

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