source: git/kernel/ring.cc @ 994445

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