source: git/kernel/ring.cc @ 8837a0

spielwiese
Last change on this file since 8837a0 was 8837a0, checked in by Michael Brickenstein <bricken@…>, 19 years ago
*bricken: added some const git-svn-id: file:///usr/local/Singular/svn/trunk@8533 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 100.4 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: ring.cc,v 1.41 2005-08-18 07:53:47 bricken 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(const 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      if (r->minideal!=NULL)
280      {
281        if (r==currRing) iiWriteMatrix((matrix)r->minideal,"//   minpolys",1,0);
282        else PrintS("//   minpolys=...");
283        PrintLn();
284      }
285    }
286  }
287  Print("//   number of vars : %d",r->N);
288
289  //for (nblocks=0; r->order[nblocks]; nblocks++);
290  nblocks=rBlocks(r)-1;
291
292  for (int l=0, nlen=0 ; l<nblocks; l++)
293  {
294    int i;
295    Print("\n//        block %3d : ",l+1);
296
297    Print("ordering %s", rSimpleOrdStr(r->order[l]));
298
299    if ((r->order[l] >= ringorder_lp)
300    ||(r->order[l] == ringorder_M)
301    ||(r->order[l] == ringorder_a)
302    ||(r->order[l] == ringorder_a64)
303    ||(r->order[l] == ringorder_aa))
304    {
305      PrintS("\n//                  : names    ");
306      for (i = r->block0[l]-1; i<r->block1[l]; i++)
307      {
308        nlen = strlen(r->names[i]);
309        Print("%s ",r->names[i]);
310      }
311    }
312#ifndef NDEBUG
313    else if (r->order[l] == ringorder_s)
314    {
315      Print("  syzcomp at %d",r->typ[l].data.syz.limit);
316    }
317#endif
318
319    if (r->wvhdl[l]!=NULL)
320    {
321      for (int j= 0;
322           j<(r->block1[l]-r->block0[l]+1)*(r->block1[l]-r->block0[l]+1);
323           j+=i)
324      {
325        PrintS("\n//                  : weights  ");
326        for (i = 0; i<=r->block1[l]-r->block0[l]; i++)
327        {
328          if (r->order[l] == ringorder_a64)
329          { int64 *w=(int64 *)r->wvhdl[l];
330            Print("%*lld " ,nlen,w[i+j],i+j);
331          }
332          else
333            Print("%*d " ,nlen,r->wvhdl[l][i+j],i+j);
334        }
335        if (r->order[l]!=ringorder_M) break;
336      }
337    }
338  }
339#ifdef HAVE_PLURAL
340  if (r->nc!=NULL)
341  {
342    PrintS("\n//   noncommutative relations:");
343    if (r==currRing)
344    {
345      poly pl=NULL;
346      int nl;
347      int i,j;
348      //    Print("\n//   noncommutative relations (type %d):",(int)r->nc->type);
349      for (i = 1; i<r->N; i++)
350      {
351        for (j = i+1; j<=r->N; j++)
352        {
353          nl = nIsOne(p_GetCoeff(MATELEM(r->nc->C,i,j),r));
354          if ( (MATELEM(r->nc->D,i,j)!=NULL) || (!nl) )
355          {
356            Print("\n//    %s%s=",r->names[j-1],r->names[i-1]);
357            pl = MATELEM(r->nc->MT[UPMATELEM(i,j,r->N)],1,1);
358            pWrite0(pl);
359          }
360        }
361      }
362    }
363    else PrintS(" ...");
364#ifdef PDEBUG
365    Print("\n//   noncommutative type:%d",r->nc->type);
366    Print("\n//   is skew constant:%d",r->nc->IsSkewConstant);
367    Print("\n//   ref:%d",r->nc->ref);
368#endif
369  }
370#endif
371  if (r->qideal!=NULL)
372  {
373    PrintS("\n// quotient ring from ideal");
374    if (r==currRing)
375    {
376      PrintLn();
377      iiWriteMatrix((matrix)r->qideal,"_",1);
378    }
379    else PrintS(" ...");
380  }
381}
382
383void rDelete(ring r)
384{
385  int i, j;
386
387  if (r == NULL) return;
388
389#ifdef HAVE_PLURAL
390  if (r->nc != NULL)
391  {
392    if (r->nc->ref>1) /* in use by somebody else */
393    {
394      r->nc->ref--;
395    }
396    else
397    {
398      ncKill(r);
399    }
400  }
401#endif
402  nKillChar(r);
403  rUnComplete(r);
404  // delete order stuff
405  if (r->order != NULL)
406  {
407    i=rBlocks(r);
408    assume(r->block0 != NULL && r->block1 != NULL && r->wvhdl != NULL);
409    // delete order
410    omFreeSize((ADDRESS)r->order,i*sizeof(int));
411    omFreeSize((ADDRESS)r->block0,i*sizeof(int));
412    omFreeSize((ADDRESS)r->block1,i*sizeof(int));
413    // delete weights
414    for (j=0; j<i; j++)
415    {
416      if (r->wvhdl[j]!=NULL)
417        omFree(r->wvhdl[j]);
418    }
419    omFreeSize((ADDRESS)r->wvhdl,i*sizeof(int *));
420  }
421  else
422  {
423    assume(r->block0 == NULL && r->block1 == NULL && r->wvhdl == NULL);
424  }
425
426  // delete varnames
427  if(r->names!=NULL)
428  {
429    for (i=0; i<r->N; i++)
430    {
431      if (r->names[i] != NULL) omFree((ADDRESS)r->names[i]);
432    }
433    omFreeSize((ADDRESS)r->names,r->N*sizeof(char_ptr));
434  }
435
436  // delete parameter
437  if (r->parameter!=NULL)
438  {
439    char **s=r->parameter;
440    j = 0;
441    while (j < rPar(r))
442    {
443      if (*s != NULL) omFree((ADDRESS)*s);
444      s++;
445      j++;
446    }
447    omFreeSize((ADDRESS)r->parameter,rPar(r)*sizeof(char_ptr));
448  }
449  omFreeBin(r, ip_sring_bin);
450}
451
452int rOrderName(char * ordername)
453{
454  int order=ringorder_unspec;
455  while (order!= 0)
456  {
457    if (strcmp(ordername,rSimpleOrdStr(order))==0)
458      break;
459    order--;
460  }
461  if (order==0) Werror("wrong ring order `%s`",ordername);
462  omFree((ADDRESS)ordername);
463  return order;
464}
465
466char * rOrdStr(ring r)
467{
468  int nblocks,l,i;
469
470  for (nblocks=0; r->order[nblocks]; nblocks++);
471  nblocks--;
472
473  StringSetS("");
474  for (l=0; ; l++)
475  {
476    StringAppend((char *)rSimpleOrdStr(r->order[l]));
477    if ((r->order[l] != ringorder_c) && (r->order[l] != ringorder_C))
478    {
479      if (r->wvhdl[l]!=NULL)
480      {
481        StringAppendS("(");
482        for (int j= 0;
483             j<(r->block1[l]-r->block0[l]+1)*(r->block1[l]-r->block0[l]+1);
484             j+=i+1)
485        {
486          char c=',';
487          if(r->order[l]==ringorder_a64)
488          {
489            int64 * w=(int64 *)r->wvhdl[l];
490            for (i = 0; i<r->block1[l]-r->block0[l]; i++)
491            {
492              StringAppend("%lld," ,w[i]);
493            }
494            StringAppend("%lld)" ,w[i]);
495            break;
496          }
497          else
498          {
499            for (i = 0; i<r->block1[l]-r->block0[l]; i++)
500            {
501              StringAppend("%d," ,r->wvhdl[l][i+j]);
502            }
503          }
504          if (r->order[l]!=ringorder_M)
505          {
506            StringAppend("%d)" ,r->wvhdl[l][i+j]);
507            break;
508          }
509          if (j+i+1==(r->block1[l]-r->block0[l]+1)*(r->block1[l]-r->block0[l]+1))
510            c=')';
511          StringAppend("%d%c" ,r->wvhdl[l][i+j],c);
512        }
513      }
514      else
515        StringAppend("(%d)",r->block1[l]-r->block0[l]+1);
516    }
517    if (l==nblocks) return omStrDup(StringAppendS(""));
518    StringAppendS(",");
519  }
520}
521
522char * rVarStr(ring r)
523{
524  int i;
525  int l=2;
526  char *s;
527
528  for (i=0; i<r->N; i++)
529  {
530    l+=strlen(r->names[i])+1;
531  }
532  s=(char *)omAlloc(l);
533  s[0]='\0';
534  for (i=0; i<r->N-1; i++)
535  {
536    strcat(s,r->names[i]);
537    strcat(s,",");
538  }
539  strcat(s,r->names[i]);
540  return s;
541}
542
543char * rCharStr(ring r)
544{
545  char *s;
546  int i;
547
548  if (r->parameter==NULL)
549  {
550    i=r->ch;
551    if(i==-1)
552      s=omStrDup("real");                    /* R */
553    else
554    {
555      s=(char *)omAlloc(6);
556      sprintf(s,"%d",i);                   /* Q, Z/p */
557    }
558    return s;
559  }
560  if (rField_is_long_C(r))
561  {
562    s=(char *)omAlloc(21+strlen(r->parameter[0]));
563    sprintf(s,"complex,%d,%s",r->float_len,r->parameter[0]);   /* C */
564    return s;
565  }
566  int l=0;
567  for(i=0; i<rPar(r);i++)
568  {
569    l+=(strlen(r->parameter[i])+1);
570  }
571  s=(char *)omAlloc(l+6);
572  s[0]='\0';
573  if (r->ch<0)       sprintf(s,"%d",-r->ch); /* Fp(a) */
574  else if (r->ch==1) sprintf(s,"0");         /* Q(a)  */
575  else
576  {
577    sprintf(s,"%d,%s",r->ch,r->parameter[0]); /* Fq  */
578    return s;
579  }
580  char tt[2];
581  tt[0]=',';
582  tt[1]='\0';
583  for(i=0; i<rPar(r);i++)
584  {
585    strcat(s,tt);
586    strcat(s,r->parameter[i]);
587  }
588  return s;
589}
590
591char * rParStr(ring r)
592{
593  if (r->parameter==NULL) return omStrDup("");
594
595  int i;
596  int l=2;
597
598  for (i=0; i<rPar(r); i++)
599  {
600    l+=strlen(r->parameter[i])+1;
601  }
602  char *s=(char *)omAlloc(l);
603  s[0]='\0';
604  for (i=0; i<rPar(r)-1; i++)
605  {
606    strcat(s,r->parameter[i]);
607    strcat(s,",");
608  }
609  strcat(s,r->parameter[i]);
610  return s;
611}
612
613char * rString(ring r)
614{
615  char *ch=rCharStr(r);
616  char *var=rVarStr(r);
617  char *ord=rOrdStr(r);
618  char *res=(char *)omAlloc(strlen(ch)+strlen(var)+strlen(ord)+9);
619  sprintf(res,"(%s),(%s),(%s)",ch,var,ord);
620  omFree((ADDRESS)ch);
621  omFree((ADDRESS)var);
622  omFree((ADDRESS)ord);
623  return res;
624}
625
626int  rIsExtension(ring r)
627{
628  return (r->parameter!=NULL); /* R, Q, Fp: FALSE */
629}
630
631int  rIsExtension()
632{
633  return rIsExtension( currRing );
634}
635
636int rChar(ring r)
637{
638  if (rField_is_numeric(r))
639    return 0;
640  if (!rIsExtension(r)) /* Q, Fp */
641    return r->ch;
642  if (rField_is_Zp_a(r))  /* Fp(a)  */
643    return -r->ch;
644  if (rField_is_Q_a(r))   /* Q(a)  */
645    return 0;
646  /*else*/               /* GF(p,n) */
647  {
648    if ((r->ch & 1)==0) return 2;
649    int i=3;
650    while ((r->ch % i)!=0) i+=2;
651    return i;
652  }
653}
654
655/*2
656 *returns -1 for not compatible, (sum is undefined)
657 *         0 for equal, (and sum)
658 *         1 for compatible (and sum)
659 */
660int rSum(ring r1, ring r2, ring &sum)
661{
662  if (r1==r2)
663  {
664    sum=r1;
665    r1->ref++;
666    return 0;
667  }
668  ring save=currRing;
669  ip_sring tmpR;
670  memset(&tmpR,0,sizeof(tmpR));
671  /* check coeff. field =====================================================*/
672  if (rInternalChar(r1)==rInternalChar(r2))
673  {
674    tmpR.ch=rInternalChar(r1);
675    if (rField_is_Q(r1)||rField_is_Zp(r1)||rField_is_GF(r1)) /*Q, Z/p, GF(p,n)*/
676    {
677      if (r1->parameter!=NULL)
678      {
679        if (strcmp(r1->parameter[0],r2->parameter[0])==0) /* 1 char */
680        {
681          tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
682          tmpR.parameter[0]=omStrDup(r1->parameter[0]);
683          tmpR.P=1;
684        }
685        else
686        {
687          WerrorS("GF(p,n)+GF(p,n)");
688          return -1;
689        }
690      }
691    }
692    else if ((r1->ch==1)||(r1->ch<-1)) /* Q(a),Z/p(a) */
693    {
694      if (r1->minpoly!=NULL)
695      {
696        if (r2->minpoly!=NULL)
697        {
698          // HANNES: TODO: delete nSetChar
699          rChangeCurrRing(r1);
700          if ((strcmp(r1->parameter[0],r2->parameter[0])==0) /* 1 char */
701              && n_Equal(r1->minpoly,r2->minpoly, r1))
702          {
703            tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
704            tmpR.parameter[0]=omStrDup(r1->parameter[0]);
705            tmpR.minpoly=n_Copy(r1->minpoly, r1);
706            tmpR.P=1;
707            // HANNES: TODO: delete nSetChar
708            rChangeCurrRing(save);
709          }
710          else
711          {
712            // HANNES: TODO: delete nSetChar
713            rChangeCurrRing(save);
714            WerrorS("different minpolys");
715            return -1;
716          }
717        }
718        else
719        {
720          if ((strcmp(r1->parameter[0],r2->parameter[0])==0) /* 1 char */
721              && (rPar(r2)==1))
722          {
723            tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
724            tmpR.parameter[0]=omStrDup(r1->parameter[0]);
725            tmpR.P=1;
726            tmpR.minpoly=n_Copy(r1->minpoly, r1);
727          }
728          else
729          {
730            WerrorS("different parameters and minpoly!=0");
731            return -1;
732          }
733        }
734      }
735      else /* r1->minpoly==NULL */
736      {
737        if (r2->minpoly!=NULL)
738        {
739          if ((strcmp(r1->parameter[0],r2->parameter[0])==0) /* 1 char */
740              && (rPar(r1)==1))
741          {
742            tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
743            tmpR.parameter[0]=omStrDup(r1->parameter[0]);
744            tmpR.P=1;
745            tmpR.minpoly=n_Copy(r2->minpoly, r2);
746          }
747          else
748          {
749            WerrorS("different parameters and minpoly!=0");
750            return -1;
751          }
752        }
753        else
754        {
755          int len=rPar(r1)+rPar(r2);
756          tmpR.parameter=(char **)omAlloc0(len*sizeof(char_ptr));
757          int i;
758          for (i=0;i<rPar(r1);i++)
759          {
760            tmpR.parameter[i]=omStrDup(r1->parameter[i]);
761          }
762          int j,l;
763          for(j=0;j<rPar(r2);j++)
764          {
765            for(l=0;l<i;l++)
766            {
767              if(strcmp(tmpR.parameter[l],r2->parameter[j])==0)
768                break;
769            }
770            if (l==i)
771            {
772              tmpR.parameter[i]=omStrDup(r2->parameter[j]);
773              i++;
774            }
775          }
776          if (i!=len)
777          {
778            tmpR.parameter=(char**)omReallocSize(tmpR.parameter,len*sizeof(char_ptr),i*sizeof(char_ptr));
779          }
780          tmpR.P=i;
781        }
782      }
783    }
784  }
785  else /* r1->ch!=r2->ch */
786  {
787    if (r1->ch<-1) /* Z/p(a) */
788    {
789      if ((r2->ch==0) /* Q */
790          || (r2->ch==-r1->ch)) /* Z/p */
791      {
792        tmpR.ch=rInternalChar(r1);
793        tmpR.P=rPar(r1);
794        tmpR.parameter=(char **)omAlloc(rPar(r1)*sizeof(char_ptr));
795        int i;
796        for (i=0;i<rPar(r1);i++)
797        {
798          tmpR.parameter[i]=omStrDup(r1->parameter[i]);
799        }
800        if (r1->minpoly!=NULL)
801        {
802          tmpR.minpoly=n_Copy(r1->minpoly, r1);
803        }
804      }
805      else  /* R, Q(a),Z/q,Z/p(a),GF(p,n) */
806      {
807        WerrorS("Z/p(a)+(R,Q(a),Z/q(a),GF(q,n))");
808        return -1;
809      }
810    }
811    else if (r1->ch==-1) /* R */
812    {
813      WerrorS("R+..");
814      return -1;
815    }
816    else if (r1->ch==0) /* Q */
817    {
818      if ((r2->ch<-1)||(r2->ch==1)) /* Z/p(a),Q(a) */
819      {
820        tmpR.ch=rInternalChar(r2);
821        tmpR.P=rPar(r2);
822        tmpR.parameter=(char **)omAlloc(rPar(r2)*sizeof(char_ptr));
823        int i;
824        for (i=0;i<rPar(r2);i++)
825        {
826          tmpR.parameter[i]=omStrDup(r2->parameter[i]);
827        }
828        if (r2->minpoly!=NULL)
829        {
830          tmpR.minpoly=n_Copy(r2->minpoly, r2);
831        }
832      }
833      else if (r2->ch>1) /* Z/p,GF(p,n) */
834      {
835        tmpR.ch=r2->ch;
836        if (r2->parameter!=NULL)
837        {
838          tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
839          tmpR.P=1;
840          tmpR.parameter[0]=omStrDup(r2->parameter[0]);
841        }
842      }
843      else
844      {
845        WerrorS("Q+R");
846        return -1; /* R */
847      }
848    }
849    else if (r1->ch==1) /* Q(a) */
850    {
851      if (r2->ch==0) /* Q */
852      {
853        tmpR.ch=rInternalChar(r1);
854        tmpR.P=rPar(r1);
855        tmpR.parameter=(char **)omAlloc(rPar(r1)*sizeof(char_ptr));
856        int i;
857        for(i=0;i<rPar(r1);i++)
858        {
859          tmpR.parameter[i]=omStrDup(r1->parameter[i]);
860        }
861        if (r1->minpoly!=NULL)
862        {
863          tmpR.minpoly=n_Copy(r1->minpoly, r1);
864        }
865      }
866      else  /* R, Z/p,GF(p,n) */
867      {
868        WerrorS("Q(a)+(R,Z/p,GF(p,n))");
869        return -1;
870      }
871    }
872    else /* r1->ch >=2 , Z/p */
873    {
874      if (r2->ch==0) /* Q */
875      {
876        tmpR.ch=r1->ch;
877      }
878      else if (r2->ch==-r1->ch) /* Z/p(a) */
879      {
880        tmpR.ch=rInternalChar(r2);
881        tmpR.P=rPar(r2);
882        tmpR.parameter=(char **)omAlloc(rPar(r2)*sizeof(char_ptr));
883        int i;
884        for(i=0;i<rPar(r2);i++)
885        {
886          tmpR.parameter[i]=omStrDup(r2->parameter[i]);
887        }
888        if (r2->minpoly!=NULL)
889        {
890          tmpR.minpoly=n_Copy(r2->minpoly, r2);
891        }
892      }
893      else
894      {
895        WerrorS("Z/p+(GF(q,n),Z/q(a),R,Q(a))");
896        return -1; /* GF(p,n),Z/q(a),R,Q(a) */
897      }
898    }
899  }
900  /* variable names ========================================================*/
901  int i,j,k;
902  int l=r1->N+r2->N;
903  char **names=(char **)omAlloc0(l*sizeof(char_ptr));
904  k=0;
905
906  // collect all varnames from r1, except those which are parameters
907  // of r2, or those which are the empty string
908  for (i=0;i<r1->N;i++)
909  {
910    BOOLEAN b=TRUE;
911
912    if (*(r1->names[i]) == '\0')
913      b = FALSE;
914    else if ((r2->parameter!=NULL) && (strlen(r1->names[i])==1))
915    {
916      for(j=0;j<rPar(r2);j++)
917      {
918        if (strcmp(r1->names[i],r2->parameter[j])==0)
919        {
920          b=FALSE;
921          break;
922        }
923      }
924    }
925
926    if (b)
927    {
928      //Print("name : %d: %s\n",k,r1->names[i]);
929      names[k]=omStrDup(r1->names[i]);
930      k++;
931    }
932    //else
933    //  Print("no name (par1) %s\n",r1->names[i]);
934  }
935  // Add variables from r2, except those which are parameters of r1
936  // those which are empty strings, and those which equal a var of r1
937  for(i=0;i<r2->N;i++)
938  {
939    BOOLEAN b=TRUE;
940
941    if (*(r2->names[i]) == '\0')
942      b = FALSE;
943    else if ((r1->parameter!=NULL) && (strlen(r2->names[i])==1))
944    {
945      for(j=0;j<rPar(r1);j++)
946      {
947        if (strcmp(r2->names[i],r1->parameter[j])==0)
948        {
949          b=FALSE;
950          break;
951        }
952      }
953    }
954
955    if (b)
956    {
957      for(j=0;j<r1->N;j++)
958      {
959        if (strcmp(r1->names[j],r2->names[i])==0)
960        {
961          b=FALSE;
962          break;
963        }
964      }
965      if (b)
966      {
967        //Print("name : %d : %s\n",k,r2->names[i]);
968        names[k]=omStrDup(r2->names[i]);
969        k++;
970      }
971      //else
972      //  Print("no name (var): %s\n",r2->names[i]);
973    }
974    //else
975    //  Print("no name (par): %s\n",r2->names[i]);
976  }
977  // check whether we found any vars at all
978  if (k == 0)
979  {
980    names[k]=omStrDup("");
981    k=1;
982  }
983  tmpR.N=k;
984  tmpR.names=names;
985  /* ordering *======================================================== */
986  tmpR.OrdSgn=1;
987  if ((r1->order[0]==ringorder_unspec)
988      && (r2->order[0]==ringorder_unspec))
989  {
990    tmpR.order=(int*)omAlloc(3*sizeof(int));
991    tmpR.block0=(int*)omAlloc(3*sizeof(int));
992    tmpR.block1=(int*)omAlloc(3*sizeof(int));
993    tmpR.wvhdl=(int**)omAlloc0(3*sizeof(int_ptr));
994    tmpR.order[0]=ringorder_unspec;
995    tmpR.order[1]=ringorder_C;
996    tmpR.order[2]=0;
997    tmpR.block0[0]=1;
998    tmpR.block1[0]=tmpR.N;
999  }
1000  else if (l==k) /* r3=r1+r2 */
1001  {
1002    int b;
1003    ring rb;
1004    if (r1->order[0]==ringorder_unspec)
1005    {
1006      /* extend order of r2 to r3 */
1007      b=rBlocks(r2);
1008      rb=r2;
1009      tmpR.OrdSgn=r2->OrdSgn;
1010    }
1011    else if (r2->order[0]==ringorder_unspec)
1012    {
1013      /* extend order of r1 to r3 */
1014      b=rBlocks(r1);
1015      rb=r1;
1016      tmpR.OrdSgn=r1->OrdSgn;
1017    }
1018    else
1019    {
1020      b=rBlocks(r1)+rBlocks(r2)-2; /* for only one order C, only one 0 */
1021      rb=NULL;
1022    }
1023    tmpR.order=(int*)omAlloc0(b*sizeof(int));
1024    tmpR.block0=(int*)omAlloc0(b*sizeof(int));
1025    tmpR.block1=(int*)omAlloc0(b*sizeof(int));
1026    tmpR.wvhdl=(int**)omAlloc0(b*sizeof(int_ptr));
1027    /* weights not implemented yet ...*/
1028    if (rb!=NULL)
1029    {
1030      for (i=0;i<b;i++)
1031      {
1032        tmpR.order[i]=rb->order[i];
1033        tmpR.block0[i]=rb->block0[i];
1034        tmpR.block1[i]=rb->block1[i];
1035        if (rb->wvhdl[i]!=NULL)
1036          WarnS("rSum: weights not implemented");
1037      }
1038      tmpR.block0[0]=1;
1039    }
1040    else /* ring sum for complete rings */
1041    {
1042      for (i=0;r1->order[i]!=0;i++)
1043      {
1044        tmpR.order[i]=r1->order[i];
1045        tmpR.block0[i]=r1->block0[i];
1046        tmpR.block1[i]=r1->block1[i];
1047        if (r1->wvhdl[i]!=NULL)
1048          tmpR.wvhdl[i] = (int*) omMemDup(r1->wvhdl[i]);
1049      }
1050      j=i;
1051      i--;
1052      if ((r1->order[i]==ringorder_c)
1053          ||(r1->order[i]==ringorder_C))
1054      {
1055        j--;
1056        tmpR.order[b-2]=r1->order[i];
1057      }
1058      for (i=0;r2->order[i]!=0;i++)
1059      {
1060        if ((r2->order[i]!=ringorder_c)
1061            &&(r2->order[i]!=ringorder_C))
1062        {
1063          tmpR.order[j]=r2->order[i];
1064          tmpR.block0[j]=r2->block0[i]+r1->N;
1065          tmpR.block1[j]=r2->block1[i]+r1->N;
1066          if (r2->wvhdl[i]!=NULL)
1067          {
1068            tmpR.wvhdl[j] = (int*) omMemDup(r2->wvhdl[i]);
1069          }
1070          j++;
1071        }
1072      }
1073      if((r1->OrdSgn==-1)||(r2->OrdSgn==-1))
1074        tmpR.OrdSgn=-1;
1075    }
1076  }
1077  else if ((k==r1->N) && (k==r2->N)) /* r1 and r2 are "quite" the same ring */
1078    /* copy r1, because we have the variables from r1 */
1079  {
1080    int b=rBlocks(r1);
1081
1082    tmpR.order=(int*)omAlloc0(b*sizeof(int));
1083    tmpR.block0=(int*)omAlloc0(b*sizeof(int));
1084    tmpR.block1=(int*)omAlloc0(b*sizeof(int));
1085    tmpR.wvhdl=(int**)omAlloc0(b*sizeof(int_ptr));
1086    /* weights not implemented yet ...*/
1087    for (i=0;i<b;i++)
1088    {
1089      tmpR.order[i]=r1->order[i];
1090      tmpR.block0[i]=r1->block0[i];
1091      tmpR.block1[i]=r1->block1[i];
1092      if (r1->wvhdl[i]!=NULL)
1093      {
1094        tmpR.wvhdl[i] = (int*) omMemDup(r1->wvhdl[i]);
1095      }
1096    }
1097    tmpR.OrdSgn=r1->OrdSgn;
1098  }
1099  else
1100  {
1101    for(i=0;i<k;i++) omFree((ADDRESS)tmpR.names[i]);
1102    omFreeSize((ADDRESS)names,tmpR.N*sizeof(char_ptr));
1103    Werror("difficulties with variables: %d,%d -> %d",rVar(r1),rVar(r2),k);
1104    return -1;
1105  }
1106  sum=(ring)omAllocBin(ip_sring_bin);
1107  memcpy(sum,&tmpR,sizeof(ip_sring));
1108  rComplete(sum);
1109//#ifdef RDEBUG
1110//  rDebugPrint(sum);
1111//#endif
1112#ifdef HAVE_PLURAL
1113  ring old_ring = currRing;
1114  BOOLEAN R1_is_nc = rIsPluralRing(r1);
1115  BOOLEAN R2_is_nc = rIsPluralRing(r2);
1116  if ( (R1_is_nc) || (R2_is_nc))
1117  {
1118    rChangeCurrRing(r1); /* since rCopy works well only in currRing */
1119    ring R1 = rCopy(r1);
1120    rChangeCurrRing(r2);
1121    ring R2 = rCopy(r2);
1122    rChangeCurrRing(sum);
1123    /* basic nc constructions  */
1124    sum->nc = (nc_struct *)omAlloc0(sizeof(nc_struct));
1125    sum->nc->ref = 1;
1126    sum->nc->basering = sum;
1127    if ( !R1_is_nc ) nc_rCreateNCcomm(R1);
1128    if ( !R2_is_nc ) nc_rCreateNCcomm(R2);
1129    /* nc->type's */
1130    sum->nc->type = nc_undef;
1131    nc_type t1 = R1->nc->type, t2 = R2->nc->type;
1132    if ( t1==t2) sum->nc->type = t1;
1133    else
1134    {
1135      if ( (t1==nc_general) || (t2==nc_general) ) sum->nc->type = nc_general;
1136    }
1137    if (sum->nc->type == nc_undef) /* not yet done */
1138    {
1139      switch (t1)
1140      {
1141        case nc_comm:
1142          sum->nc->type = t2;
1143          break;
1144        case nc_lie:
1145          switch(t2)
1146          {
1147            case nc_skew:
1148              sum->nc->type = nc_general;  break;
1149            case nc_comm:
1150              sum->nc->type = nc_lie;  break;
1151            default:
1152              /*sum->nc->type = nc_undef;*/  break;
1153          }
1154          break;
1155        case nc_skew:
1156          switch(t2)
1157          {
1158            case nc_lie:
1159              sum->nc->type = nc_lie;  break;
1160            case nc_comm:
1161              sum->nc->type = nc_skew;  break;
1162            default:
1163              /*sum->nc->type = nc_undef;*/  break;
1164          }
1165        default:
1166          /*sum->nc->type = nc_undef;*/
1167          break;
1168      }
1169    }
1170    if (sum->nc->type == nc_undef)
1171      WarnS("Error on recognizing nc types");
1172    /* multiplication matrices business: */
1173    /* find permutations of vars and pars */
1174    int *perm1 = (int *)omAlloc0((rVar(R1)+1)*sizeof(int));
1175    int *par_perm1 = NULL;
1176    if (rPar(R1)!=0) par_perm1=(int *)omAlloc0((rPar(R1)+1)*sizeof(int));
1177    int *perm2 = (int *)omAlloc0((rVar(R2)+1)*sizeof(int));
1178    int *par_perm2 = NULL;
1179    if (rPar(R2)!=0) par_perm2=(int *)omAlloc0((rPar(R2)+1)*sizeof(int));
1180    maFindPerm(R1->names,  rVar(R1),  R1->parameter,  rPar(R1),
1181               sum->names, rVar(sum), sum->parameter, rPar(sum),
1182               perm1, par_perm1, sum->ch);
1183    maFindPerm(R2->names,  rVar(R2),  R2->parameter,  rPar(R2),
1184               sum->names, rVar(sum), sum->parameter, rPar(sum),
1185               perm2, par_perm2, sum->ch);
1186    nMapFunc nMap1 = nSetMap(R1);
1187    nMapFunc nMap2 = nSetMap(R2);
1188    matrix C1 = R1->nc->C, C2 = R2->nc->C;
1189    matrix D1 = R1->nc->D, D2 = R2->nc->D;
1190    int l = rVar(R1) + rVar(R2);
1191    matrix C  = mpNew(l,l);
1192    matrix D  = mpNew(l,l);
1193    int param_shift = 0;
1194    for (i=1; i<= rVar(R1) + rVar(R2); i++)
1195    {
1196      for (j= i+1; j<= rVar(R1) + rVar(R2); j++)
1197      {
1198        MATELEM(C,i,j) = pOne();
1199      }
1200    }
1201    for (i=1; i< rVar(R1); i++)
1202    {
1203      for (j=i+1; j<=rVar(R1); j++)
1204      {
1205
1206        MATELEM(C,i,j) = pPermPoly(MATELEM(C1,i,j),perm1,R1,nMap1,par_perm1,rPar(R1));
1207        if (MATELEM(D1,i,j) != NULL)
1208        {
1209          MATELEM(D,i,j) = pPermPoly(MATELEM(D1,i,j),perm1,R1,nMap1,par_perm1,rPar(R1));
1210        }
1211      }
1212    }
1213    for (i=1; i< rVar(R2); i++)
1214    {
1215      for (j=i+1; j<=rVar(R2); j++)
1216      {
1217        MATELEM(C,rVar(R1)+i,rVar(R1)+j) = pPermPoly(MATELEM(C2,i,j),perm2,R2,nMap2,par_perm2,rPar(R2));
1218              if (MATELEM(D2,i,j) != NULL)
1219        {
1220          MATELEM(D,rVar(R1)+i,rVar(R1)+j) = pPermPoly(MATELEM(D2,i,j),perm2,R2,nMap2,par_perm2,rPar(R2));
1221        }
1222      }
1223    }
1224    idTest((ideal)C);
1225    idTest((ideal)D);
1226    sum->nc->C = C;
1227    sum->nc->D = D;
1228    if (nc_InitMultiplication(sum))
1229      WarnS("Error initializing multiplication!");
1230    sum->nc->IsSkewConstant =(int)((R1->nc->IsSkewConstant) && (R2->nc->IsSkewConstant));
1231    /* delete R1, R2*/
1232    rDelete(R1);
1233    rDelete(R2);
1234    /* delete perm arrays */
1235    if (perm1!=NULL) omFree((ADDRESS)perm1);
1236    if (perm2!=NULL) omFree((ADDRESS)perm2);
1237    if (par_perm1!=NULL) omFree((ADDRESS)par_perm1);
1238    if (par_perm2!=NULL) omFree((ADDRESS)par_perm2);
1239    rChangeCurrRing(old_ring);
1240  }
1241#endif
1242  ideal Q=NULL;
1243  ideal Q1=NULL, Q2=NULL;
1244  ring old_ring2 = currRing;
1245  if (r1->qideal!=NULL)
1246  {
1247    rChangeCurrRing(sum);
1248//     if (r2->qideal!=NULL)
1249//     {
1250//       WerrorS("todo: qring+qring");
1251//       return -1;
1252//     }
1253//     else
1254//     {}
1255    /* these were defined in the Plural Part above... */
1256    int *perm1 = (int *)omAlloc0((rVar(r1)+1)*sizeof(int));
1257    int *par_perm1 = NULL;
1258    if (rPar(r1)!=0) par_perm1=(int *)omAlloc0((rPar(r1)+1)*sizeof(int));
1259    maFindPerm(r1->names,  rVar(r1),  r1->parameter,  rPar(r1),
1260               sum->names, rVar(sum), sum->parameter, rPar(sum),
1261               perm1, par_perm1, sum->ch);
1262    nMapFunc nMap1 = nSetMap(r1);
1263    Q1 = idInit(IDELEMS(r1->qideal),1);
1264    for (int for_i=0;for_i<IDELEMS(r1->qideal);for_i++)
1265      Q1->m[for_i] = pPermPoly(r1->qideal->m[for_i],perm1,r1,nMap1,par_perm1,rPar(r1));
1266    omFree((ADDRESS)perm1);
1267  }
1268
1269  if (r2->qideal!=NULL)
1270  {
1271    if (currRing!=sum)
1272      rChangeCurrRing(sum);
1273    int *perm2 = (int *)omAlloc0((rVar(r2)+1)*sizeof(int));
1274    int *par_perm2 = NULL;
1275    if (rPar(r2)!=0) par_perm2=(int *)omAlloc0((rPar(r2)+1)*sizeof(int));
1276    maFindPerm(r2->names,  rVar(r2),  r2->parameter,  rPar(r2),
1277               sum->names, rVar(sum), sum->parameter, rPar(sum),
1278               perm2, par_perm2, sum->ch);
1279    nMapFunc nMap2 = nSetMap(r2);
1280    Q2 = idInit(IDELEMS(r2->qideal),1);
1281    for (int for_i=0;for_i<IDELEMS(r2->qideal);for_i++)
1282      Q2->m[for_i] = pPermPoly(r2->qideal->m[for_i],perm2,r2,nMap2,par_perm2,rPar(r2));
1283    omFree((ADDRESS)perm2);
1284  }
1285  if ( (Q1!=NULL) || ( Q2!=NULL))
1286  {
1287    Q = idSimpleAdd(Q1,Q2);
1288    rChangeCurrRing(old_ring2);
1289  }
1290  sum->qideal = Q;
1291  return 1;
1292}
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.