source: git/kernel/ring.cc @ 7bdf71

spielwiese
Last change on this file since 7bdf71 was 7bdf71, checked in by Hans Schönemann <hannes@…>, 14 years ago
*hannes: rCopy0 and copy_ideal git-svn-id: file:///usr/local/Singular/svn/trunk@12017 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 137.8 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: ring.cc,v 1.125 2009-07-28 08:49:15 Singular Exp $ */
5
6/*
7* ABSTRACT - the interpreter related ring operations
8*/
9
10/* includes */
11#include <math.h>
12#include "mod2.h"
13
14#ifndef NDEBUG
15# define MYTEST 0
16#else /* ifndef NDEBUG */
17# define MYTEST 0
18#endif /* ifndef NDEBUG */
19
20#include "structs.h"
21#include "omalloc.h"
22#include "polys.h"
23#include "numbers.h"
24#include "febase.h"
25#include "intvec.h"
26#include "longalg.h"
27#include "ffields.h"
28#include "ideals.h"
29#include "ring.h"
30#include "prCopy.h"
31#include "../Singular/ipshell.h"
32#include "p_Procs.h"
33#ifdef HAVE_PLURAL
34#include "gring.h"
35#include "sca.h"
36#endif
37#include "maps.h"
38#include "matpol.h"
39#ifdef HAVE_FACTORY
40#include "factory.h"
41#endif
42
43#define BITS_PER_LONG 8*SIZEOF_LONG
44
45static const char * const ringorder_name[] =
46{
47  " ?", ///< ringorder_no = 0,
48  "a", ///< ringorder_a,
49  "A", ///< ringorder_a64,
50  "c", ///< ringorder_c,
51  "C", ///< ringorder_C,
52  "M", ///< ringorder_M,
53  "S", ///< ringorder_S,
54  "s", ///< ringorder_s,
55  "lp", ///< ringorder_lp,
56  "dp", ///< ringorder_dp,
57  "rp", ///< ringorder_rp,
58  "Dp", ///< ringorder_Dp,
59  "wp", ///< ringorder_wp,
60  "Wp", ///< ringorder_Wp,
61  "ls", ///< ringorder_ls,
62  "ds", ///< ringorder_ds,
63  "Ds", ///< ringorder_Ds,
64  "ws", ///< ringorder_ws,
65  "Ws", ///< ringorder_Ws,
66  "L", ///< ringorder_L,
67  "aa", ///< ringorder_aa
68  "rs", ///< ringorder_rs,
69  "IS", ///<  ringorder_IS
70  " _" ///< ringorder_unspec
71};
72
73const char * rSimpleOrdStr(int ord)
74{
75  return ringorder_name[ord];
76}
77
78/// unconditionally deletes fields in r
79void rDelete(ring r);
80/// set r->VarL_Size, r->VarL_Offset, r->VarL_LowIndex
81static void rSetVarL(ring r);
82/// get r->divmask depending on bits per exponent
83static unsigned long rGetDivMask(int bits);
84/// right-adjust r->VarOffset
85static void rRightAdjustVarOffset(ring r);
86static void rOptimizeLDeg(ring r);
87
88/*0 implementation*/
89//BOOLEAN rField_is_R(ring r=currRing)
90//{
91//  if (r->ch== -1)
92//  {
93//    if (r->float_len==(short)0) return TRUE;
94//  }
95//  return FALSE;
96//}
97
98/// internally changes the gloabl ring and resets the relevant
99/// global variables:
100void rChangeCurrRing(ring r)
101{
102 // if ((currRing!=NULL) && (currRing->minpoly!=NULL))
103 // {
104 //   omCheckAddr(currRing->minpoly);
105 // }
106  /*------------ set global ring vars --------------------------------*/
107  currRing = r;
108  currQuotient=NULL;
109  if (r != NULL)
110  {
111    rTest(r);
112    /*------------ set global ring vars --------------------------------*/
113    currQuotient=r->qideal;
114
115    /*------------ global variables related to coefficients ------------*/
116    nSetChar(r);
117
118    /*------------ global variables related to polys -------------------*/
119    pSetGlobals(r);
120    /*------------ global variables related to factory -------------------*/
121#ifdef HAVE_FACTORY
122    //int c=ABS(nGetChar());
123    //if (c==1) c=0;
124    //setCharacteristic( c );
125#endif
126  }
127}
128
129void rNameCheck(ring R)
130{
131  int i,j;
132  for(i=0;i<R->N-1;i++)
133  {
134    for(j=i+1;j<R->N;j++)
135    {
136      if (strcmp(R->names[i],R->names[j])==0)
137      {
138        Warn("name conflict var(%d) and var(%d): `%s`, rename to `@(%d)`",i+1,j+1,R->names[i],j+1);
139        omFree(R->names[j]);
140        R->names[j]=(char *)omAlloc(10);
141        sprintf(R->names[j],"@(%d)",j+1);
142      }
143    }
144  }
145  for(i=0;i<R->P; i++)
146  {
147    for(j=0;j<R->N;j++)
148    {
149      if (strcmp(R->parameter[i],R->names[j])==0)
150      {
151        Warn("name conflict par(%d) and var(%d): `%s`, rename to `@@(%d)`",i+1,j+1,R->names[j],i+1);
152        omFree(R->parameter[i]);
153        R->parameter[i]=(char *)omAlloc(10);
154        sprintf(R->parameter[i],"@@(%d)",i+1);
155      }
156    }
157  }
158}
159
160ring rDefault(int ch, int N, char **n)
161{
162  ring r=(ring) omAlloc0Bin(sip_sring_bin);
163  r->ch    = ch;
164  r->N     = N;
165  /*r->P     = 0; Alloc0 */
166  /*names*/
167  r->names = (char **) omAlloc0(N * sizeof(char_ptr));
168  int i;
169  for(i=0;i<N;i++)
170  {
171    r->names[i]  = omStrDup(n[i]);
172  }
173  /*weights: entries for 2 blocks: NULL*/
174  r->wvhdl = (int **)omAlloc0(2 * sizeof(int_ptr));
175  /*order: lp,0*/
176  r->order = (int *) omAlloc(2* sizeof(int *));
177  r->block0 = (int *)omAlloc0(2 * sizeof(int *));
178  r->block1 = (int *)omAlloc0(2 * sizeof(int *));
179  /* ringorder dp for the first block: var 1..N */
180  r->order[0]  = ringorder_lp;
181  r->block0[0] = 1;
182  r->block1[0] = N;
183  /* the last block: everything is 0 */
184  r->order[1]  = 0;
185  /*polynomial ring*/
186  r->OrdSgn    = 1;
187
188  /* complete ring intializations */
189  rComplete(r);
190  return r;
191}
192
193///////////////////////////////////////////////////////////////////////////
194//
195// rInit: define a new ring from sleftv's
196//
197//-> ipshell.cc
198
199/////////////////////////////
200// Auxillary functions
201//
202
203// check intvec, describing the ordering
204BOOLEAN rCheckIV(intvec *iv)
205{
206  if ((iv->length()!=2)&&(iv->length()!=3))
207  {
208    WerrorS("weights only for orderings wp,ws,Wp,Ws,a,M");
209    return TRUE;
210  }
211  return FALSE;
212}
213
214int rTypeOfMatrixOrder(intvec * order)
215{
216  int i=0,j,typ=1;
217  int sz = (int)sqrt((double)(order->length()-2));
218  if ((sz*sz)!=(order->length()-2))
219  {
220    WerrorS("Matrix order is not a square matrix");
221    typ=0;
222  }
223  while ((i<sz) && (typ==1))
224  {
225    j=0;
226    while ((j<sz) && ((*order)[j*sz+i+2]==0)) j++;
227    if (j>=sz)
228    {
229      typ = 0;
230      WerrorS("Matrix order not complete");
231    }
232    else if ((*order)[j*sz+i+2]<0)
233      typ = -1;
234    else
235      i++;
236  }
237  return typ;
238}
239
240// set R->order, R->block, R->wvhdl, r->OrdSgn from sleftv
241BOOLEAN rSleftvOrdering2Ordering(sleftv *ord, ring R);
242
243// get array of strings from list of sleftv's
244BOOLEAN rSleftvList2StringArray(sleftv* sl, char** p);
245
246
247/*2
248 * set a new ring from the data:
249 s: name, chr: ch, varnames: rv, ordering: ord, typ: typ
250 */
251
252int r_IsRingVar(const char *n, ring r)
253{
254  if ((r!=NULL) && (r->names!=NULL))
255  {
256    for (int i=0; i<r->N; i++)
257    {
258      if (r->names[i]==NULL) return -1;
259      if (strcmp(n,r->names[i]) == 0) return (int)i;
260    }
261  }
262  return -1;
263}
264
265
266void rWrite(ring r)
267{
268  if ((r==NULL)||(r->order==NULL))
269    return; /*to avoid printing after errors....*/
270
271  int nblocks=rBlocks(r);
272
273  // omCheckAddrSize(r,sizeof(ip_sring));
274  omCheckAddrSize(r->order,nblocks*sizeof(int));
275  omCheckAddrSize(r->block0,nblocks*sizeof(int));
276  omCheckAddrSize(r->block1,nblocks*sizeof(int));
277  omCheckAddrSize(r->wvhdl,nblocks*sizeof(int_ptr));
278  omCheckAddrSize(r->names,r->N*sizeof(char_ptr));
279
280  nblocks--;
281
282
283  if (rField_is_GF(r))
284  {
285    Print("//   # ground field : %d\n",rInternalChar(r));
286    Print("//   primitive element : %s\n", r->parameter[0]);
287    if (r==currRing)
288    {
289      StringSetS("//   minpoly        : ");
290      nfShowMipo();PrintS(StringAppendS("\n"));
291    }
292  }
293#ifdef HAVE_RINGS
294  else if (rField_is_Ring(r))
295  {
296    PrintS("//   coeff. ring is : ");
297    if (rField_is_Ring_Z(r)) PrintS("Integers\n");
298    int l = mpz_sizeinbase(r->ringflaga, 10) + 2;
299    char* s = (char*) omAlloc(l);
300    mpz_get_str(s,10,r->ringflaga);
301    if (rField_is_Ring_ModN(r)) Print("Z/%s\n", s);
302    if (rField_is_Ring_2toM(r)) Print("Z/2^%lu\n", r->ringflagb);
303    if (rField_is_Ring_PtoM(r)) Print("Z/%s^%lu\n", s, r->ringflagb);
304    omFreeSize((ADDRESS)s, l);
305  }
306#endif
307  else
308  {
309    PrintS("//   characteristic : ");
310    if ( rField_is_R(r) )             PrintS("0 (real)\n");  /* R */
311    else if ( rField_is_long_R(r) )
312      Print("0 (real:%d digits, additional %d digits)\n",
313             r->float_len,r->float_len2);  /* long R */
314    else if ( rField_is_long_C(r) )
315      Print("0 (complex:%d digits, additional %d digits)\n",
316             r->float_len, r->float_len2);  /* long C */
317    else
318      Print ("%d\n",rChar(r)); /* Fp(a) */
319    if (r->parameter!=NULL)
320    {
321      Print ("//   %d parameter    : ",rPar(r));
322      char **sp=r->parameter;
323      int nop=0;
324      while (nop<rPar(r))
325      {
326        PrintS(*sp);
327        PrintS(" ");
328        sp++; nop++;
329      }
330      PrintS("\n//   minpoly        : ");
331      if ( rField_is_long_C(r) )
332      {
333        // i^2+1:
334        Print("(%s^2+1)\n",r->parameter[0]);
335      }
336      else if (r->minpoly==NULL)
337      {
338        PrintS("0\n");
339      }
340      else if (r==currRing)
341      {
342        StringSetS(""); nWrite(r->minpoly); PrintS(StringAppendS("\n"));
343      }
344      else
345      {
346        PrintS("...\n");
347      }
348      if (r->minideal!=NULL)
349      {
350        if (r==currRing) iiWriteMatrix((matrix)r->minideal,"//   minpolys",1,0);
351        else PrintS("//   minpolys=...");
352        PrintLn();
353      }
354    }
355  }
356  Print("//   number of vars : %d",r->N);
357
358  //for (nblocks=0; r->order[nblocks]; nblocks++);
359  nblocks=rBlocks(r)-1;
360
361  for (int l=0, nlen=0 ; l<nblocks; l++)
362  {
363    int i;
364    Print("\n//        block %3d : ",l+1);
365
366    Print("ordering %s", rSimpleOrdStr(r->order[l]));
367
368
369    if (r->order[l] == ringorder_s)
370    {
371      assume( l == 0 );
372#ifndef NDEBUG
373      Print("  syzcomp at %d",r->typ[l].data.syz.limit);
374#endif
375      continue;
376    }
377    else if (r->order[l] == ringorder_IS)
378    {
379#ifndef NDEBUG
380      if(r->block0[l] == 0 )
381        Print("::prefix");
382      else
383        Print("::suffix (sign: %d)", r->block0[l]);
384#endif
385      continue;
386    } else
387    if (
388    (  (r->order[l] >= ringorder_lp)
389    ||(r->order[l] == ringorder_M)
390    ||(r->order[l] == ringorder_a)
391    ||(r->order[l] == ringorder_a64)
392    ||(r->order[l] == ringorder_aa) ) && (r->order[l] < ringorder_IS) )
393    {
394      PrintS("\n//                  : names   ");
395      for (i = r->block0[l]-1; i<r->block1[l]; i++)
396      {
397        nlen = strlen(r->names[i]);
398        Print(" %s",r->names[i]);
399      }
400    }
401
402    if (r->wvhdl[l]!=NULL)
403    {
404      for (int j= 0;
405           j<(r->block1[l]-r->block0[l]+1)*(r->block1[l]-r->block0[l]+1);
406           j+=i)
407      {
408        PrintS("\n//                  : weights ");
409        for (i = 0; i<=r->block1[l]-r->block0[l]; i++)
410        {
411          if (r->order[l] == ringorder_a64)
412          {
413            int64 *w=(int64 *)r->wvhdl[l];
414            #if SIZEOF_LONG == 4
415                  Print("%*lld " ,nlen,w[i+j],i+j);
416            #else
417            Print(" %*ld"  ,nlen,w[i+j],i+j);
418            #endif
419          }
420          else
421            Print(" %*d" ,nlen,r->wvhdl[l][i+j],i+j);
422        }
423        if (r->order[l]!=ringorder_M) break;
424      }
425    }
426  }
427#ifdef HAVE_PLURAL
428  if(rIsPluralRing(r))
429  {
430    PrintS("\n//   noncommutative relations:");
431    if (r==currRing)
432    {
433      poly pl=NULL;
434      int nl;
435      int i,j;
436      for (i = 1; i<r->N; i++)
437      {
438        for (j = i+1; j<=r->N; j++)
439        {
440          nl = nIsOne(p_GetCoeff(MATELEM(r->GetNC()->C,i,j),r->GetNC()->basering));
441          if ( (MATELEM(r->GetNC()->D,i,j)!=NULL) || (!nl) )
442          {
443            Print("\n//    %s%s=",r->names[j-1],r->names[i-1]);
444            pl = MATELEM(r->GetNC()->MT[UPMATELEM(i,j,r->N)],1,1);
445            p_Write0(pl, r->GetNC()->basering, r->GetNC()->basering);
446          }
447        }
448      }
449    }
450    else PrintS(" ...");
451#ifdef PDEBUG
452    Print("\n//   noncommutative type:%d", (int)ncRingType(r));
453    Print("\n//      is skew constant:%d",r->GetNC()->IsSkewConstant);
454    Print("\n//                 ncref:%d",r->GetNC()->ref);
455    Print("\n//               commref:%d",r->ref);
456    Print("\n//               baseref:%d",r->GetNC()->basering->ref);
457    if( rIsSCA(r) )
458    {
459      Print("\n//   alternating variables: [%d, %d]", scaFirstAltVar(r), scaLastAltVar(r));
460      const ideal Q = SCAQuotient(r); // resides within r!
461      PrintS("\n//   quotient of sca by ideal");
462
463      if (Q!=NULL)
464      {
465        if (r==currRing)
466        {
467          PrintLn();
468          iiWriteMatrix((matrix)Q,"scaQ",1);
469        }
470        else PrintS(" ...");
471      } else
472        PrintS(" (NULL)");
473    }
474#endif
475  }
476#endif
477  if (r->qideal!=NULL)
478  {
479    PrintS("\n// quotient ring from ideal");
480    if (r==currRing)
481    {
482      PrintLn();
483      iiWriteMatrix((matrix)r->qideal,"_",1);
484    }
485    else PrintS(" ...");
486  }
487}
488
489void rDelete(ring r)
490{
491  int i, j;
492
493  if (r == NULL) return;
494
495#ifdef HAVE_PLURAL
496  if (rIsPluralRing(r))
497    nc_rKill(r);
498#endif
499
500  nKillChar(r);
501  rUnComplete(r);
502  // delete order stuff
503  if (r->order != NULL)
504  {
505    i=rBlocks(r);
506    assume(r->block0 != NULL && r->block1 != NULL && r->wvhdl != NULL);
507    // delete order
508    omFreeSize((ADDRESS)r->order,i*sizeof(int));
509    omFreeSize((ADDRESS)r->block0,i*sizeof(int));
510    omFreeSize((ADDRESS)r->block1,i*sizeof(int));
511    // delete weights
512    for (j=0; j<i; j++)
513    {
514      if (r->wvhdl[j]!=NULL)
515        omFree(r->wvhdl[j]);
516    }
517    omFreeSize((ADDRESS)r->wvhdl,i*sizeof(int *));
518  }
519  else
520  {
521    assume(r->block0 == NULL && r->block1 == NULL && r->wvhdl == NULL);
522  }
523
524  // delete varnames
525  if(r->names!=NULL)
526  {
527    for (i=0; i<r->N; i++)
528    {
529      if (r->names[i] != NULL) omFree((ADDRESS)r->names[i]);
530    }
531    omFreeSize((ADDRESS)r->names,r->N*sizeof(char_ptr));
532  }
533
534  // delete parameter
535  if (r->parameter!=NULL)
536  {
537    char **s=r->parameter;
538    j = 0;
539    while (j < rPar(r))
540    {
541      if (*s != NULL) omFree((ADDRESS)*s);
542      s++;
543      j++;
544    }
545    omFreeSize((ADDRESS)r->parameter,rPar(r)*sizeof(char_ptr));
546  }
547#ifdef HAVE_RINGS
548  if (r->ringflaga != NULL)
549  {
550    mpz_clear(r->ringflaga);
551    omFree((ADDRESS)r->ringflaga);
552  }
553#endif
554  omFreeBin(r, ip_sring_bin);
555}
556
557int rOrderName(char * ordername)
558{
559  int order=ringorder_unspec;
560  while (order!= 0)
561  {
562    if (strcmp(ordername,rSimpleOrdStr(order))==0)
563      break;
564    order--;
565  }
566  if (order==0) Werror("wrong ring order `%s`",ordername);
567  omFree((ADDRESS)ordername);
568  return order;
569}
570
571char * rOrdStr(ring r)
572{
573  if ((r==NULL)||(r->order==NULL)) return omStrDup("");
574  int nblocks,l,i;
575
576  for (nblocks=0; r->order[nblocks]; nblocks++);
577  nblocks--;
578
579  StringSetS("");
580  for (l=0; ; l++)
581  {
582    StringAppendS((char *)rSimpleOrdStr(r->order[l]));
583    if ((r->order[l] != ringorder_c) && (r->order[l] != ringorder_C))
584    {
585      if (r->wvhdl[l]!=NULL)
586      {
587        StringAppendS("(");
588        for (int j= 0;
589             j<(r->block1[l]-r->block0[l]+1)*(r->block1[l]-r->block0[l]+1);
590             j+=i+1)
591        {
592          char c=',';
593          if(r->order[l]==ringorder_a64)
594          {
595            int64 * w=(int64 *)r->wvhdl[l];
596            for (i = 0; i<r->block1[l]-r->block0[l]; i++)
597            {
598              StringAppend("%lld," ,w[i]);
599            }
600            StringAppend("%lld)" ,w[i]);
601            break;
602          }
603          else
604          {
605            for (i = 0; i<r->block1[l]-r->block0[l]; i++)
606            {
607              StringAppend("%d," ,r->wvhdl[l][i+j]);
608            }
609          }
610          if (r->order[l]!=ringorder_M)
611          {
612            StringAppend("%d)" ,r->wvhdl[l][i+j]);
613            break;
614          }
615          if (j+i+1==(r->block1[l]-r->block0[l]+1)*(r->block1[l]-r->block0[l]+1))
616            c=')';
617          StringAppend("%d%c" ,r->wvhdl[l][i+j],c);
618        }
619      }
620      else
621        StringAppend("(%d)",r->block1[l]-r->block0[l]+1);
622    }
623    if (l==nblocks) return omStrDup(StringAppendS(""));
624    StringAppendS(",");
625  }
626}
627
628char * rVarStr(ring r)
629{
630  if ((r==NULL)||(r->names==NULL)) return omStrDup("");
631  int i;
632  int l=2;
633  char *s;
634
635  for (i=0; i<r->N; i++)
636  {
637    l+=strlen(r->names[i])+1;
638  }
639  s=(char *)omAlloc(l);
640  s[0]='\0';
641  for (i=0; i<r->N-1; i++)
642  {
643    strcat(s,r->names[i]);
644    strcat(s,",");
645  }
646  strcat(s,r->names[i]);
647  return s;
648}
649
650char * rCharStr(ring r)
651{
652  char *s;
653  int i;
654
655#ifdef HAVE_RINGS
656  if (rField_is_Ring_Z(r))
657  {
658    s=omStrDup("integer");                   /* Z */
659    return s;
660  }
661  if(rField_is_Ring_2toM(r))
662  {
663    return omStrDup("coefficient ring");
664  }
665  if(rField_is_Ring_ModN(r))
666  {
667    return omStrDup("coefficient ring");
668  }
669  if(rField_is_Ring_PtoM(r))
670  {
671    return omStrDup("coefficient ring");
672  }
673#endif
674  if (r->parameter==NULL)
675  {
676    i=r->ch;
677    if(i==-1)
678      s=omStrDup("real");                    /* R */
679    else
680    {
681      s=(char *)omAlloc(MAX_INT_LEN+1);
682      sprintf(s,"%d",i);                   /* Q, Z/p */
683    }
684    return s;
685  }
686  if (rField_is_long_C(r))
687  {
688    s=(char *)omAlloc(21+strlen(r->parameter[0]));
689    sprintf(s,"complex,%d,%s",r->float_len,r->parameter[0]);   /* C */
690    return s;
691  }
692  int l=0;
693  for(i=0; i<rPar(r);i++)
694  {
695    l+=(strlen(r->parameter[i])+1);
696  }
697  s=(char *)omAlloc(l+MAX_INT_LEN+1);
698  s[0]='\0';
699  if (r->ch<0)       sprintf(s,"%d",-r->ch); /* Fp(a) */
700  else if (r->ch==1) sprintf(s,"0");         /* Q(a)  */
701  else
702  {
703    sprintf(s,"%d,%s",r->ch,r->parameter[0]); /* GF(q)  */
704    return s;
705  }
706  char tt[2];
707  tt[0]=',';
708  tt[1]='\0';
709  for(i=0; i<rPar(r);i++)
710  {
711    strcat(s,tt);
712    strcat(s,r->parameter[i]);
713  }
714  return s;
715}
716
717char * rParStr(ring r)
718{
719  if ((r==NULL)||(r->parameter==NULL)) return omStrDup("");
720
721  int i;
722  int l=2;
723
724  for (i=0; i<rPar(r); i++)
725  {
726    l+=strlen(r->parameter[i])+1;
727  }
728  char *s=(char *)omAlloc(l);
729  s[0]='\0';
730  for (i=0; i<rPar(r)-1; i++)
731  {
732    strcat(s,r->parameter[i]);
733    strcat(s,",");
734  }
735  strcat(s,r->parameter[i]);
736  return s;
737}
738
739char * rString(ring r)
740{
741  char *ch=rCharStr(r);
742  char *var=rVarStr(r);
743  char *ord=rOrdStr(r);
744  char *res=(char *)omAlloc(strlen(ch)+strlen(var)+strlen(ord)+9);
745  sprintf(res,"(%s),(%s),(%s)",ch,var,ord);
746  omFree((ADDRESS)ch);
747  omFree((ADDRESS)var);
748  omFree((ADDRESS)ord);
749  return res;
750}
751
752int  rIsExtension(ring r)
753{
754  return (r->parameter!=NULL); /* R, Q, Fp: FALSE */
755}
756
757int  rIsExtension()
758{
759  return rIsExtension( currRing );
760}
761
762int rChar(ring r)
763{
764  if (rField_is_numeric(r))
765    return 0;
766  if (!rIsExtension(r)) /* Q, Fp */
767    return r->ch;
768  if (rField_is_Zp_a(r))  /* Fp(a)  */
769    return -r->ch;
770  if (rField_is_Q_a(r))   /* Q(a)  */
771    return 0;
772  /*else*/               /* GF(p,n) */
773  {
774    if ((r->ch & 1)==0) return 2;
775    int i=3;
776    while ((r->ch % i)!=0) i+=2;
777    return i;
778  }
779}
780
781/*2
782 *returns -1 for not compatible, (sum is undefined)
783 *         1 for compatible (and sum)
784 */
785/* vartest: test for variable/paramter names
786* dp_dp: for comm. rings: use block order dp + dp/ds/wp
787*/
788int rTensor(ring r1, ring r2, ring &sum, BOOLEAN vartest, BOOLEAN dp_dp)
789{
790  ring save=currRing;
791  ip_sring tmpR;
792  memset(&tmpR,0,sizeof(tmpR));
793  /* check coeff. field =====================================================*/
794  if (rInternalChar(r1)==rInternalChar(r2))
795  {
796    tmpR.ch=rInternalChar(r1);
797    if (rField_is_Q(r1)||rField_is_Zp(r1)||rField_is_GF(r1)) /*Q, Z/p, GF(p,n)*/
798    {
799      if (r1->parameter!=NULL)
800      {
801        if (!vartest || (strcmp(r1->parameter[0],r2->parameter[0])==0)) /* 1 par */
802        {
803          tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
804          tmpR.parameter[0]=omStrDup(r1->parameter[0]);
805          tmpR.P=1;
806        }
807        else
808        {
809          WerrorS("GF(p,n)+GF(p,n)");
810          return -1;
811        }
812      }
813    }
814    else if ((r1->ch==1)||(r1->ch<-1)) /* Q(a),Z/p(a) */
815    {
816      if (r1->minpoly!=NULL)
817      {
818        if (r2->minpoly!=NULL)
819        {
820          // HANNES: TODO: delete nSetChar
821          rChangeCurrRing(r1);
822          if ((!vartest || (strcmp(r1->parameter[0],r2->parameter[0])==0)) /* 1 par */
823              && n_Equal(r1->minpoly,r2->minpoly, r1))
824          {
825            tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
826            tmpR.parameter[0]=omStrDup(r1->parameter[0]);
827            tmpR.minpoly=n_Copy(r1->minpoly, r1);
828            tmpR.P=1;
829            // HANNES: TODO: delete nSetChar
830            rChangeCurrRing(save);
831          }
832          else
833          {
834            // HANNES: TODO: delete nSetChar
835            rChangeCurrRing(save);
836            WerrorS("different minpolys");
837            return -1;
838          }
839        }
840        else
841        {
842          if ((!vartest || (strcmp(r1->parameter[0],r2->parameter[0])==0)) /* 1 par */
843              && (rPar(r2)==1))
844          {
845            tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
846            tmpR.parameter[0]=omStrDup(r1->parameter[0]);
847            tmpR.P=1;
848            tmpR.minpoly=n_Copy(r1->minpoly, r1);
849          }
850          else
851          {
852            WerrorS("different parameters and minpoly!=0");
853            return -1;
854          }
855        }
856      }
857      else /* r1->minpoly==NULL */
858      {
859        if (r2->minpoly!=NULL)
860        {
861          if ((!vartest || (strcmp(r1->parameter[0],r2->parameter[0])==0)) /* 1 par */
862              && (rPar(r1)==1))
863          {
864            tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
865            tmpR.parameter[0]=omStrDup(r1->parameter[0]);
866            tmpR.P=1;
867            tmpR.minpoly=n_Copy(r2->minpoly, r2);
868          }
869          else
870          {
871            WerrorS("different parameters and minpoly!=0");
872            return -1;
873          }
874        }
875        else
876        {
877          int len=rPar(r1)+rPar(r2);
878          tmpR.parameter=(char **)omAlloc0(len*sizeof(char_ptr));
879          int i;
880          for (i=0;i<rPar(r1);i++)
881          {
882            tmpR.parameter[i]=omStrDup(r1->parameter[i]);
883          }
884          int j,l;
885          for(j=0;j<rPar(r2);j++)
886          {
887            if (vartest)
888            {
889              for(l=0;l<i;l++)
890              {
891                if(strcmp(tmpR.parameter[l],r2->parameter[j])==0)
892                  break;
893              }
894            }
895            else
896              l=i;
897            if (l==i)
898            {
899              tmpR.parameter[i]=omStrDup(r2->parameter[j]);
900              i++;
901            }
902          }
903          if (i!=len)
904          {
905            tmpR.parameter=(char**)omReallocSize(tmpR.parameter,len*sizeof(char_ptr),i*sizeof(char_ptr));
906          }
907          tmpR.P=i;
908        }
909      }
910    }
911  }
912  else /* r1->ch!=r2->ch */
913  {
914    if (r1->ch<-1) /* Z/p(a) */
915    {
916      if ((r2->ch==0) /* Q */
917          || (r2->ch==-r1->ch)) /* Z/p */
918      {
919        tmpR.ch=rInternalChar(r1);
920        tmpR.P=rPar(r1);
921        tmpR.parameter=(char **)omAlloc(rPar(r1)*sizeof(char_ptr));
922        int i;
923        for (i=0;i<rPar(r1);i++)
924        {
925          tmpR.parameter[i]=omStrDup(r1->parameter[i]);
926        }
927        if (r1->minpoly!=NULL)
928        {
929          tmpR.minpoly=n_Copy(r1->minpoly, r1);
930        }
931      }
932      else  /* R, Q(a),Z/q,Z/p(a),GF(p,n) */
933      {
934        WerrorS("Z/p(a)+(R,Q(a),Z/q(a),GF(q,n))");
935        return -1;
936      }
937    }
938    else if (r1->ch==-1) /* R */
939    {
940      WerrorS("R+..");
941      return -1;
942    }
943    else if (r1->ch==0) /* Q */
944    {
945      if ((r2->ch<-1)||(r2->ch==1)) /* Z/p(a),Q(a) */
946      {
947        tmpR.ch=rInternalChar(r2);
948        tmpR.P=rPar(r2);
949        tmpR.parameter=(char **)omAlloc(rPar(r2)*sizeof(char_ptr));
950        int i;
951        for (i=0;i<rPar(r2);i++)
952        {
953          tmpR.parameter[i]=omStrDup(r2->parameter[i]);
954        }
955        if (r2->minpoly!=NULL)
956        {
957          tmpR.minpoly=n_Copy(r2->minpoly, r2);
958        }
959      }
960      else if (r2->ch>1) /* Z/p,GF(p,n) */
961      {
962        tmpR.ch=r2->ch;
963        if (r2->parameter!=NULL)
964        {
965          tmpR.parameter=(char **)omAllocBin(char_ptr_bin);
966          tmpR.P=1;
967          tmpR.parameter[0]=omStrDup(r2->parameter[0]);
968        }
969      }
970      else
971      {
972        WerrorS("Q+R");
973        return -1; /* R */
974      }
975    }
976    else if (r1->ch==1) /* Q(a) */
977    {
978      if (r2->ch==0) /* Q */
979      {
980        tmpR.ch=rInternalChar(r1);
981        tmpR.P=rPar(r1);
982        tmpR.parameter=(char **)omAlloc(rPar(r1)*sizeof(char_ptr));
983        int i;
984        for(i=0;i<rPar(r1);i++)
985        {
986          tmpR.parameter[i]=omStrDup(r1->parameter[i]);
987        }
988        if (r1->minpoly!=NULL)
989        {
990          tmpR.minpoly=n_Copy(r1->minpoly, r1);
991        }
992      }
993      else  /* R, Z/p,GF(p,n) */
994      {
995        WerrorS("Q(a)+(R,Z/p,GF(p,n))");
996        return -1;
997      }
998    }
999    else /* r1->ch >=2 , Z/p */
1000    {
1001      if (r2->ch==0) /* Q */
1002      {
1003        tmpR.ch=r1->ch;
1004      }
1005      else if (r2->ch==-r1->ch) /* Z/p(a) */
1006      {
1007        tmpR.ch=rInternalChar(r2);
1008        tmpR.P=rPar(r2);
1009        tmpR.parameter=(char **)omAlloc(rPar(r2)*sizeof(char_ptr));
1010        int i;
1011        for(i=0;i<rPar(r2);i++)
1012        {
1013          tmpR.parameter[i]=omStrDup(r2->parameter[i]);
1014        }
1015        if (r2->minpoly!=NULL)
1016        {
1017          tmpR.minpoly=n_Copy(r2->minpoly, r2);
1018        }
1019      }
1020      else
1021      {
1022        WerrorS("Z/p+(GF(q,n),Z/q(a),R,Q(a))");
1023        return -1; /* GF(p,n),Z/q(a),R,Q(a) */
1024      }
1025    }
1026  }
1027  /* variable names ========================================================*/
1028  int i,j,k;
1029  int l=r1->N+r2->N;
1030  char **names=(char **)omAlloc0(l*sizeof(char_ptr));
1031  k=0;
1032
1033  // collect all varnames from r1, except those which are parameters
1034  // of r2, or those which are the empty string
1035  for (i=0;i<r1->N;i++)
1036  {
1037    BOOLEAN b=TRUE;
1038
1039    if (*(r1->names[i]) == '\0')
1040      b = FALSE;
1041    else if ((r2->parameter!=NULL) && (strlen(r1->names[i])==1))
1042    {
1043      if (vartest)
1044      {
1045        for(j=0;j<rPar(r2);j++)
1046        {
1047          if (strcmp(r1->names[i],r2->parameter[j])==0)
1048          {
1049            b=FALSE;
1050            break;
1051          }
1052        }
1053      }
1054    }
1055
1056    if (b)
1057    {
1058      //Print("name : %d: %s\n",k,r1->names[i]);
1059      names[k]=omStrDup(r1->names[i]);
1060      k++;
1061    }
1062    //else
1063    //  Print("no name (par1) %s\n",r1->names[i]);
1064  }
1065  // Add variables from r2, except those which are parameters of r1
1066  // those which are empty strings, and those which equal a var of r1
1067  for(i=0;i<r2->N;i++)
1068  {
1069    BOOLEAN b=TRUE;
1070
1071    if (*(r2->names[i]) == '\0')
1072      b = FALSE;
1073    else if ((r1->parameter!=NULL) && (strlen(r2->names[i])==1))
1074    {
1075      if (vartest)
1076      {
1077        for(j=0;j<rPar(r1);j++)
1078        {
1079          if (strcmp(r2->names[i],r1->parameter[j])==0)
1080          {
1081            b=FALSE;
1082            break;
1083          }
1084        }
1085      }
1086    }
1087
1088    if (b)
1089    {
1090      if (vartest)
1091      {
1092        for(j=0;j<r1->N;j++)
1093        {
1094          if (strcmp(r1->names[j],r2->names[i])==0)
1095          {
1096            b=FALSE;
1097            break;
1098          }
1099        }
1100      }
1101      if (b)
1102      {
1103        //Print("name : %d : %s\n",k,r2->names[i]);
1104        names[k]=omStrDup(r2->names[i]);
1105        k++;
1106      }
1107      //else
1108      //  Print("no name (var): %s\n",r2->names[i]);
1109    }
1110    //else
1111    //  Print("no name (par): %s\n",r2->names[i]);
1112  }
1113  // check whether we found any vars at all
1114  if (k == 0)
1115  {
1116    names[k]=omStrDup("");
1117    k=1;
1118  }
1119  tmpR.N=k;
1120  tmpR.names=names;
1121  /* ordering *======================================================== */
1122  tmpR.OrdSgn=1;
1123  if (dp_dp
1124#ifdef HAVE_PLURAL
1125      && !rIsPluralRing(r1) && !rIsPluralRing(r2)
1126#endif
1127     )
1128  {
1129    tmpR.order=(int*)omAlloc(4*sizeof(int));
1130    tmpR.block0=(int*)omAlloc0(4*sizeof(int));
1131    tmpR.block1=(int*)omAlloc0(4*sizeof(int));
1132    tmpR.wvhdl=(int**)omAlloc0(4*sizeof(int_ptr));
1133    tmpR.order[0]=ringorder_dp;
1134    tmpR.block0[0]=1;
1135    tmpR.block1[0]=rVar(r1);
1136    if (r2->OrdSgn==1)
1137    {
1138      if ((r2->block0[0]==1)
1139      && (r2->block1[0]==rVar(r2))
1140      && ((r2->order[0]==ringorder_wp)
1141        || (r2->order[0]==ringorder_Wp)
1142        || (r2->order[0]==ringorder_Dp))
1143     )
1144     {
1145       tmpR.order[1]=r2->order[0];
1146       if (r2->wvhdl[0]!=NULL)
1147         tmpR.wvhdl[1]=(int *)omMemDup(r2->wvhdl[0]);
1148     }
1149     else
1150        tmpR.order[1]=ringorder_dp;
1151    }
1152    else
1153    {
1154      tmpR.order[1]=ringorder_ds;
1155      tmpR.OrdSgn=-1;
1156    }
1157    tmpR.block0[1]=rVar(r1)+1;
1158    tmpR.block1[1]=rVar(r1)+rVar(r2);
1159    tmpR.order[2]=ringorder_C;
1160    tmpR.order[3]=0;
1161  }
1162  else
1163  {
1164    if ((r1->order[0]==ringorder_unspec)
1165        && (r2->order[0]==ringorder_unspec))
1166    {
1167      tmpR.order=(int*)omAlloc(3*sizeof(int));
1168      tmpR.block0=(int*)omAlloc(3*sizeof(int));
1169      tmpR.block1=(int*)omAlloc(3*sizeof(int));
1170      tmpR.wvhdl=(int**)omAlloc0(3*sizeof(int_ptr));
1171      tmpR.order[0]=ringorder_unspec;
1172      tmpR.order[1]=ringorder_C;
1173      tmpR.order[2]=0;
1174      tmpR.block0[0]=1;
1175      tmpR.block1[0]=tmpR.N;
1176    }
1177    else if (l==k) /* r3=r1+r2 */
1178    {
1179      int b;
1180      ring rb;
1181      if (r1->order[0]==ringorder_unspec)
1182      {
1183        /* extend order of r2 to r3 */
1184        b=rBlocks(r2);
1185        rb=r2;
1186        tmpR.OrdSgn=r2->OrdSgn;
1187      }
1188      else if (r2->order[0]==ringorder_unspec)
1189      {
1190        /* extend order of r1 to r3 */
1191        b=rBlocks(r1);
1192        rb=r1;
1193        tmpR.OrdSgn=r1->OrdSgn;
1194      }
1195      else
1196      {
1197        b=rBlocks(r1)+rBlocks(r2)-2; /* for only one order C, only one 0 */
1198        rb=NULL;
1199      }
1200      tmpR.order=(int*)omAlloc0(b*sizeof(int));
1201      tmpR.block0=(int*)omAlloc0(b*sizeof(int));
1202      tmpR.block1=(int*)omAlloc0(b*sizeof(int));
1203      tmpR.wvhdl=(int**)omAlloc0(b*sizeof(int_ptr));
1204      /* weights not implemented yet ...*/
1205      if (rb!=NULL)
1206      {
1207        for (i=0;i<b;i++)
1208        {
1209          tmpR.order[i]=rb->order[i];
1210          tmpR.block0[i]=rb->block0[i];
1211          tmpR.block1[i]=rb->block1[i];
1212          if (rb->wvhdl[i]!=NULL)
1213            WarnS("rSum: weights not implemented");
1214        }
1215        tmpR.block0[0]=1;
1216      }
1217      else /* ring sum for complete rings */
1218      {
1219        for (i=0;r1->order[i]!=0;i++)
1220        {
1221          tmpR.order[i]=r1->order[i];
1222          tmpR.block0[i]=r1->block0[i];
1223          tmpR.block1[i]=r1->block1[i];
1224          if (r1->wvhdl[i]!=NULL)
1225            tmpR.wvhdl[i] = (int*) omMemDup(r1->wvhdl[i]);
1226        }
1227        j=i;
1228        i--;
1229        if ((r1->order[i]==ringorder_c)
1230            ||(r1->order[i]==ringorder_C))
1231        {
1232          j--;
1233          tmpR.order[b-2]=r1->order[i];
1234        }
1235        for (i=0;r2->order[i]!=0;i++)
1236        {
1237          if ((r2->order[i]!=ringorder_c)
1238              &&(r2->order[i]!=ringorder_C))
1239          {
1240            tmpR.order[j]=r2->order[i];
1241            tmpR.block0[j]=r2->block0[i]+rVar(r1);
1242            tmpR.block1[j]=r2->block1[i]+rVar(r1);
1243            if (r2->wvhdl[i]!=NULL)
1244            {
1245              tmpR.wvhdl[j] = (int*) omMemDup(r2->wvhdl[i]);
1246            }
1247            j++;
1248          }
1249        }
1250        if((r1->OrdSgn==-1)||(r2->OrdSgn==-1))
1251          tmpR.OrdSgn=-1;
1252      }
1253    }
1254    else if ((k==rVar(r1)) && (k==rVar(r2))) /* r1 and r2 are "quite" the same ring */
1255      /* copy r1, because we have the variables from r1 */
1256    {
1257      int b=rBlocks(r1);
1258
1259      tmpR.order=(int*)omAlloc0(b*sizeof(int));
1260      tmpR.block0=(int*)omAlloc0(b*sizeof(int));
1261      tmpR.block1=(int*)omAlloc0(b*sizeof(int));
1262      tmpR.wvhdl=(int**)omAlloc0(b*sizeof(int_ptr));
1263      /* weights not implemented yet ...*/
1264      for (i=0;i<b;i++)
1265      {
1266        tmpR.order[i]=r1->order[i];
1267        tmpR.block0[i]=r1->block0[i];
1268        tmpR.block1[i]=r1->block1[i];
1269        if (r1->wvhdl[i]!=NULL)
1270        {
1271          tmpR.wvhdl[i] = (int*) omMemDup(r1->wvhdl[i]);
1272        }
1273      }
1274      tmpR.OrdSgn=r1->OrdSgn;
1275    }
1276    else
1277    {
1278      for(i=0;i<k;i++) omFree((ADDRESS)tmpR.names[i]);
1279      omFreeSize((ADDRESS)names,tmpR.N*sizeof(char_ptr));
1280      Werror("difficulties with variables: %d,%d -> %d",rVar(r1),rVar(r2),k);
1281      return -1;
1282    }
1283  }
1284  sum=(ring)omAllocBin(ip_sring_bin);
1285  memcpy(sum,&tmpR,sizeof(ip_sring));
1286  rComplete(sum);
1287
1288//#ifdef RDEBUG
1289//  rDebugPrint(sum);
1290//#endif
1291
1292#ifdef HAVE_PLURAL
1293  if(1)
1294  {
1295    ring old_ring = currRing;
1296
1297    BOOLEAN R1_is_nc = rIsPluralRing(r1);
1298    BOOLEAN R2_is_nc = rIsPluralRing(r2);
1299
1300    if ( (R1_is_nc) || (R2_is_nc))
1301    {
1302      rChangeCurrRing(r1); /* since rCopy works well only in currRing */
1303      ring R1 = rCopy(r1);
1304      if ( !R1_is_nc ) nc_rCreateNCcomm(R1);
1305
1306#if 0
1307#ifdef RDEBUG
1308      rWrite(R1);
1309      rDebugPrint(R1);
1310#endif
1311#endif
1312      rChangeCurrRing(r2);
1313      ring R2 = rCopy(r2);
1314      if ( !R2_is_nc ) nc_rCreateNCcomm(R2);
1315
1316#if 0
1317#ifdef RDEBUG
1318      rWrite(R2);
1319      rDebugPrint(R2);
1320#endif
1321#endif
1322
1323      rChangeCurrRing(sum); // ?
1324
1325      // Projections from R_i into Sum:
1326      /* multiplication matrices business: */
1327      /* find permutations of vars and pars */
1328      int *perm1 = (int *)omAlloc0((rVar(R1)+1)*sizeof(int));
1329      int *par_perm1 = NULL;
1330      if (rPar(R1)!=0) par_perm1=(int *)omAlloc0((rPar(R1)+1)*sizeof(int));
1331
1332      int *perm2 = (int *)omAlloc0((rVar(R2)+1)*sizeof(int));
1333      int *par_perm2 = NULL;
1334      if (rPar(R2)!=0) par_perm2=(int *)omAlloc0((rPar(R2)+1)*sizeof(int));
1335
1336      maFindPerm(R1->names,  rVar(R1),  R1->parameter,  rPar(R1),
1337                 sum->names, rVar(sum), sum->parameter, rPar(sum),
1338                 perm1, par_perm1, sum->ch);
1339
1340      maFindPerm(R2->names,  rVar(R2),  R2->parameter,  rPar(R2),
1341                 sum->names, rVar(sum), sum->parameter, rPar(sum),
1342                 perm2, par_perm2, sum->ch);
1343
1344      nMapFunc nMap1 = nSetMap(R1);
1345      nMapFunc nMap2 = nSetMap(R2);
1346
1347      matrix C1 = R1->GetNC()->C, C2 = R2->GetNC()->C;
1348      matrix D1 = R1->GetNC()->D, D2 = R2->GetNC()->D;
1349
1350      // !!!! BUG? C1 and C2 might live in different baserings!!!
1351      // it cannot be both the currRing! :)
1352      // the currRing is sum!
1353
1354      int l = rVar(R1) + rVar(R2);
1355
1356      matrix C  = mpNew(l,l);
1357      matrix D  = mpNew(l,l);
1358
1359      int param_shift = 0;
1360
1361      for (i = 1; i <= rVar(R1); i++)
1362        for (j= rVar(R1)+1; j <= l; j++)
1363          MATELEM(C,i,j) = p_One( sum); // in 'sum'
1364
1365      idTest((ideal)C);
1366
1367      // Create blocked C and D matrices:
1368      for (i=1; i<= rVar(R1); i++)
1369        for (j=i+1; j<=rVar(R1); j++)
1370        {
1371          assume(MATELEM(C1,i,j) != NULL);
1372          MATELEM(C,i,j) = pPermPoly(MATELEM(C1,i,j), perm1, R1, nMap1, par_perm1, rPar(R1)); // need ADD + CMP ops.
1373
1374          if (MATELEM(D1,i,j) != NULL)
1375            MATELEM(D,i,j) = pPermPoly(MATELEM(D1,i,j),perm1,R1,nMap1,par_perm1,rPar(R1));
1376        }
1377
1378      idTest((ideal)C);
1379      idTest((ideal)D);
1380
1381
1382      for (i=1; i<= rVar(R2); i++)
1383        for (j=i+1; j<=rVar(R2); j++)
1384        {
1385          assume(MATELEM(C2,i,j) != NULL);
1386          MATELEM(C,rVar(R1)+i,rVar(R1)+j) = pPermPoly(MATELEM(C2,i,j),perm2,R2,nMap2,par_perm2,rPar(R2));
1387
1388          if (MATELEM(D2,i,j) != NULL)
1389            MATELEM(D,rVar(R1)+i,rVar(R1)+j) = pPermPoly(MATELEM(D2,i,j),perm2,R2,nMap2,par_perm2,rPar(R2));
1390        }
1391
1392      idTest((ideal)C);
1393      idTest((ideal)D);
1394
1395      // Now sum is non-commutative with blocked structure constants!
1396      if (nc_CallPlural(C, D, NULL, NULL, sum, false, false, true, sum))
1397        WarnS("Error initializing non-commutative multiplication!");
1398
1399      /* delete R1, R2*/
1400
1401#if 0
1402#ifdef RDEBUG
1403      rWrite(sum);
1404      rDebugPrint(sum);
1405
1406      Print("\nRefs: R1: %d, R2: %d\n", R1->GetNC()->ref, R2->GetNC()->ref);
1407
1408#endif
1409#endif
1410
1411
1412      rDelete(R1);
1413      rDelete(R2);
1414
1415      /* delete perm arrays */
1416      if (perm1!=NULL) omFree((ADDRESS)perm1);
1417      if (perm2!=NULL) omFree((ADDRESS)perm2);
1418      if (par_perm1!=NULL) omFree((ADDRESS)par_perm1);
1419      if (par_perm2!=NULL) omFree((ADDRESS)par_perm2);
1420
1421      rChangeCurrRing(old_ring);
1422    }
1423
1424  }
1425#endif
1426
1427  ideal Q=NULL;
1428  ideal Q1=NULL, Q2=NULL;
1429  ring old_ring2 = currRing;
1430  if (r1->qideal!=NULL)
1431  {
1432    rChangeCurrRing(sum);
1433//     if (r2->qideal!=NULL)
1434//     {
1435//       WerrorS("todo: qring+qring");
1436//       return -1;
1437//     }
1438//     else
1439//     {}
1440    /* these were defined in the Plural Part above... */
1441    int *perm1 = (int *)omAlloc0((rVar(r1)+1)*sizeof(int));
1442    int *par_perm1 = NULL;
1443    if (rPar(r1)!=0) par_perm1=(int *)omAlloc0((rPar(r1)+1)*sizeof(int));
1444    maFindPerm(r1->names,  rVar(r1),  r1->parameter,  rPar(r1),
1445               sum->names, rVar(sum), sum->parameter, rPar(sum),
1446               perm1, par_perm1, sum->ch);
1447    nMapFunc nMap1 = nSetMap(r1);
1448    Q1 = idInit(IDELEMS(r1->qideal),1);
1449    for (int for_i=0;for_i<IDELEMS(r1->qideal);for_i++)
1450      Q1->m[for_i] = pPermPoly(r1->qideal->m[for_i],perm1,r1,nMap1,par_perm1,rPar(r1));
1451    omFree((ADDRESS)perm1);
1452  }
1453
1454  if (r2->qideal!=NULL)
1455  {
1456    if (currRing!=sum)
1457      rChangeCurrRing(sum);
1458    int *perm2 = (int *)omAlloc0((rVar(r2)+1)*sizeof(int));
1459    int *par_perm2 = NULL;
1460    if (rPar(r2)!=0) par_perm2=(int *)omAlloc0((rPar(r2)+1)*sizeof(int));
1461    maFindPerm(r2->names,  rVar(r2),  r2->parameter,  rPar(r2),
1462               sum->names, rVar(sum), sum->parameter, rPar(sum),
1463               perm2, par_perm2, sum->ch);
1464    nMapFunc nMap2 = nSetMap(r2);
1465    Q2 = idInit(IDELEMS(r2->qideal),1);
1466    for (int for_i=0;for_i<IDELEMS(r2->qideal);for_i++)
1467      Q2->m[for_i] = pPermPoly(r2->qideal->m[for_i],perm2,r2,nMap2,par_perm2,rPar(r2));
1468    omFree((ADDRESS)perm2);
1469  }
1470  if ( (Q1!=NULL) || ( Q2!=NULL))
1471  {
1472    Q = idSimpleAdd(Q1,Q2);
1473    rChangeCurrRing(old_ring2);
1474  }
1475  sum->qideal = Q;
1476
1477#ifdef HAVE_PLURAL
1478  if( rIsPluralRing(sum) )
1479    nc_SetupQuotient( sum );
1480#endif
1481  return 1;
1482}
1483
1484/*2
1485 *returns -1 for not compatible, (sum is undefined)
1486 *         0 for equal, (and sum)
1487 *         1 for compatible (and sum)
1488 */
1489int rSum(ring r1, ring r2, ring &sum)
1490{
1491  if (r1==r2)
1492  {
1493    sum=r1;
1494    r1->ref++;
1495    return 0;
1496  }
1497  return rTensor(r1,r2,sum,TRUE,FALSE);
1498}
1499
1500/*2
1501 * create a copy of the ring r, which must be equivalent to currRing
1502 * used for qring definition,..
1503 * (i.e.: normal rings: same nCopy as currRing;
1504 *        qring:        same nCopy, same idCopy as currRing)
1505 * DOES NOT CALL rComplete
1506 */
1507ring rCopy0(const ring r, BOOLEAN copy_qideal, BOOLEAN copy_ordering)
1508{
1509  if (r == NULL) return NULL;
1510  int i,j;
1511  ring res=(ring)omAllocBin(ip_sring_bin);
1512  memset(res,0,sizeof(ip_sring));
1513  //memcpy4(res,r,sizeof(ip_sring));
1514  //memset: res->idroot=NULL; /* local objects */
1515  //ideal      minideal;
1516  res->options=r->options; /* ring dependent options */
1517
1518  //memset: res->ordsgn=NULL;
1519  //memset: res->typ=NULL;
1520  //memset: res->VarOffset=NULL;
1521  //memset: res->firstwv=NULL;
1522
1523  //struct omBin_s*   PolyBin; /* Bin from where monoms are allocated */
1524  //memset: res->PolyBin=NULL; // rComplete
1525  res->ch=r->ch;     /* characteristic */
1526#ifdef HAVE_RINGS
1527  res->ringtype=r->ringtype;  /* cring = 0 => coefficient field, cring = 1 => coeffs from Z/2^m */
1528  if (r->ringflaga!=NULL)
1529  {
1530    res->ringflaga = (int_number) omAlloc(sizeof(MP_INT));
1531    mpz_init_set(res->ringflaga,r->ringflaga);
1532  }
1533  res->ringflagb=r->ringflagb;
1534#endif
1535  //memset: res->ref=0; /* reference counter to the ring */
1536
1537  res->float_len=r->float_len; /* additional char-flags */
1538  res->float_len2=r->float_len2; /* additional char-flags */
1539
1540  res->N=r->N;      /* number of vars */
1541  res->P=r->P;      /* number of pars */
1542  res->OrdSgn=r->OrdSgn; /* 1 for polynomial rings, -1 otherwise */
1543
1544  res->firstBlockEnds=r->firstBlockEnds;
1545#ifdef HAVE_PLURAL
1546  res->real_var_start=r->real_var_start;
1547  res->real_var_end=r->real_var_end;
1548#endif
1549
1550#ifdef HAVE_SHIFTBBA
1551  res->isLPring=r->isLPring; /* 0 for non-letterplace rings, otherwise the number of LP blocks, at least 1, known also as lV */
1552#endif
1553
1554  res->VectorOut=r->VectorOut;
1555  res->ShortOut=r->ShortOut;
1556  res->CanShortOut=r->CanShortOut;
1557  res->LexOrder=r->LexOrder; // TRUE if the monomial ordering has polynomial and power series blocks
1558  res->MixedOrder=r->MixedOrder; // ?? 1 for lex ordering (except ls), -1 otherwise
1559  res->ComponentOrder=r->ComponentOrder;
1560
1561  //memset: res->ExpL_Size=0;
1562  //memset: res->CmpL_Size=0;
1563  //memset: res->VarL_Size=0;
1564  //memset: res->pCompIndex=0;
1565  //memset: res->pOrdIndex=0;
1566  //memset: res->OrdSize=0;
1567  //memset: res->VarL_LowIndex=0;
1568  //memset: res->MinExpPerLong=0;
1569  //memset: res->NegWeightL_Size=0;
1570  //memset: res->NegWeightL_Offset=NULL;
1571  //memset: res->VarL_Offset=NULL;
1572
1573  // the following are set by rComplete unless predefined
1574  // therefore, we copy these values: maybe they are non-standard
1575  /* mask for getting single exponents */
1576  res->bitmask=r->bitmask;
1577  res->divmask=r->divmask;
1578  res->BitsPerExp = r->BitsPerExp;
1579  res->ExpPerLong =  r->ExpPerLong;
1580
1581  //memset: res->p_Procs=NULL;
1582  //memset: res->pFDeg=NULL;
1583  //memset: res->pLDeg=NULL;
1584  //memset: res->pFDegOrig=NULL;
1585  //memset: res->pLDegOrig=NULL;
1586  //memset: res->p_Setm=NULL;
1587  //memset: res->cf=NULL;
1588  res->options=r->options;
1589  #ifdef HAVE_RINGS
1590  res->ringtype=r->ringtype;
1591  #endif
1592  //
1593  if (r->algring!=NULL)
1594    r->algring->ref++;
1595  res->algring=r->algring;
1596  //memset: res->minideal=NULL;
1597  if (r->parameter!=NULL)
1598  {
1599    res->minpoly=nCopy(r->minpoly);
1600    int l=rPar(r);
1601    res->parameter=(char **)omAlloc(l*sizeof(char_ptr));
1602    int i;
1603    for(i=0;i<rPar(r);i++)
1604    {
1605      res->parameter[i]=omStrDup(r->parameter[i]);
1606    }
1607    if (r->minideal!=NULL)
1608    {
1609      res->minideal=id_Copy(r->minideal,r->algring);
1610    }
1611  }
1612  if (copy_ordering == TRUE)
1613  {
1614    i=rBlocks(r);
1615    res->wvhdl   = (int **)omAlloc(i * sizeof(int_ptr));
1616    res->order   = (int *) omAlloc(i * sizeof(int));
1617    res->block0  = (int *) omAlloc(i * sizeof(int));
1618    res->block1  = (int *) omAlloc(i * sizeof(int));
1619    for (j=0; j<i; j++)
1620    {
1621      if (r->wvhdl[j]!=NULL)
1622      {
1623        res->wvhdl[j] = (int*) omMemDup(r->wvhdl[j]);
1624      }
1625      else
1626        res->wvhdl[j]=NULL;
1627    }
1628    memcpy4(res->order,r->order,i * sizeof(int));
1629    memcpy4(res->block0,r->block0,i * sizeof(int));
1630    memcpy4(res->block1,r->block1,i * sizeof(int));
1631  }
1632  //memset: else
1633  //memset: {
1634  //memset:   res->wvhdl = NULL;
1635  //memset:   res->order = NULL;
1636  //memset:   res->block0 = NULL;
1637  //memset:   res->block1 = NULL;
1638  //memset: }
1639
1640  res->names   = (char **)omAlloc0(rVar(r) * sizeof(char_ptr));
1641  for (i=0; i<rVar(res); i++)
1642  {
1643    res->names[i] = omStrDup(r->names[i]);
1644  }
1645  if (r->qideal!=NULL)
1646  {
1647    if (copy_qideal) 
1648    {
1649      #ifndef NDEBUG
1650      if (!copy_ordering)
1651        WerrorS("internal error: rCopy0(Q,TRUE,FALSE)");
1652      else
1653      #endif
1654      {
1655      #ifndef NDEBUG
1656        WarnS("internal bad stuff: rCopy0(Q,TRUE,TRUE)");
1657      #endif
1658        rComplete(res);
1659        res->qideal= idrCopyR_NoSort(r->qideal, r, res);
1660        rUnComplete(res);
1661      }
1662    }
1663    //memset: else res->qideal = NULL;
1664  }
1665  //memset: else res->qideal = NULL;
1666#ifdef HAVE_PLURAL
1667  //memset: res->GetNC() = NULL; // copy is purely commutative!!!
1668//  if (rIsPluralRing(r))
1669//    nc_rCopy0(res, r); // is this correct??? imho: no!
1670#endif
1671  return res;
1672}
1673
1674/*2
1675 * create a copy of the ring r, which must be equivalent to currRing
1676 * used for qring definition,..
1677 * (i.e.: normal rings: same nCopy as currRing;
1678 *        qring:        same nCopy, same idCopy as currRing)
1679 */
1680ring rCopy(ring r)
1681{
1682  if (r == NULL) return NULL;
1683  ring res=rCopy0(r);
1684  rComplete(res, 1); // res is purely commutative so far
1685
1686#ifdef HAVE_PLURAL
1687  if (rIsPluralRing(r))
1688    if( nc_rCopy(res, r, true) );
1689#endif
1690
1691  return res;
1692}
1693
1694// returns TRUE, if r1 equals r2 FALSE, otherwise Equality is
1695// determined componentwise, if qr == 1, then qrideal equality is
1696// tested, as well
1697BOOLEAN rEqual(ring r1, ring r2, BOOLEAN qr)
1698{
1699  int i, j;
1700
1701  if (r1 == r2) return TRUE;
1702
1703  if (r1 == NULL || r2 == NULL) return FALSE;
1704
1705  if ((rInternalChar(r1) != rInternalChar(r2))
1706  || (r1->float_len != r2->float_len)
1707  || (r1->float_len2 != r2->float_len2)
1708  || (rVar(r1) != rVar(r2))
1709  || (r1->OrdSgn != r2->OrdSgn)
1710  || (rPar(r1) != rPar(r2)))
1711    return FALSE;
1712
1713  for (i=0; i<rVar(r1); i++)
1714  {
1715    if (r1->names[i] != NULL && r2->names[i] != NULL)
1716    {
1717      if (strcmp(r1->names[i], r2->names[i])) return FALSE;
1718    }
1719    else if ((r1->names[i] != NULL) ^ (r2->names[i] != NULL))
1720    {
1721      return FALSE;
1722    }
1723  }
1724
1725  i=0;
1726  while (r1->order[i] != 0)
1727  {
1728    if (r2->order[i] == 0) return FALSE;
1729    if ((r1->order[i] != r2->order[i])
1730    || (r1->block0[i] != r2->block0[i])
1731    || (r1->block1[i] != r2->block1[i]))
1732      return FALSE;
1733    if (r1->wvhdl[i] != NULL)
1734    {
1735      if (r2->wvhdl[i] == NULL)
1736        return FALSE;
1737      for (j=0; j<r1->block1[i]-r1->block0[i]+1; j++)
1738        if (r2->wvhdl[i][j] != r1->wvhdl[i][j])
1739          return FALSE;
1740    }
1741    else if (r2->wvhdl[i] != NULL) return FALSE;
1742    i++;
1743  }
1744  if (r2->order[i] != 0) return FALSE;
1745
1746  for (i=0; i<rPar(r1);i++)
1747  {
1748      if (strcmp(r1->parameter[i], r2->parameter[i])!=0)
1749        return FALSE;
1750  }
1751
1752  if (r1->minpoly != NULL)
1753  {
1754    if (r2->minpoly == NULL) return FALSE;
1755    if (currRing == r1 || currRing == r2)
1756    {
1757      if (! nEqual(r1->minpoly, r2->minpoly)) return FALSE;
1758    }
1759  }
1760  else if (r2->minpoly != NULL) return FALSE;
1761
1762  if (qr)
1763  {
1764    if (r1->qideal != NULL)
1765    {
1766      ideal id1 = r1->qideal, id2 = r2->qideal;
1767      int i, n;
1768      poly *m1, *m2;
1769
1770      if (id2 == NULL) return FALSE;
1771      if ((n = IDELEMS(id1)) != IDELEMS(id2)) return FALSE;
1772
1773      if (currRing == r1 || currRing == r2)
1774      {
1775        m1 = id1->m;
1776        m2 = id2->m;
1777        for (i=0; i<n; i++)
1778          if (! pEqualPolys(m1[i],m2[i])) return FALSE;
1779      }
1780    }
1781    else if (r2->qideal != NULL) return FALSE;
1782  }
1783
1784  return TRUE;
1785}
1786
1787// returns TRUE, if r1 and r2 represents the monomials in the same way
1788// FALSE, otherwise
1789// this is an analogue to rEqual but not so strict
1790BOOLEAN rSamePolyRep(ring r1, ring r2)
1791{
1792  int i, j;
1793
1794  if (r1 == r2) return TRUE;
1795
1796  if (r1 == NULL || r2 == NULL) return FALSE;
1797
1798  if ((rInternalChar(r1) != rInternalChar(r2))
1799  || (r1->float_len != r2->float_len)
1800  || (r1->float_len2 != r2->float_len2)
1801  || (rVar(r1) != rVar(r2))
1802  || (r1->OrdSgn != r2->OrdSgn)
1803  || (rPar(r1) != rPar(r2)))
1804    return FALSE;
1805
1806  if (rVar(r1)!=rVar(r2)) return FALSE;
1807  if (rPar(r1)!=rPar(r2)) return FALSE;
1808
1809  i=0;
1810  while (r1->order[i] != 0)
1811  {
1812    if (r2->order[i] == 0) return FALSE;
1813    if ((r1->order[i] != r2->order[i])
1814    || (r1->block0[i] != r2->block0[i])
1815    || (r1->block1[i] != r2->block1[i]))
1816      return FALSE;
1817    if (r1->wvhdl[i] != NULL)
1818    {
1819      if (r2->wvhdl[i] == NULL)
1820        return FALSE;
1821      for (j=0; j<r1->block1[i]-r1->block0[i]+1; j++)
1822        if (r2->wvhdl[i][j] != r1->wvhdl[i][j])
1823          return FALSE;
1824    }
1825    else if (r2->wvhdl[i] != NULL) return FALSE;
1826    i++;
1827  }
1828  if (r2->order[i] != 0) return FALSE;
1829
1830  // we do not check minpoly
1831  // we do not check qideal
1832
1833  return TRUE;
1834}
1835
1836rOrderType_t rGetOrderType(ring r)
1837{
1838  // check for simple ordering
1839  if (rHasSimpleOrder(r))
1840  {
1841    if ((r->order[1] == ringorder_c)
1842    || (r->order[1] == ringorder_C))
1843    {
1844      switch(r->order[0])
1845      {
1846          case ringorder_dp:
1847          case ringorder_wp:
1848          case ringorder_ds:
1849          case ringorder_ws:
1850          case ringorder_ls:
1851          case ringorder_unspec:
1852            if (r->order[1] == ringorder_C
1853            ||  r->order[0] == ringorder_unspec)
1854              return rOrderType_ExpComp;
1855            return rOrderType_Exp;
1856
1857          default:
1858            assume(r->order[0] == ringorder_lp ||
1859                   r->order[0] == ringorder_rs ||
1860                   r->order[0] == ringorder_Dp ||
1861                   r->order[0] == ringorder_Wp ||
1862                   r->order[0] == ringorder_Ds ||
1863                   r->order[0] == ringorder_Ws);
1864
1865            if (r->order[1] == ringorder_c) return rOrderType_ExpComp;
1866            return rOrderType_Exp;
1867      }
1868    }
1869    else
1870    {
1871      assume((r->order[0]==ringorder_c)||(r->order[0]==ringorder_C));
1872      return rOrderType_CompExp;
1873    }
1874  }
1875  else
1876    return rOrderType_General;
1877}
1878
1879BOOLEAN rHasSimpleOrder(const ring r)
1880{
1881  if (r->order[0] == ringorder_unspec) return TRUE;
1882  int blocks = rBlocks(r) - 1;
1883  assume(blocks >= 1);
1884  if (blocks == 1) return TRUE;
1885  if (blocks > 2)  return FALSE;
1886  if ((r->order[0] != ringorder_c)
1887  && (r->order[0] != ringorder_C)
1888  && (r->order[1] != ringorder_c)
1889  && (r->order[1] != ringorder_C))
1890    return FALSE;
1891  if ((r->order[1] == ringorder_M)
1892  || (r->order[0] == ringorder_M))
1893    return FALSE;
1894  return TRUE;
1895}
1896
1897// returns TRUE, if simple lp or ls ordering
1898BOOLEAN rHasSimpleLexOrder(const ring r)
1899{
1900  return rHasSimpleOrder(r) &&
1901    (r->order[0] == ringorder_ls ||
1902     r->order[0] == ringorder_lp ||
1903     r->order[1] == ringorder_ls ||
1904     r->order[1] == ringorder_lp);
1905}
1906
1907BOOLEAN rOrder_is_DegOrdering(const rRingOrder_t order)
1908{
1909  switch(order)
1910  {
1911      case ringorder_dp:
1912      case ringorder_Dp:
1913      case ringorder_ds:
1914      case ringorder_Ds:
1915      case ringorder_Ws:
1916      case ringorder_Wp:
1917      case ringorder_ws:
1918      case ringorder_wp:
1919        return TRUE;
1920
1921      default:
1922        return FALSE;
1923  }
1924}
1925
1926BOOLEAN rOrder_is_WeightedOrdering(rRingOrder_t order)
1927{
1928  switch(order)
1929  {
1930      case ringorder_Ws:
1931      case ringorder_Wp:
1932      case ringorder_ws:
1933      case ringorder_wp:
1934        return TRUE;
1935
1936      default:
1937        return FALSE;
1938  }
1939}
1940
1941BOOLEAN rHasSimpleOrderAA(ring r)
1942{
1943  int blocks = rBlocks(r) - 1;
1944  if ((blocks > 3) || (blocks < 2)) return FALSE;
1945  if (blocks == 3)
1946  {
1947    return (((r->order[0] == ringorder_aa) && (r->order[1] != ringorder_M) &&
1948             ((r->order[2] == ringorder_c) || (r->order[2] == ringorder_C))) ||
1949            (((r->order[0] == ringorder_c) || (r->order[0] == ringorder_C)) &&
1950             (r->order[1] == ringorder_aa) && (r->order[2] != ringorder_M)));
1951  }
1952  else
1953  {
1954    return ((r->order[0] == ringorder_aa) && (r->order[1] != ringorder_M));
1955  }
1956}
1957
1958// return TRUE if p_SetComp requires p_Setm
1959BOOLEAN rOrd_SetCompRequiresSetm(ring r)
1960{
1961  if (r->typ != NULL)
1962  {
1963    int pos;
1964    for (pos=0;pos<r->OrdSize;pos++)
1965    {
1966      sro_ord* o=&(r->typ[pos]);
1967      if ((o->ord_typ == ro_syzcomp) || (o->ord_typ == ro_syz) || (o->ord_typ == ro_is) || (o->ord_typ == ro_isTemp)) return TRUE;
1968    }
1969  }
1970  return FALSE;
1971}
1972
1973// return TRUE if p->exp[r->pOrdIndex] holds total degree of p */
1974BOOLEAN rOrd_is_Totaldegree_Ordering(ring r)
1975{
1976  // Hmm.... what about Syz orderings?
1977  return (rVar(r) > 1 &&
1978          ((rHasSimpleOrder(r) &&
1979           (rOrder_is_DegOrdering((rRingOrder_t)r->order[0]) ||
1980            rOrder_is_DegOrdering(( rRingOrder_t)r->order[1]))) ||
1981           (rHasSimpleOrderAA(r) &&
1982            (rOrder_is_DegOrdering((rRingOrder_t)r->order[1]) ||
1983             rOrder_is_DegOrdering((rRingOrder_t)r->order[2])))));
1984}
1985
1986// return TRUE if p->exp[r->pOrdIndex] holds a weighted degree of p */
1987BOOLEAN rOrd_is_WeightedDegree_Ordering(ring r =currRing)
1988{
1989  // Hmm.... what about Syz orderings?
1990  return ((rVar(r) > 1) &&
1991          rHasSimpleOrder(r) &&
1992          (rOrder_is_WeightedOrdering((rRingOrder_t)r->order[0]) ||
1993           rOrder_is_WeightedOrdering(( rRingOrder_t)r->order[1])));
1994}
1995
1996BOOLEAN rIsPolyVar(int v, ring r)
1997{
1998  int  i=0;
1999  while(r->order[i]!=0)
2000  {
2001    if((r->block0[i]<=v)
2002    && (r->block1[i]>=v))
2003    {
2004      switch(r->order[i])
2005      {
2006        case ringorder_a:
2007          return (r->wvhdl[i][v-r->block0[i]]>0);
2008        case ringorder_M:
2009          return 2; /*don't know*/
2010        case ringorder_a64: /* assume: all weight are non-negative!*/
2011        case ringorder_lp:
2012        case ringorder_rs:
2013        case ringorder_dp:
2014        case ringorder_Dp:
2015        case ringorder_wp:
2016        case ringorder_Wp:
2017          return TRUE;
2018        case ringorder_ls:
2019        case ringorder_ds:
2020        case ringorder_Ds:
2021        case ringorder_ws:
2022        case ringorder_Ws:
2023          return FALSE;
2024        default:
2025          break;
2026      }
2027    }
2028    i++;
2029  }
2030  return 3; /* could not find var v*/
2031}
2032
2033#ifdef RDEBUG
2034// This should eventually become a full-fledge ring check, like pTest
2035BOOLEAN rDBTest(ring r, const char* fn, const int l)
2036{
2037  int i,j;
2038
2039  if (r == NULL)
2040  {
2041    dReportError("Null ring in %s:%d", fn, l);
2042    return FALSE;
2043  }
2044
2045
2046  if (r->N == 0) return TRUE;
2047
2048//  omCheckAddrSize(r,sizeof(ip_sring));
2049#if OM_CHECK > 0
2050  i=rBlocks(r);
2051  omCheckAddrSize(r->order,i*sizeof(int));
2052  omCheckAddrSize(r->block0,i*sizeof(int));
2053  omCheckAddrSize(r->block1,i*sizeof(int));
2054  if (r->wvhdl!=NULL)
2055    omCheckAddrSize(r->wvhdl,i*sizeof(int *));
2056  for (j=0;j<i; j++)
2057  {
2058    if (r->wvhdl[j] != NULL) omCheckAddr(r->wvhdl[j]);
2059  }
2060#endif
2061  if (r->VarOffset == NULL)
2062  {
2063    dReportError("Null ring VarOffset -- no rComplete (?) in n %s:%d", fn, l);
2064    return FALSE;
2065  }
2066  omCheckAddrSize(r->VarOffset,(r->N+1)*sizeof(int));
2067
2068  if ((r->OrdSize==0)!=(r->typ==NULL))
2069  {
2070    dReportError("mismatch OrdSize and typ-pointer in %s:%d");
2071    return FALSE;
2072  }
2073  omcheckAddrSize(r->typ,r->OrdSize*sizeof(*(r->typ)));
2074  omCheckAddrSize(r->VarOffset,(r->N+1)*sizeof(*(r->VarOffset)));
2075  // test assumptions:
2076  for(i=0;i<=r->N;i++) // for all variables (i = 0..N)
2077  {
2078    if(r->typ!=NULL)
2079    {
2080      for(j=0;j<r->OrdSize;j++) // for all ordering blocks (j =0..OrdSize-1)
2081      {
2082        if(r->typ[j].ord_typ == ro_isTemp)
2083        {
2084          const int p = r->typ[j].data.isTemp.suffixpos;
2085
2086          if(p <= j)
2087            dReportError("ordrec prefix %d is unmatched",j);
2088
2089          assume( p < r->OrdSize );
2090
2091          if(r->typ[p].ord_typ != ro_is)
2092            dReportError("ordrec prefix %d is unmatched (suffix: %d is wrong!!!)",j, p);
2093
2094          // Skip all intermediate blocks for undone variables:
2095          if(r->typ[j].data.isTemp.pVarOffset[i] != -1) // Check i^th variable
2096          {
2097            j = p - 1; // SKIP ALL INTERNAL BLOCKS...???
2098            continue; // To make for check OrdSize bound...
2099          }
2100        } else
2101        if (r->typ[j].ord_typ == ro_is)
2102        {
2103          // Skip all intermediate blocks for undone variables:
2104          if(r->typ[j].data.is.pVarOffset[i] != -1)
2105          {
2106            // ???
2107          }
2108
2109        } else
2110        {
2111          if (r->typ[j].ord_typ==ro_cp)
2112          {
2113            if(((short)r->VarOffset[i]) == r->typ[j].data.cp.place)
2114              dReportError("ordrec %d conflicts with var %d",j,i);
2115          }
2116          else
2117            if ((r->typ[j].ord_typ!=ro_syzcomp)
2118            && (r->VarOffset[i] == r->typ[j].data.dp.place))
2119              dReportError("ordrec %d conflicts with var %d",j,i);
2120        }
2121      }
2122    }
2123    int tmp;
2124      tmp=r->VarOffset[i] & 0xffffff;
2125      #if SIZEOF_LONG == 8
2126        if ((r->VarOffset[i] >> 24) >63)
2127      #else
2128        if ((r->VarOffset[i] >> 24) >31)
2129      #endif
2130          dReportError("bit_start out of range:%d",r->VarOffset[i] >> 24);
2131      if (i > 0 && ((tmp<0) ||(tmp>r->ExpL_Size-1)))
2132      {
2133        dReportError("varoffset out of range for var %d: %d",i,tmp);
2134      }
2135  }
2136  if(r->typ!=NULL)
2137  {
2138    for(j=0;j<r->OrdSize;j++)
2139    {
2140      if ((r->typ[j].ord_typ==ro_dp)
2141      || (r->typ[j].ord_typ==ro_wp)
2142      || (r->typ[j].ord_typ==ro_wp_neg))
2143      {
2144        if (r->typ[j].data.dp.start > r->typ[j].data.dp.end)
2145          dReportError("in ordrec %d: start(%d) > end(%d)",j,
2146            r->typ[j].data.dp.start, r->typ[j].data.dp.end);
2147        if ((r->typ[j].data.dp.start < 1)
2148        || (r->typ[j].data.dp.end > r->N))
2149          dReportError("in ordrec %d: start(%d)<1 or end(%d)>vars(%d)",j,
2150            r->typ[j].data.dp.start, r->typ[j].data.dp.end,r->N);
2151      }
2152    }
2153  }
2154  if (r->minpoly!=NULL)
2155  {
2156    omCheckAddr(r->minpoly);
2157  }
2158  //assume(r->cf!=NULL);
2159
2160  return TRUE;
2161}
2162#endif
2163
2164static void rO_Align(int &place, int &bitplace)
2165{
2166  // increment place to the next aligned one
2167  // (count as Exponent_t,align as longs)
2168  if (bitplace!=BITS_PER_LONG)
2169  {
2170    place++;
2171    bitplace=BITS_PER_LONG;
2172  }
2173}
2174
2175static void rO_TDegree(int &place, int &bitplace, int start, int end,
2176    long *o, sro_ord &ord_struct)
2177{
2178  // degree (aligned) of variables v_start..v_end, ordsgn 1
2179  rO_Align(place,bitplace);
2180  ord_struct.ord_typ=ro_dp;
2181  ord_struct.data.dp.start=start;
2182  ord_struct.data.dp.end=end;
2183  ord_struct.data.dp.place=place;
2184  o[place]=1;
2185  place++;
2186  rO_Align(place,bitplace);
2187}
2188
2189static void rO_TDegree_neg(int &place, int &bitplace, int start, int end,
2190    long *o, sro_ord &ord_struct)
2191{
2192  // degree (aligned) of variables v_start..v_end, ordsgn -1
2193  rO_Align(place,bitplace);
2194  ord_struct.ord_typ=ro_dp;
2195  ord_struct.data.dp.start=start;
2196  ord_struct.data.dp.end=end;
2197  ord_struct.data.dp.place=place;
2198  o[place]=-1;
2199  place++;
2200  rO_Align(place,bitplace);
2201}
2202
2203static void rO_WDegree(int &place, int &bitplace, int start, int end,
2204    long *o, sro_ord &ord_struct, int *weights)
2205{
2206  // weighted degree (aligned) of variables v_start..v_end, ordsgn 1
2207  while((start<end) && (weights[0]==0)) { start++; weights++; }
2208  while((start<end) && (weights[end-start]==0)) { end--; }
2209  int i;
2210  int pure_tdeg=1;
2211  for(i=start;i<=end;i++)
2212  {
2213    if(weights[i-start]!=1)
2214    {
2215      pure_tdeg=0;
2216      break;
2217    }
2218  }
2219  if (pure_tdeg)
2220  {
2221    rO_TDegree(place,bitplace,start,end,o,ord_struct);
2222    return;
2223  }
2224  rO_Align(place,bitplace);
2225  ord_struct.ord_typ=ro_wp;
2226  ord_struct.data.wp.start=start;
2227  ord_struct.data.wp.end=end;
2228  ord_struct.data.wp.place=place;
2229  ord_struct.data.wp.weights=weights;
2230  o[place]=1;
2231  place++;
2232  rO_Align(place,bitplace);
2233  for(i=start;i<=end;i++)
2234  {
2235    if(weights[i-start]<0)
2236    {
2237      ord_struct.ord_typ=ro_wp_neg;
2238      break;
2239    }
2240  }
2241}
2242
2243static void rO_WDegree64(int &place, int &bitplace, int start, int end,
2244    long *o, sro_ord &ord_struct, int64 *weights)
2245{
2246  // weighted degree (aligned) of variables v_start..v_end, ordsgn 1,
2247  // reserved 2 places
2248  rO_Align(place,bitplace);
2249  ord_struct.ord_typ=ro_wp64;
2250  ord_struct.data.wp64.start=start;
2251  ord_struct.data.wp64.end=end;
2252  ord_struct.data.wp64.place=place;
2253  ord_struct.data.wp64.weights64=weights;
2254  o[place]=1;
2255  place++;
2256  o[place]=1;
2257  place++;
2258  rO_Align(place,bitplace);
2259  int i;
2260}
2261
2262static void rO_WDegree_neg(int &place, int &bitplace, int start, int end,
2263    long *o, sro_ord &ord_struct, int *weights)
2264{
2265  // weighted degree (aligned) of variables v_start..v_end, ordsgn -1
2266  while((start<end) && (weights[0]==0)) { start++; weights++; }
2267  while((start<end) && (weights[end-start]==0)) { end--; }
2268  rO_Align(place,bitplace);
2269  ord_struct.ord_typ=ro_wp;
2270  ord_struct.data.wp.start=start;
2271  ord_struct.data.wp.end=end;
2272  ord_struct.data.wp.place=place;
2273  ord_struct.data.wp.weights=weights;
2274  o[place]=-1;
2275  place++;
2276  rO_Align(place,bitplace);
2277  int i;
2278  for(i=start;i<=end;i++)
2279  {
2280    if(weights[i-start]<0)
2281    {
2282      ord_struct.ord_typ=ro_wp_neg;
2283      break;
2284    }
2285  }
2286}
2287
2288static void rO_LexVars(int &place, int &bitplace, int start, int end,
2289  int &prev_ord, long *o,int *v, int bits, int opt_var)
2290{
2291  // a block of variables v_start..v_end with lex order, ordsgn 1
2292  int k;
2293  int incr=1;
2294  if(prev_ord==-1) rO_Align(place,bitplace);
2295
2296  if (start>end)
2297  {
2298    incr=-1;
2299  }
2300  for(k=start;;k+=incr)
2301  {
2302    bitplace-=bits;
2303    if (bitplace < 0) { bitplace=BITS_PER_LONG-bits; place++; }
2304    o[place]=1;
2305    v[k]= place | (bitplace << 24);
2306    if (k==end) break;
2307  }
2308  prev_ord=1;
2309  if (opt_var!= -1)
2310  {
2311    assume((opt_var == end+1) ||(opt_var == end-1));
2312    if((opt_var != end+1) &&(opt_var != end-1)) WarnS("hier-2");
2313    int save_bitplace=bitplace;
2314    bitplace-=bits;
2315    if (bitplace < 0)
2316    {
2317      bitplace=save_bitplace;
2318      return;
2319    }
2320    // there is enough space for the optional var
2321    v[opt_var]=place | (bitplace << 24);
2322  }
2323}
2324
2325static void rO_LexVars_neg(int &place, int &bitplace, int start, int end,
2326  int &prev_ord, long *o,int *v, int bits, int opt_var)
2327{
2328  // a block of variables v_start..v_end with lex order, ordsgn -1
2329  int k;
2330  int incr=1;
2331  if(prev_ord==1) rO_Align(place,bitplace);
2332
2333  if (start>end)
2334  {
2335    incr=-1;
2336  }
2337  for(k=start;;k+=incr)
2338  {
2339    bitplace-=bits;
2340    if (bitplace < 0) { bitplace=BITS_PER_LONG-bits; place++; }
2341    o[place]=-1;
2342    v[k]=place | (bitplace << 24);
2343    if (k==end) break;
2344  }
2345  prev_ord=-1;
2346//  #if 0
2347  if (opt_var!= -1)
2348  {
2349    assume((opt_var == end+1) ||(opt_var == end-1));
2350    if((opt_var != end+1) &&(opt_var != end-1)) WarnS("hier-1");
2351    int save_bitplace=bitplace;
2352    bitplace-=bits;
2353    if (bitplace < 0)
2354    {
2355      bitplace=save_bitplace;
2356      return;
2357    }
2358    // there is enough space for the optional var
2359    v[opt_var]=place | (bitplace << 24);
2360  }
2361//  #endif
2362}
2363
2364static void rO_Syzcomp(int &place, int &bitplace, int &prev_ord,
2365    long *o, sro_ord &ord_struct)
2366{
2367  // ordering is derived from component number
2368  rO_Align(place,bitplace);
2369  ord_struct.ord_typ=ro_syzcomp;
2370  ord_struct.data.syzcomp.place=place;
2371  ord_struct.data.syzcomp.Components=NULL;
2372  ord_struct.data.syzcomp.ShiftedComponents=NULL;
2373  o[place]=1;
2374  prev_ord=1;
2375  place++;
2376  rO_Align(place,bitplace);
2377}
2378
2379static void rO_Syz(int &place, int &bitplace, int &prev_ord,
2380    long *o, sro_ord &ord_struct)
2381{
2382  // ordering is derived from component number
2383  // let's reserve one Exponent_t for it
2384  if ((prev_ord== 1) || (bitplace!=BITS_PER_LONG))
2385    rO_Align(place,bitplace);
2386  ord_struct.ord_typ=ro_syz;
2387  ord_struct.data.syz.place=place;
2388  ord_struct.data.syz.limit=0;
2389  ord_struct.data.syz.syz_index = NULL;
2390  ord_struct.data.syz.curr_index = 1;
2391  o[place]= -1;
2392  prev_ord=-1;
2393  place++;
2394}
2395
2396
2397static void rO_ISPrefix(int &place, int &bitplace, int &prev_ord,
2398    long *o, int N, int *v, sro_ord &ord_struct)
2399{
2400  if ((prev_ord== 1) || (bitplace!=BITS_PER_LONG))
2401    rO_Align(place,bitplace);
2402  // since we add something afterwards - it's better to start with anew!?
2403
2404  ord_struct.ord_typ = ro_isTemp;
2405  ord_struct.data.isTemp.start = place;
2406  ord_struct.data.isTemp.pVarOffset = (int *)omMemDup(v);
2407  ord_struct.data.isTemp.suffixpos = -1;
2408
2409  // We will act as rO_Syz on our own!!!
2410  // Here we allocate an exponent as a level placeholder
2411  o[place]= -1;
2412  prev_ord=-1;
2413  place++;
2414
2415#if MYTEST
2416  Print("rO_ISPrefix: place = %d, v: {", ord_struct.data.isTemp.start);
2417
2418  for( int i = 0; i <= N; i++ )
2419    Print("v[%d]: %09x", i, ord_struct.data.isTemp.pVarOffset[i]);
2420
2421  PrintS("}!\n");
2422#endif
2423}
2424static void rO_ISSuffix(int &place, int &bitplace, int &prev_ord, long *o,
2425  int N, int *v, sro_ord *tmp_typ, int &typ_i, int sgn)
2426{
2427#if MYTEST
2428  Print("rO_ISSuffix: place = %d\n", place);
2429#endif
2430
2431  // Let's find previous prefix:
2432  int typ_j = typ_i - 1;
2433  while(typ_j >= 0)
2434  {
2435    if( tmp_typ[typ_j].ord_typ == ro_isTemp)
2436      break;
2437    typ_j --;
2438  }
2439
2440  assume( typ_j >= 0 );
2441
2442  if( typ_j < 0 ) // Found NO prefix!!! :(
2443    return;
2444
2445  assume( tmp_typ[typ_j].ord_typ == ro_isTemp );
2446
2447  // Get saved state:
2448  const int start = tmp_typ[typ_j].data.isTemp.start;
2449  int *pVarOffset = tmp_typ[typ_j].data.isTemp.pVarOffset;
2450
2451/*
2452  // shift up all blocks
2453  while(typ_j < (typ_i-1))
2454  {
2455    tmp_typ[typ_j] = tmp_typ[typ_j+1];
2456    typ_j++;
2457  }
2458  typ_j = typ_i - 1; // No increment for typ_i
2459*/
2460  tmp_typ[typ_j].data.isTemp.suffixpos = typ_i;
2461
2462  // Let's keep that dummy for now...
2463  typ_j = typ_i; // the typ to change!
2464  typ_i++; // Just for now...
2465
2466
2467#if MYTEST
2468  PrintS("Changes in v: {");
2469#endif
2470
2471  for( int i = 0; i <= N; i++ ) // Note [0] == component !!! No Skip?
2472  {
2473    // Was i-th variable allocated inbetween?
2474    if( v[i] != pVarOffset[i] )
2475    {
2476      pVarOffset[i] = v[i]; // Save for later...
2477      v[i] = -1; // Undo!
2478      assume( pVarOffset[i] != -1 );
2479#if MYTEST
2480      Print("v[%d]: %010x", i, pVarOffset[i]);
2481#endif
2482    } else
2483      pVarOffset[i] = -1; // No change here...
2484  }
2485
2486  if( pVarOffset[0] != -1 )
2487    pVarOffset[0] &= 0x0fff;
2488
2489#if MYTEST
2490  PrintS("}!\n");
2491#endif
2492  sro_ord &ord_struct = tmp_typ[typ_j];
2493
2494
2495  ord_struct.ord_typ = ro_is;
2496  ord_struct.data.is.start = start;
2497  ord_struct.data.is.end   = place;
2498  ord_struct.data.is.pVarOffset = pVarOffset;
2499
2500
2501  // What about component???
2502//   if( v[0] != -1 ) // There is a component already...???
2503//     if( o[ v[0] & 0x0fff ] == sgn )
2504//     {
2505//       pVarOffset[0] = -1; // NEVER USED Afterwards...
2506//       return;
2507//     }
2508
2509 
2510  // Moreover: we need to allocate the module component (v[0]) here!
2511  if( v[0] == -1) // It's possible that there was module component v0 at the begining (before prefix)!
2512  {
2513    // Start with a whole long exponent
2514    if( bitplace != BITS_PER_LONG )
2515      rO_Align(place, bitplace);
2516
2517    assume( bitplace == BITS_PER_LONG );
2518    bitplace -= BITS_PER_LONG;
2519    assume(bitplace == 0);
2520    v[0] = place | (bitplace << 24); // Never mind whether pVarOffset[0] > 0!!!
2521    o[place] = sgn; // Singnum for component ordering
2522    prev_ord = sgn;
2523  }
2524}
2525
2526
2527static unsigned long rGetExpSize(unsigned long bitmask, int & bits)
2528{
2529  if (bitmask == 0)
2530  {
2531    bits=16; bitmask=0xffff;
2532  }
2533  else if (bitmask <= 1L)
2534  {
2535    bits=1; bitmask = 1L;
2536  }
2537  else if (bitmask <= 3L)
2538  {
2539    bits=2; bitmask = 3L;
2540  }
2541  else if (bitmask <= 7L)
2542  {
2543    bits=3; bitmask=7L;
2544  }
2545  else if (bitmask <= 0xfL)
2546  {
2547    bits=4; bitmask=0xfL;
2548  }
2549  else if (bitmask <= 0x1fL)
2550  {
2551    bits=5; bitmask=0x1fL;
2552  }
2553  else if (bitmask <= 0x3fL)
2554  {
2555    bits=6; bitmask=0x3fL;
2556  }
2557#if SIZEOF_LONG == 8
2558  else if (bitmask <= 0x7fL)
2559  {
2560    bits=7; bitmask=0x7fL; /* 64 bit longs only */
2561  }
2562#endif
2563  else if (bitmask <= 0xffL)
2564  {
2565    bits=8; bitmask=0xffL;
2566  }
2567#if SIZEOF_LONG == 8
2568  else if (bitmask <= 0x1ffL)
2569  {
2570    bits=9; bitmask=0x1ffL; /* 64 bit longs only */
2571  }
2572#endif
2573  else if (bitmask <= 0x3ffL)
2574  {
2575    bits=10; bitmask=0x3ffL;
2576  }
2577#if SIZEOF_LONG == 8
2578  else if (bitmask <= 0xfffL)
2579  {
2580    bits=12; bitmask=0xfff; /* 64 bit longs only */
2581  }
2582#endif
2583  else if (bitmask <= 0xffffL)
2584  {
2585    bits=16; bitmask=0xffffL;
2586  }
2587#if SIZEOF_LONG == 8
2588  else if (bitmask <= 0xfffffL)
2589  {
2590    bits=20; bitmask=0xfffffL; /* 64 bit longs only */
2591  }
2592  else if (bitmask <= 0xffffffffL)
2593  {
2594    bits=32; bitmask=0xffffffffL;
2595  }
2596  else if (bitmask <= 0x7fffffffffffffffL)
2597  {
2598    bits=63; bitmask=0x7fffffffffffffffL; /* for overflow tests*/
2599  }
2600  else
2601  {
2602    bits=63; bitmask=0x7fffffffffffffffL; /* for overflow tests*/
2603  }
2604#else
2605  else if (bitmask <= 0x7fffffff)
2606  {
2607    bits=31; bitmask=0x7fffffff; /* for overflow tests*/
2608  }
2609  else
2610  {
2611    bits=31; bitmask=0x7fffffffL; /* for overflow tests*/
2612  }
2613#endif
2614  return bitmask;
2615}
2616
2617/*2
2618* optimize rGetExpSize for a block of N variables, exp <=bitmask
2619*/
2620static unsigned long rGetExpSize(unsigned long bitmask, int & bits, int N)
2621{
2622  bitmask =rGetExpSize(bitmask, bits);
2623  int vars_per_long=BIT_SIZEOF_LONG/bits;
2624  int bits1;
2625  loop
2626  {
2627    if (bits == BIT_SIZEOF_LONG-1)
2628    {
2629      bits =  BIT_SIZEOF_LONG - 1;
2630      return LONG_MAX;
2631    }
2632    unsigned long bitmask1 =rGetExpSize(bitmask+1, bits1);
2633    int vars_per_long1=BIT_SIZEOF_LONG/bits1;
2634    if ((((N+vars_per_long-1)/vars_per_long) ==
2635         ((N+vars_per_long1-1)/vars_per_long1)))
2636    {
2637      vars_per_long=vars_per_long1;
2638      bits=bits1;
2639      bitmask=bitmask1;
2640    }
2641    else
2642    {
2643      return bitmask; /* and bits */
2644    }
2645  }
2646}
2647
2648
2649bool rSetISReference(const ideal F, const int i, const int p, const intvec * componentWeights, const ring r);
2650
2651
2652/*2
2653 * create a copy of the ring r, which must be equivalent to currRing
2654 * used for std computations
2655 * may share data structures with currRing
2656 * DOES CALL rComplete
2657 */
2658ring rModifyRing(ring r, BOOLEAN omit_degree,
2659                         BOOLEAN omit_comp,
2660                         unsigned long exp_limit)
2661{
2662  assume (r != NULL );
2663  assume (exp_limit > 1);
2664  BOOLEAN need_other_ring;
2665  BOOLEAN omitted_degree = FALSE;
2666
2667  int iNeedInducedOrderingSetup = 0; ///< How many induced ordering block do we have?
2668  int bits;
2669
2670  exp_limit=rGetExpSize(exp_limit, bits, r->N);
2671  need_other_ring = (exp_limit != r->bitmask);
2672
2673  int nblocks=rBlocks(r);
2674  int *order=(int*)omAlloc0((nblocks+1)*sizeof(int));
2675  int *block0=(int*)omAlloc0((nblocks+1)*sizeof(int));
2676  int *block1=(int*)omAlloc0((nblocks+1)*sizeof(int));
2677  int **wvhdl=(int**)omAlloc0((nblocks+1)*sizeof(int_ptr));
2678
2679  int i=0;
2680  int j=0; /*  i index in r, j index in res */
2681
2682  for( int r_ord=r->order[i]; (r_ord != 0) && (i < nblocks); j++, r_ord=r->order[++i])
2683  {
2684    BOOLEAN copy_block_index=TRUE;
2685
2686    if (r->block0[i]==r->block1[i])
2687    {
2688      switch(r_ord)
2689      {
2690        case ringorder_wp:
2691        case ringorder_dp:
2692        case ringorder_Wp:
2693        case ringorder_Dp:
2694          r_ord=ringorder_lp;
2695          break;
2696        case ringorder_Ws:
2697        case ringorder_Ds:
2698        case ringorder_ws:
2699        case ringorder_ds:
2700          r_ord=ringorder_ls;
2701          break;
2702        default:
2703          break;
2704      }
2705    }
2706    switch(r_ord)
2707    {
2708      case ringorder_S:
2709      {
2710#ifndef NDEBUG
2711        dReportError("Error: unhandled ordering in rModifyRing: ringorder_S = [%d]", r_ord);
2712#endif
2713        order[j]=r_ord; /*r->order[i];*/
2714        break;
2715      }
2716      case ringorder_C:
2717      case ringorder_c:
2718        if (!omit_comp)
2719        {
2720          order[j]=r_ord; /*r->order[i]*/;
2721        }
2722        else
2723        {
2724          j--;
2725          need_other_ring=TRUE;
2726          omit_comp=FALSE;
2727          copy_block_index=FALSE;
2728        }
2729        break;
2730      case ringorder_wp:
2731      case ringorder_dp:
2732      case ringorder_ws:
2733      case ringorder_ds:
2734        if(!omit_degree)
2735        {
2736          order[j]=r_ord; /*r->order[i]*/;
2737        }
2738        else
2739        {
2740          order[j]=ringorder_rs;
2741          need_other_ring=TRUE;
2742          omit_degree=FALSE;
2743          omitted_degree = TRUE;
2744        }
2745        break;
2746      case ringorder_Wp:
2747      case ringorder_Dp:
2748      case ringorder_Ws:
2749      case ringorder_Ds:
2750        if(!omit_degree)
2751        {
2752          order[j]=r_ord; /*r->order[i];*/
2753        }
2754        else
2755        {
2756          order[j]=ringorder_lp;
2757          need_other_ring=TRUE;
2758          omit_degree=FALSE;
2759          omitted_degree = TRUE;
2760        }
2761        break;
2762      case ringorder_IS:
2763      {
2764        if (omit_comp)
2765        {
2766          dReportError("Error: WRONG USAGE of rModifyRing: cannot omit component due to the ordering block [%d]: %d", i, r_ord);
2767          omit_comp = FALSE;
2768        }
2769        order[j]=r_ord; /*r->order[i];*/
2770        iNeedInducedOrderingSetup++;
2771        break;
2772      }
2773      case ringorder_s:
2774      {
2775        assume((i == 0) && (j == 0));
2776        if (omit_comp)
2777        {
2778#ifndef NDEBUG
2779          Warn("WRONG USAGE? of rModifyRing: omitting component due to the ordering block [%d]: %d", i, r_ord);
2780#endif
2781          omit_comp = FALSE;
2782        }
2783        order[j]=r_ord; /*r->order[i];*/
2784        break;
2785      }
2786      default:
2787        order[j]=r_ord; /*r->order[i];*/
2788        break;
2789    }
2790    if (copy_block_index)
2791    {
2792      block0[j]=r->block0[i];
2793      block1[j]=r->block1[i];
2794      wvhdl[j]=r->wvhdl[i];
2795    }
2796
2797    // order[j]=ringorder_no; //  done by omAlloc0
2798  }
2799  if(!need_other_ring)
2800  {
2801    omFreeSize(order,(nblocks+1)*sizeof(int));
2802    omFreeSize(block0,(nblocks+1)*sizeof(int));
2803    omFreeSize(block1,(nblocks+1)*sizeof(int));
2804    omFreeSize(wvhdl,(nblocks+1)*sizeof(int_ptr));
2805    return r;
2806  }
2807  ring res=(ring)omAlloc0Bin(ip_sring_bin);
2808  *res = *r;
2809
2810#ifdef HAVE_PLURAL
2811  res->GetNC() = NULL;
2812#endif
2813
2814  // res->qideal, res->idroot ???
2815  res->wvhdl=wvhdl;
2816  res->order=order;
2817  res->block0=block0;
2818  res->block1=block1;
2819  res->bitmask=exp_limit;
2820  int tmpref=r->cf->ref;
2821  rComplete(res, 1);
2822  r->cf->ref=tmpref;
2823
2824  // adjust res->pFDeg: if it was changed globally, then
2825  // it must also be changed for new ring
2826  if (r->pFDegOrig != res->pFDegOrig &&
2827           rOrd_is_WeightedDegree_Ordering(r))
2828  {
2829    // still might need adjustment for weighted orderings
2830    // and omit_degree
2831    res->firstwv = r->firstwv;
2832    res->firstBlockEnds = r->firstBlockEnds;
2833    res->pFDeg = res->pFDegOrig = pWFirstTotalDegree;
2834  }
2835  if (omitted_degree)
2836    res->pLDeg = res->pLDegOrig = r->pLDegOrig;
2837
2838  rOptimizeLDeg(res);
2839
2840  // set syzcomp
2841  if (res->typ != NULL)
2842  {
2843    if( res->typ[0].ord_typ == ro_syz) // "s" Always on [0] place!
2844    {
2845      res->typ[0] = r->typ[0]; // Copy struct!? + setup the same limit!
2846
2847      if (r->typ[0].data.syz.limit > 0)
2848      {
2849        res->typ[0].data.syz.syz_index
2850          = (int*) omAlloc((r->typ[0].data.syz.limit +1)*sizeof(int));
2851        memcpy(res->typ[0].data.syz.syz_index, r->typ[0].data.syz.syz_index,
2852              (r->typ[0].data.syz.limit +1)*sizeof(int));
2853      }
2854    }
2855
2856    if( iNeedInducedOrderingSetup > 0 )
2857    {
2858      for(j = 0, i = 0; (i < nblocks) && (iNeedInducedOrderingSetup > 0); i++)
2859        if( res->typ[i].ord_typ == ro_is ) // Search for suffixes!
2860        {
2861          ideal F = idrHeadR(r->typ[i].data.is.F, r, res); // Copy F from r into res!
2862          assume(
2863            rSetISReference(
2864              F,  // WILL BE COPIED!
2865              r->typ[i].data.is.limit,
2866              j++,
2867              r->typ[i].data.is.componentWeights, // WILL BE COPIED
2868              res)
2869            );
2870          id_Delete(&F, res);
2871          iNeedInducedOrderingSetup--;
2872        }
2873    } // Process all induced Ordering blocks! ...
2874  }
2875  // the special case: homog (omit_degree) and 1 block rs: that is global:
2876  // it comes from dp
2877  res->OrdSgn=r->OrdSgn;
2878
2879
2880#ifdef HAVE_PLURAL
2881  if (rIsPluralRing(r))
2882  {
2883    if ( nc_rComplete(r, res, false) ) // no qideal!
2884    {
2885#ifndef NDEBUG
2886      WarnS("error in nc_rComplete");
2887#endif
2888      // cleanup?
2889
2890//      rDelete(res);
2891//      return r;
2892
2893      // just go on..
2894    }
2895
2896    if( rIsSCA(r) )
2897    {
2898      if( !sca_Force(res, scaFirstAltVar(r), scaLastAltVar(r)) )
2899      WarnS("error in sca_Force!");
2900    }
2901  }
2902#endif
2903
2904  return res;
2905}
2906
2907// construct Wp,C ring
2908ring rModifyRing_Wp(ring r, int* weights)
2909{
2910  ring res=(ring)omAlloc0Bin(ip_sring_bin);
2911  *res = *r;
2912#ifdef HAVE_PLURAL
2913  res->GetNC() = NULL;
2914#endif
2915
2916  /*weights: entries for 3 blocks: NULL*/
2917  res->wvhdl = (int **)omAlloc0(3 * sizeof(int_ptr));
2918  /*order: Wp,C,0*/
2919  res->order = (int *) omAlloc(3 * sizeof(int *));
2920  res->block0 = (int *)omAlloc0(3 * sizeof(int *));
2921  res->block1 = (int *)omAlloc0(3 * sizeof(int *));
2922  /* ringorder Wp for the first block: var 1..r->N */
2923  res->order[0]  = ringorder_Wp;
2924  res->block0[0] = 1;
2925  res->block1[0] = r->N;
2926  res->wvhdl[0] = weights;
2927  /* ringorder C for the second block: no vars */
2928  res->order[1]  = ringorder_C;
2929  /* the last block: everything is 0 */
2930  res->order[2]  = 0;
2931  /*polynomial ring*/
2932  res->OrdSgn    = 1;
2933
2934  int tmpref=r->cf->ref;
2935  rComplete(res, 1);
2936  r->cf->ref=tmpref;
2937#ifdef HAVE_PLURAL
2938  if (rIsPluralRing(r))
2939  {
2940    if ( nc_rComplete(r, res, false) ) // no qideal!
2941    {
2942#ifndef NDEBUG
2943      WarnS("error in nc_rComplete");
2944#endif
2945      // cleanup?
2946
2947//      rDelete(res);
2948//      return r;
2949
2950      // just go on..
2951    }
2952  }
2953#endif
2954  return res;
2955}
2956
2957// construct lp, C ring with r->N variables, r->names vars....
2958ring rModifyRing_Simple(ring r, BOOLEAN ommit_degree, BOOLEAN ommit_comp, unsigned long exp_limit, BOOLEAN &simple)
2959{
2960  simple=TRUE;
2961  if (!rHasSimpleOrder(r))
2962  {
2963    simple=FALSE; // sorting needed
2964    assume (r != NULL );
2965    assume (exp_limit > 1);
2966    BOOLEAN omitted_degree = FALSE;
2967    int bits;
2968
2969    exp_limit=rGetExpSize(exp_limit, bits, r->N);
2970
2971    int nblocks=1+(ommit_comp!=0);
2972    int *order=(int*)omAlloc0((nblocks+1)*sizeof(int));
2973    int *block0=(int*)omAlloc0((nblocks+1)*sizeof(int));
2974    int *block1=(int*)omAlloc0((nblocks+1)*sizeof(int));
2975    int **wvhdl=(int**)omAlloc0((nblocks+1)*sizeof(int_ptr));
2976
2977    order[0]=ringorder_lp;
2978    block0[0]=1;
2979    block1[0]=r->N;
2980    if (!ommit_comp)
2981    {
2982      order[1]=ringorder_C;
2983    }
2984    ring res=(ring)omAlloc0Bin(ip_sring_bin);
2985    *res = *r;
2986#ifdef HAVE_PLURAL
2987    res->GetNC() = NULL;
2988#endif
2989    // res->qideal, res->idroot ???
2990    res->wvhdl=wvhdl;
2991    res->order=order;
2992    res->block0=block0;
2993    res->block1=block1;
2994    res->bitmask=exp_limit;
2995    int tmpref=r->cf->ref;
2996    rComplete(res, 1);
2997    r->cf->ref=tmpref;
2998
2999#ifdef HAVE_PLURAL
3000    if (rIsPluralRing(r))
3001    {
3002      if ( nc_rComplete(r, res, false) ) // no qideal!
3003      {
3004#ifndef NDEBUG
3005        WarnS("error in nc_rComplete");
3006#endif
3007        // cleanup?
3008
3009//      rDelete(res);
3010//      return r;
3011
3012      // just go on..
3013      }
3014    }
3015#endif
3016
3017    rOptimizeLDeg(res);
3018
3019    return res;
3020  }
3021  return rModifyRing(r, ommit_degree, ommit_comp, exp_limit);
3022}
3023
3024void rKillModifiedRing_Simple(ring r)
3025{
3026  rKillModifiedRing(r);
3027}
3028
3029
3030void rKillModifiedRing(ring r)
3031{
3032  rUnComplete(r);
3033  omFree(r->order);
3034  omFree(r->block0);
3035  omFree(r->block1);
3036  omFree(r->wvhdl);
3037  omFreeBin(r,ip_sring_bin);
3038}
3039
3040void rKillModified_Wp_Ring(ring r)
3041{
3042  rUnComplete(r);
3043  omFree(r->order);
3044  omFree(r->block0);
3045  omFree(r->block1);
3046  omFree(r->wvhdl[0]);
3047  omFree(r->wvhdl);
3048  omFreeBin(r,ip_sring_bin);
3049}
3050
3051static void rSetOutParams(ring r)
3052{
3053  r->VectorOut = (r->order[0] == ringorder_c);
3054  r->ShortOut = TRUE;
3055#ifdef HAVE_TCL
3056  if (tcllmode)
3057  {
3058    r->ShortOut = FALSE;
3059  }
3060  else
3061#endif
3062  {
3063    int i;
3064    if ((r->parameter!=NULL) && (r->ch<2))
3065    {
3066      for (i=0;i<rPar(r);i++)
3067      {
3068        if(strlen(r->parameter[i])>1)
3069        {
3070          r->ShortOut=FALSE;
3071          break;
3072        }
3073      }
3074    }
3075    if (r->ShortOut)
3076    {
3077      // Hmm... sometimes (e.g., from maGetPreimage) new variables
3078      // are intorduced, but their names are never set
3079      // hence, we do the following awkward trick
3080      int N = omSizeWOfAddr(r->names);
3081      if (r->N < N) N = r->N;
3082
3083      for (i=(N-1);i>=0;i--)
3084      {
3085        if(r->names[i] != NULL && strlen(r->names[i])>1)
3086        {
3087          r->ShortOut=FALSE;
3088          break;
3089        }
3090      }
3091    }
3092  }
3093  r->CanShortOut = r->ShortOut;
3094}
3095
3096/*2
3097* sets pMixedOrder and pComponentOrder for orderings with more than one block
3098* block of variables (ip is the block number, o_r the number of the ordering)
3099* o is the position of the orderingering in r
3100*/
3101static void rHighSet(ring r, int o_r, int o)
3102{
3103  switch(o_r)
3104  {
3105    case ringorder_lp:
3106    case ringorder_dp:
3107    case ringorder_Dp:
3108    case ringorder_wp:
3109    case ringorder_Wp:
3110    case ringorder_rp:
3111    case ringorder_a:
3112    case ringorder_aa:
3113    case ringorder_a64:
3114      if (r->OrdSgn==-1) r->MixedOrder=TRUE;
3115      break;
3116    case ringorder_ls:
3117    case ringorder_rs:
3118    case ringorder_ds:
3119    case ringorder_Ds:
3120    case ringorder_s:
3121      break;
3122    case ringorder_ws:
3123    case ringorder_Ws:
3124      if (r->wvhdl[o]!=NULL)
3125      {
3126        int i;
3127        for(i=r->block1[o]-r->block0[o];i>=0;i--)
3128          if (r->wvhdl[o][i]<0) { r->MixedOrder=TRUE; break; }
3129      }
3130      break;
3131    case ringorder_c:
3132      r->ComponentOrder=1;
3133      break;
3134    case ringorder_C:
3135    case ringorder_S:
3136      r->ComponentOrder=-1;
3137      break;
3138    case ringorder_M:
3139      r->MixedOrder=TRUE;
3140      break;
3141    case ringorder_IS:
3142    { // TODO: What is r->ComponentOrder???
3143      r->MixedOrder=TRUE;
3144/*
3145      if( r->block0[o] != 0 ) // Suffix has the comonent
3146        r->ComponentOrder = r->block0[o];
3147      else // Prefix has level...
3148        r->ComponentOrder=-1;
3149*/
3150      break;
3151    }
3152
3153    default:
3154      dReportError("wrong internal ordering:%d at %s, l:%d\n",o_r,__FILE__,__LINE__);
3155  }
3156}
3157
3158static void rSetFirstWv(ring r, int i, int* order, int* block1, int** wvhdl)
3159{
3160  // cheat for ringorder_aa
3161  if (order[i] == ringorder_aa)
3162    i++;
3163  if(block1[i]!=r->N) r->LexOrder=TRUE;
3164  r->firstBlockEnds=block1[i];
3165  r->firstwv = wvhdl[i];
3166  if ((order[i]== ringorder_ws)
3167  || (order[i]==ringorder_Ws)
3168  || (order[i]== ringorder_wp)
3169  || (order[i]==ringorder_Wp)
3170  || (order[i]== ringorder_a)
3171   /*|| (order[i]==ringorder_A)*/)
3172  {
3173    int j;
3174    for(j=block1[i]-r->block0[i];j>=0;j--)
3175    {
3176      if (r->firstwv[j]<0) r->MixedOrder=TRUE;
3177      if (r->firstwv[j]==0) r->LexOrder=TRUE;
3178    }
3179  }
3180  else if (order[i]==ringorder_a64)
3181  {
3182    int j;
3183    int64 *w=rGetWeightVec(r);
3184    for(j=block1[i]-r->block0[i];j>=0;j--)
3185    {
3186      if (w[j]==0) r->LexOrder=TRUE;
3187    }
3188  }
3189}
3190
3191static void rOptimizeLDeg(ring r)
3192{
3193  if (r->pFDeg == pDeg)
3194  {
3195    if (r->pLDeg == pLDeg1)
3196      r->pLDeg = pLDeg1_Deg;
3197    if (r->pLDeg == pLDeg1c)
3198      r->pLDeg = pLDeg1c_Deg;
3199  }
3200  else if (r->pFDeg == pTotaldegree)
3201  {
3202    if (r->pLDeg == pLDeg1)
3203      r->pLDeg = pLDeg1_Totaldegree;
3204    if (r->pLDeg == pLDeg1c)
3205      r->pLDeg = pLDeg1c_Totaldegree;
3206  }
3207  else if (r->pFDeg == pWFirstTotalDegree)
3208  {
3209    if (r->pLDeg == pLDeg1)
3210      r->pLDeg = pLDeg1_WFirstTotalDegree;
3211    if (r->pLDeg == pLDeg1c)
3212      r->pLDeg = pLDeg1c_WFirstTotalDegree;
3213  }
3214}
3215
3216// set pFDeg, pLDeg, MixOrder, ComponentOrder, etc
3217static void rSetDegStuff(ring r)
3218{
3219  int* order = r->order;
3220  int* block0 = r->block0;
3221  int* block1 = r->block1;
3222  int** wvhdl = r->wvhdl;
3223
3224  if (order[0]==ringorder_S ||order[0]==ringorder_s || order[0]==ringorder_IS)
3225  {
3226    order++;
3227    block0++;
3228    block1++;
3229    wvhdl++;
3230  }
3231  r->LexOrder = FALSE;
3232  r->MixedOrder = FALSE;
3233  r->ComponentOrder = 1;
3234  r->pFDeg = pTotaldegree;
3235  r->pLDeg = (r->OrdSgn == 1 ? pLDegb : pLDeg0);
3236
3237  /*======== ordering type is (_,c) =========================*/
3238  if ((order[0]==ringorder_unspec) || (order[1] == 0)
3239      ||(
3240    ((order[1]==ringorder_c)||(order[1]==ringorder_C)
3241     ||(order[1]==ringorder_S) ||(order[1]==ringorder_IS)
3242     ||(order[1]==ringorder_s))
3243    && (order[0]!=ringorder_M)
3244    && (order[2]==0))
3245    )
3246  {
3247    if ((order[0]!=ringorder_unspec)
3248    && ((order[1]==ringorder_C)||(order[1]==ringorder_S)||(order[1]==ringorder_IS)||
3249        (order[1]==ringorder_s)))
3250      r->ComponentOrder=-1;
3251    if (r->OrdSgn == -1) r->pLDeg = pLDeg0c;
3252    if ((order[0] == ringorder_lp)
3253    || (order[0] == ringorder_ls)
3254    || (order[0] == ringorder_rp)
3255    || (order[0] == ringorder_rs))
3256    {
3257      r->LexOrder=TRUE;
3258      r->pLDeg = pLDeg1c;
3259      r->pFDeg = pTotaldegree;
3260    }
3261    if ((order[0] == ringorder_a)
3262    || (order[0] == ringorder_wp)
3263    || (order[0] == ringorder_Wp)
3264    || (order[0] == ringorder_ws)
3265    || (order[0] == ringorder_Ws))
3266      r->pFDeg = pWFirstTotalDegree;
3267    r->firstBlockEnds=block1[0];
3268    r->firstwv = wvhdl[0];
3269  }
3270  /*======== ordering type is (c,_) =========================*/
3271  else if (((order[0]==ringorder_c)
3272            ||(order[0]==ringorder_C)
3273            ||(order[0]==ringorder_S) ||(order[0]==ringorder_IS)
3274            ||(order[0]==ringorder_s))
3275  && (order[1]!=ringorder_M)
3276  &&  (order[2]==0))
3277  {
3278    if ((order[0]==ringorder_C)||(order[0]==ringorder_S)|| (order[0]==ringorder_IS) ||
3279        order[0]==ringorder_s)
3280      r->ComponentOrder=-1;
3281    if ((order[1] == ringorder_lp)
3282    || (order[1] == ringorder_ls)
3283    || (order[1] == ringorder_rp)
3284    || order[1] == ringorder_rs)
3285    {
3286      r->LexOrder=TRUE;
3287      r->pLDeg = pLDeg1c;
3288      r->pFDeg = pTotaldegree;
3289    }
3290    r->firstBlockEnds=block1[1];
3291    r->firstwv = wvhdl[1];
3292    if ((order[1] == ringorder_a)
3293    || (order[1] == ringorder_wp)
3294    || (order[1] == ringorder_Wp)
3295    || (order[1] == ringorder_ws)
3296    || (order[1] == ringorder_Ws))
3297      r->pFDeg = pWFirstTotalDegree;
3298  }
3299  /*------- more than one block ----------------------*/
3300  else
3301  {
3302    if ((r->VectorOut)||(order[0]==ringorder_C)||(order[0]==ringorder_S)||(order[0]==ringorder_s) ||(order[0]==ringorder_IS))
3303    {
3304      rSetFirstWv(r, 1, order, block1, wvhdl);
3305    }
3306    else
3307      rSetFirstWv(r, 0, order, block1, wvhdl);
3308
3309    /*the number of orderings:*/
3310    int i = 0;
3311    while (order[++i] != 0);
3312    do
3313    {
3314      i--;
3315      rHighSet(r, order[i],i);
3316    }
3317    while (i != 0);
3318
3319    if ((order[0]!=ringorder_c)
3320        && (order[0]!=ringorder_C)
3321        && (order[0]!=ringorder_S) && (order[0]!=ringorder_IS)
3322        && (order[0]!=ringorder_s))
3323    {
3324      r->pLDeg = pLDeg1c;
3325    }
3326    else
3327    {
3328      r->pLDeg = pLDeg1;
3329    }
3330    r->pFDeg = pWTotaldegree; // may be improved: pTotaldegree for lp/dp/ls/.. blocks
3331  }
3332  if (rOrd_is_Totaldegree_Ordering(r) || rOrd_is_WeightedDegree_Ordering(r))
3333    r->pFDeg = pDeg;
3334
3335  r->pFDegOrig = r->pFDeg;
3336  r->pLDegOrig = r->pLDeg;
3337  rOptimizeLDeg(r);
3338}
3339
3340/*2
3341* set NegWeightL_Size, NegWeightL_Offset
3342*/
3343static void rSetNegWeight(ring r)
3344{
3345  int i,l;
3346  if (r->typ!=NULL)
3347  {
3348    l=0;
3349    for(i=0;i<r->OrdSize;i++)
3350    {
3351      if(r->typ[i].ord_typ==ro_wp_neg) l++;
3352    }
3353    if (l>0)
3354    {
3355      r->NegWeightL_Size=l;
3356      r->NegWeightL_Offset=(int *) omAlloc(l*sizeof(int));
3357      l=0;
3358      for(i=0;i<r->OrdSize;i++)
3359      {
3360        if(r->typ[i].ord_typ==ro_wp_neg)
3361        {
3362          r->NegWeightL_Offset[l]=r->typ[i].data.wp.place;
3363          l++;
3364        }
3365      }
3366      return;
3367    }
3368  }
3369  r->NegWeightL_Size = 0;
3370  r->NegWeightL_Offset = NULL;
3371}
3372
3373static void rSetOption(ring r)
3374{
3375  // set redthrough
3376  if (!TEST_OPT_OLDSTD && r->OrdSgn == 1 && ! r->LexOrder)
3377    r->options |= Sy_bit(OPT_REDTHROUGH);
3378  else
3379    r->options &= ~Sy_bit(OPT_REDTHROUGH);
3380
3381  // set intStrategy
3382#ifdef HAVE_RINGS
3383  if (rField_is_Extension(r) || rField_is_Q(r) || rField_is_Ring(r))
3384#else
3385  if (rField_is_Extension(r) || rField_is_Q(r))
3386#endif
3387    r->options |= Sy_bit(OPT_INTSTRATEGY);
3388  else
3389    r->options &= ~Sy_bit(OPT_INTSTRATEGY);
3390
3391  // set redTail
3392  if (r->LexOrder || r->OrdSgn == -1 || rField_is_Extension(r))
3393    r->options &= ~Sy_bit(OPT_REDTAIL);
3394  else
3395    r->options |= Sy_bit(OPT_REDTAIL);
3396}
3397
3398BOOLEAN rComplete(ring r, int force)
3399{
3400  if (r->VarOffset!=NULL && force == 0) return FALSE;
3401  nInitChar(r);
3402  rSetOutParams(r);
3403  int n=rBlocks(r)-1;
3404  int i;
3405  int bits;
3406  r->bitmask=rGetExpSize(r->bitmask,bits,r->N);
3407  r->BitsPerExp = bits;
3408  r->ExpPerLong = BIT_SIZEOF_LONG / bits;
3409  r->divmask=rGetDivMask(bits);
3410
3411  // will be used for ordsgn:
3412  long *tmp_ordsgn=(long *)omAlloc0(3*(n+r->N)*sizeof(long));
3413  // will be used for VarOffset:
3414  int *v=(int *)omAlloc((r->N+1)*sizeof(int));
3415  for(i=r->N; i>=0 ; i--)
3416  {
3417    v[i]=-1;
3418  }
3419  sro_ord *tmp_typ=(sro_ord *)omAlloc0(3*(n+r->N)*sizeof(sro_ord));
3420  int typ_i=0;
3421  int prev_ordsgn=0;
3422
3423  // fill in v, tmp_typ, tmp_ordsgn, determine typ_i (== ordSize)
3424  int j=0;
3425  int j_bits=BITS_PER_LONG;
3426
3427  BOOLEAN need_to_add_comp=FALSE; // Only for ringorder_s and ringorder_S!
3428
3429  for(i=0;i<n;i++)
3430  {
3431    tmp_typ[typ_i].order_index=i;
3432    switch (r->order[i])
3433    {
3434      case ringorder_a:
3435      case ringorder_aa:
3436        rO_WDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,tmp_typ[typ_i],
3437                   r->wvhdl[i]);
3438        typ_i++;
3439        break;
3440
3441      case ringorder_a64:
3442        rO_WDegree64(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3443                     tmp_typ[typ_i], (int64 *)(r->wvhdl[i]));
3444        typ_i++;
3445        break;
3446
3447      case ringorder_c:
3448        rO_Align(j, j_bits);
3449        rO_LexVars_neg(j, j_bits, 0,0, prev_ordsgn,tmp_ordsgn,v,BITS_PER_LONG, -1);
3450        break;
3451
3452      case ringorder_C:
3453        rO_Align(j, j_bits);
3454        rO_LexVars(j, j_bits, 0,0, prev_ordsgn,tmp_ordsgn,v,BITS_PER_LONG, -1);
3455        break;
3456
3457      case ringorder_M:
3458        {
3459          int k,l;
3460          k=r->block1[i]-r->block0[i]+1; // number of vars
3461          for(l=0;l<k;l++)
3462          {
3463            rO_WDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3464                       tmp_typ[typ_i],
3465                       r->wvhdl[i]+(r->block1[i]-r->block0[i]+1)*l);
3466            typ_i++;
3467          }
3468          break;
3469        }
3470
3471      case ringorder_lp:
3472        rO_LexVars(j, j_bits, r->block0[i],r->block1[i], prev_ordsgn,
3473                   tmp_ordsgn,v,bits, -1);
3474        break;
3475
3476      case ringorder_ls:
3477        rO_LexVars_neg(j, j_bits, r->block0[i],r->block1[i], prev_ordsgn,
3478                       tmp_ordsgn,v, bits, -1);
3479        break;
3480
3481      case ringorder_rs:
3482        rO_LexVars_neg(j, j_bits, r->block1[i],r->block0[i], prev_ordsgn,
3483                       tmp_ordsgn,v, bits, -1);
3484        break;
3485
3486      case ringorder_rp:
3487        rO_LexVars(j, j_bits, r->block1[i],r->block0[i], prev_ordsgn,
3488                       tmp_ordsgn,v, bits, -1);
3489        break;
3490
3491      case ringorder_dp:
3492        if (r->block0[i]==r->block1[i])
3493        {
3494          rO_LexVars(j, j_bits, r->block0[i],r->block0[i], prev_ordsgn,
3495                     tmp_ordsgn,v, bits, -1);
3496        }
3497        else
3498        {
3499          rO_TDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3500                     tmp_typ[typ_i]);
3501          typ_i++;
3502          rO_LexVars_neg(j, j_bits, r->block1[i],r->block0[i]+1,
3503                         prev_ordsgn,tmp_ordsgn,v,bits, r->block0[i]);
3504        }
3505        break;
3506
3507      case ringorder_Dp:
3508        if (r->block0[i]==r->block1[i])
3509        {
3510          rO_LexVars(j, j_bits, r->block0[i],r->block0[i], prev_ordsgn,
3511                     tmp_ordsgn,v, bits, -1);
3512        }
3513        else
3514        {
3515          rO_TDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3516                     tmp_typ[typ_i]);
3517          typ_i++;
3518          rO_LexVars(j, j_bits, r->block0[i],r->block1[i]-1, prev_ordsgn,
3519                     tmp_ordsgn,v, bits, r->block1[i]);
3520        }
3521        break;
3522
3523      case ringorder_ds:
3524        if (r->block0[i]==r->block1[i])
3525        {
3526          rO_LexVars_neg(j, j_bits,r->block0[i],r->block1[i],prev_ordsgn,
3527                         tmp_ordsgn,v,bits, -1);
3528        }
3529        else
3530        {
3531          rO_TDegree_neg(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3532                         tmp_typ[typ_i]);
3533          typ_i++;
3534          rO_LexVars_neg(j, j_bits, r->block1[i],r->block0[i]+1,
3535                         prev_ordsgn,tmp_ordsgn,v,bits, r->block0[i]);
3536        }
3537        break;
3538
3539      case ringorder_Ds:
3540        if (r->block0[i]==r->block1[i])
3541        {
3542          rO_LexVars_neg(j, j_bits, r->block0[i],r->block0[i],prev_ordsgn,
3543                         tmp_ordsgn,v, bits, -1);
3544        }
3545        else
3546        {
3547          rO_TDegree_neg(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3548                         tmp_typ[typ_i]);
3549          typ_i++;
3550          rO_LexVars(j, j_bits, r->block0[i],r->block1[i]-1, prev_ordsgn,
3551                     tmp_ordsgn,v, bits, r->block1[i]);
3552        }
3553        break;
3554
3555      case ringorder_wp:
3556        rO_WDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3557                   tmp_typ[typ_i], r->wvhdl[i]);
3558        typ_i++;
3559        { // check for weights <=0
3560          int jj;
3561          BOOLEAN have_bad_weights=FALSE;
3562          for(jj=r->block1[i]-r->block0[i];jj>=0; jj--)
3563          {
3564            if (r->wvhdl[i][jj]<=0) have_bad_weights=TRUE;
3565          }
3566          if (have_bad_weights)
3567          {
3568             rO_TDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3569                                     tmp_typ[typ_i]);
3570             typ_i++;
3571          }
3572        }
3573        if (r->block1[i]!=r->block0[i])
3574        {
3575          rO_LexVars_neg(j, j_bits,r->block1[i],r->block0[i]+1, prev_ordsgn,
3576                         tmp_ordsgn, v,bits, r->block0[i]);
3577        }
3578        break;
3579
3580      case ringorder_Wp:
3581        rO_WDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3582                   tmp_typ[typ_i], r->wvhdl[i]);
3583        typ_i++;
3584        { // check for weights <=0
3585          int j;
3586          BOOLEAN have_bad_weights=FALSE;
3587          for(j=r->block1[i]-r->block0[i];j>=0; j--)
3588          {
3589            if (r->wvhdl[i][j]<=0) have_bad_weights=TRUE;
3590          }
3591          if (have_bad_weights)
3592          {
3593             rO_TDegree(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3594                                     tmp_typ[typ_i]);
3595             typ_i++;
3596          }
3597        }
3598        if (r->block1[i]!=r->block0[i])
3599        {
3600          rO_LexVars(j, j_bits,r->block0[i],r->block1[i]-1, prev_ordsgn,
3601                     tmp_ordsgn,v, bits, r->block1[i]);
3602        }
3603        break;
3604
3605      case ringorder_ws:
3606        rO_WDegree_neg(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3607                       tmp_typ[typ_i], r->wvhdl[i]);
3608        typ_i++;
3609        if (r->block1[i]!=r->block0[i])
3610        {
3611          rO_LexVars_neg(j, j_bits,r->block1[i],r->block0[i]+1, prev_ordsgn,
3612                         tmp_ordsgn, v,bits, r->block0[i]);
3613        }
3614        break;
3615
3616      case ringorder_Ws:
3617        rO_WDegree_neg(j,j_bits,r->block0[i],r->block1[i],tmp_ordsgn,
3618                       tmp_typ[typ_i], r->wvhdl[i]);
3619        typ_i++;
3620        if (r->block1[i]!=r->block0[i])
3621        {
3622          rO_LexVars(j, j_bits,r->block0[i],r->block1[i]-1, prev_ordsgn,
3623                     tmp_ordsgn,v, bits, r->block1[i]);
3624        }
3625        break;
3626
3627      case ringorder_S:
3628        assume(typ_i == 0 && j == 0);
3629        rO_Syzcomp(j, j_bits,prev_ordsgn, tmp_ordsgn,tmp_typ[typ_i]);
3630        need_to_add_comp=TRUE;
3631        typ_i++;
3632        break;
3633
3634      case ringorder_s:
3635        assume(typ_i == 0 && j == 0);
3636        rO_Syz(j, j_bits, prev_ordsgn, tmp_ordsgn, tmp_typ[typ_i]);
3637        need_to_add_comp=TRUE;
3638        typ_i++;
3639        break;
3640
3641      case ringorder_IS:
3642      {
3643        const int s = r->block0[i];
3644        assume( s >= -1 && s <= 1);
3645
3646        assume( r->block0[i] == r->block1[i] );
3647
3648        if(s == 0) // Prefix IS
3649          rO_ISPrefix(j, j_bits, prev_ordsgn, tmp_ordsgn, r->N, v, tmp_typ[typ_i++]); // What about prev_ordsgn?
3650        else // s = +1 or -1 // Note: typ_i might be incrimented here inside!
3651        {
3652          rO_ISSuffix(j, j_bits, prev_ordsgn, tmp_ordsgn, r->N, v, tmp_typ, typ_i, s); // Suffix.
3653          need_to_add_comp=FALSE;
3654        }
3655
3656        break;
3657      }
3658      case ringorder_unspec:
3659      case ringorder_no:
3660      default:
3661        dReportError("undef. ringorder used\n");
3662        break;
3663    }
3664  }
3665
3666  int j0=j; // save j
3667  int j_bits0=j_bits; // save jbits
3668  rO_Align(j,j_bits);
3669  r->CmpL_Size = j;
3670
3671  j_bits=j_bits0; j=j0;
3672
3673  // fill in some empty slots with variables not already covered
3674  // v0 is special, is therefore normally already covered
3675  // now we do have rings without comp...
3676  if((need_to_add_comp) && (v[0]== -1))
3677  {
3678    if (prev_ordsgn==1)
3679    {
3680      rO_Align(j, j_bits);
3681      rO_LexVars(j, j_bits, 0,0, prev_ordsgn,tmp_ordsgn,v,BITS_PER_LONG, -1);
3682    }
3683    else
3684    {
3685      rO_Align(j, j_bits);
3686      rO_LexVars_neg(j, j_bits, 0,0, prev_ordsgn,tmp_ordsgn,v,BITS_PER_LONG, -1);
3687    }
3688  }
3689  // the variables
3690  for(i=1 ; i<=r->N ; i++)
3691  {
3692    if(v[i]==(-1))
3693    {
3694      if (prev_ordsgn==1)
3695      {
3696        rO_LexVars(j, j_bits, i,i, prev_ordsgn,tmp_ordsgn,v,bits, -1);
3697      }
3698      else
3699      {
3700        rO_LexVars_neg(j,j_bits,i,i, prev_ordsgn,tmp_ordsgn,v,bits, -1);
3701      }
3702    }
3703  }
3704
3705  rO_Align(j,j_bits);
3706  // ----------------------------
3707  // finished with constructing the monomial, computing sizes:
3708
3709  r->ExpL_Size=j;
3710  r->PolyBin = omGetSpecBin(POLYSIZE + (r->ExpL_Size)*sizeof(long));
3711  assume(r->PolyBin != NULL);
3712
3713  // ----------------------------
3714  // indices and ordsgn vector for comparison
3715  //
3716  // r->pCompHighIndex already set
3717  r->ordsgn=(long *)omAlloc0(r->ExpL_Size*sizeof(long));
3718
3719  for(j=0;j<r->CmpL_Size;j++)
3720  {
3721    r->ordsgn[j] = tmp_ordsgn[j];
3722  }
3723
3724  omFreeSize((ADDRESS)tmp_ordsgn,(3*(n+r->N)*sizeof(long)));
3725
3726  // ----------------------------
3727  // description of orderings for setm:
3728  //
3729  r->OrdSize=typ_i;
3730  if (typ_i==0) r->typ=NULL;
3731  else
3732  {
3733    r->typ=(sro_ord*)omAlloc(typ_i*sizeof(sro_ord));
3734    memcpy(r->typ,tmp_typ,typ_i*sizeof(sro_ord));
3735  }
3736  omFreeSize((ADDRESS)tmp_typ,(3*(n+r->N)*sizeof(sro_ord)));
3737
3738  // ----------------------------
3739  // indices for (first copy of ) variable entries in exp.e vector (VarOffset):
3740  r->VarOffset=v;
3741
3742  // ----------------------------
3743  // other indicies
3744  r->pCompIndex=(r->VarOffset[0] & 0xffff); //r->VarOffset[0];
3745  i=0; // position
3746  j=0; // index in r->typ
3747  if (i==r->pCompIndex) i++; // IS???
3748  while ((j < r->OrdSize)
3749         && ((r->typ[j].ord_typ==ro_syzcomp) ||
3750             (r->typ[j].ord_typ==ro_syz) || (r->typ[j].ord_typ==ro_isTemp) || (r->typ[j].ord_typ==ro_is) ||
3751             (r->order[r->typ[j].order_index] == ringorder_aa)))
3752  {
3753    i++; j++;
3754  }
3755  // No use of j anymore!!!????
3756
3757  if (i==r->pCompIndex) i++;
3758  r->pOrdIndex=i; // How came it is "i" here???!!!! exp[r->pOrdIndex] is order of a poly... This may be wrong!!! IS
3759
3760  // ----------------------------
3761  rSetDegStuff(r);
3762  rSetOption(r);
3763  // ----------------------------
3764  // r->p_Setm
3765  r->p_Setm = p_GetSetmProc(r);
3766
3767  // ----------------------------
3768  // set VarL_*
3769  rSetVarL(r);
3770
3771  //  ----------------------------
3772  // right-adjust VarOffset
3773  rRightAdjustVarOffset(r);
3774
3775  // ----------------------------
3776  // set NegWeightL*
3777  rSetNegWeight(r);
3778
3779  // ----------------------------
3780  // p_Procs: call AFTER NegWeightL
3781  r->p_Procs = (p_Procs_s*)omAlloc(sizeof(p_Procs_s));
3782  p_ProcsSet(r, r->p_Procs);
3783  return FALSE;
3784}
3785
3786void rUnComplete(ring r)
3787{
3788  if (r == NULL) return;
3789  if (r->VarOffset != NULL)
3790  {
3791    if (r->OrdSize!=0 && r->typ != NULL)
3792    {
3793      for(int i = 0; i < r->OrdSize; i++)
3794        if( r->typ[i].ord_typ == ro_is) // Search for suffixes! (prefix have the same VarOffset)
3795        {
3796          id_Delete(&r->typ[i].data.is.F, r);
3797          r->typ[i].data.is.F = NULL; // ?
3798
3799          if( r->typ[i].data.is.componentWeights != NULL )
3800          {
3801            delete r->typ[i].data.is.componentWeights;
3802            r->typ[i].data.is.componentWeights = NULL; // ?
3803          }
3804         
3805
3806          if( r->typ[i].data.is.pVarOffset != NULL )
3807          {
3808            omFreeSize((ADDRESS)r->typ[i].data.is.pVarOffset, (r->N +1)*sizeof(int));
3809            r->typ[i].data.is.pVarOffset = NULL; // ?
3810          }
3811        }
3812        else if (r->typ[i].ord_typ == ro_syz)
3813        {
3814          if(r->typ[i].data.syz.limit > 0)
3815            omFreeSize(r->typ[i].data.syz.syz_index, ((r->typ[i].data.syz.limit) +1)*sizeof(int)); 
3816          r->typ[i].data.syz.syz_index = NULL;
3817        } else if (r->typ[i].ord_typ == ro_syzcomp)
3818        {
3819#ifndef NDEBUG
3820          Warn( "rUnComplete : ord_typ == ro_syzcomp was unhandled!!! Possibly memory leak!!!"  );
3821#endif
3822        }
3823
3824      omFreeSize((ADDRESS)r->typ,r->OrdSize*sizeof(sro_ord)); r->typ = NULL;
3825    }
3826
3827    if (r->order != NULL)
3828    {
3829      // delete r->order!!!???
3830    }
3831
3832    if (r->PolyBin != NULL)
3833      omUnGetSpecBin(&(r->PolyBin));
3834
3835    omFreeSize((ADDRESS)r->VarOffset, (r->N +1)*sizeof(int));
3836   
3837    if (r->ordsgn != NULL && r->CmpL_Size != 0)
3838      omFreeSize((ADDRESS)r->ordsgn,r->ExpL_Size*sizeof(long));
3839    if (r->p_Procs != NULL)
3840      omFreeSize(r->p_Procs, sizeof(p_Procs_s));
3841    omfreeSize(r->VarL_Offset, r->VarL_Size*sizeof(int));
3842  }
3843  if (r->NegWeightL_Offset!=NULL)
3844  {
3845    omFreeSize(r->NegWeightL_Offset, r->NegWeightL_Size*sizeof(int));
3846    r->NegWeightL_Offset=NULL;
3847  }
3848}
3849
3850// set r->VarL_Size, r->VarL_Offset, r->VarL_LowIndex
3851static void rSetVarL(ring r)
3852{
3853  int  min = INT_MAX, min_j = -1;
3854  int* VarL_Number = (int*) omAlloc0(r->ExpL_Size*sizeof(int));
3855
3856  int i,j;
3857
3858  // count how often a var long is occupied by an exponent
3859  for (i=1; i<=r->N; i++)
3860  {
3861    VarL_Number[r->VarOffset[i] & 0xffffff]++;
3862  }
3863
3864  // determine how many and min
3865  for (i=0, j=0; i<r->ExpL_Size; i++)
3866  {
3867    if (VarL_Number[i] != 0)
3868    {
3869      if (min > VarL_Number[i])
3870      {
3871        min = VarL_Number[i];
3872        min_j = j;
3873      }
3874      j++;
3875    }
3876  }
3877
3878  r->VarL_Size = j; // number of long with exp. entries in
3879                    //  in p->exp
3880  r->VarL_Offset = (int*) omAlloc(r->VarL_Size*sizeof(int));
3881  r->VarL_LowIndex = 0;
3882
3883  // set VarL_Offset
3884  for (i=0, j=0; i<r->ExpL_Size; i++)
3885  {
3886    if (VarL_Number[i] != 0)
3887    {
3888      r->VarL_Offset[j] = i;
3889      if (j > 0 && r->VarL_Offset[j-1] != r->VarL_Offset[j] - 1)
3890        r->VarL_LowIndex = -1;
3891      j++;
3892    }
3893  }
3894  if (r->VarL_LowIndex >= 0)
3895    r->VarL_LowIndex = r->VarL_Offset[0];
3896
3897  r->MinExpPerLong = min;
3898  if (min_j != 0)
3899  {
3900    j = r->VarL_Offset[min_j];
3901    r->VarL_Offset[min_j] = r->VarL_Offset[0];
3902    r->VarL_Offset[0] = j;
3903  }
3904  omFree(VarL_Number);
3905}
3906
3907static void rRightAdjustVarOffset(ring r)
3908{
3909  int* shifts = (int*) omAlloc(r->ExpL_Size*sizeof(int));
3910  int i;
3911  // initialize shifts
3912  for (i=0;i<r->ExpL_Size;i++)
3913    shifts[i] = BIT_SIZEOF_LONG;
3914
3915  // find minimal bit shift in each long exp entry
3916  for (i=1;i<=r->N;i++)
3917  {
3918    if (shifts[r->VarOffset[i] & 0xffffff] > r->VarOffset[i] >> 24)
3919      shifts[r->VarOffset[i] & 0xffffff] = r->VarOffset[i] >> 24;
3920  }
3921  // reset r->VarOffset: set the minimal shift to 0
3922  for (i=1;i<=r->N;i++)
3923  {
3924    if (shifts[r->VarOffset[i] & 0xffffff] != 0)
3925      r->VarOffset[i]
3926        = (r->VarOffset[i] & 0xffffff) |
3927        (((r->VarOffset[i] >> 24) - shifts[r->VarOffset[i] & 0xffffff]) << 24);
3928  }
3929  omFree(shifts);
3930}
3931
3932// get r->divmask depending on bits per exponent
3933static unsigned long rGetDivMask(int bits)
3934{
3935  unsigned long divmask = 1;
3936  int i = bits;
3937
3938  while (i < BIT_SIZEOF_LONG)
3939  {
3940    divmask |= (((unsigned long) 1) << (unsigned long) i);
3941    i += bits;
3942  }
3943  return divmask;
3944}
3945
3946#ifdef RDEBUG
3947void rDebugPrint(ring r)
3948{
3949  if (r==NULL)
3950  {
3951    PrintS("NULL ?\n");
3952    return;
3953  }
3954  // corresponds to ro_typ from ring.h:
3955  const char *TYP[]={"ro_dp","ro_wp","ro_wp64","ro_wp_neg","ro_cp",
3956                     "ro_syzcomp", "ro_syz", "ro_isTemp", "ro_is", "ro_none"};
3957  int i,j;
3958
3959  Print("ExpL_Size:%d ",r->ExpL_Size);
3960  Print("CmpL_Size:%d ",r->CmpL_Size);
3961  Print("VarL_Size:%d\n",r->VarL_Size);
3962  Print("bitmask=0x%lx (expbound=%ld) \n",r->bitmask, r->bitmask);
3963  Print("BitsPerExp=%d ExpPerLong=%d MinExpPerLong=%d at L[%d]\n", r->BitsPerExp, r->ExpPerLong, r->MinExpPerLong, r->VarL_Offset[0]);
3964  PrintS("varoffset:\n");
3965  if (r->VarOffset==NULL) PrintS(" NULL\n");
3966  else
3967    for(j=0;j<=r->N;j++)
3968      Print("  v%d at e-pos %d, bit %d\n",
3969            j,r->VarOffset[j] & 0xffffff, r->VarOffset[j] >>24);
3970  Print("divmask=%lx\n", r->divmask);
3971  PrintS("ordsgn:\n");
3972  for(j=0;j<r->CmpL_Size;j++)
3973    Print("  ordsgn %ld at pos %d\n",r->ordsgn[j],j);
3974  Print("OrdSgn:%d\n",r->OrdSgn);
3975  PrintS("ordrec:\n");
3976  for(j=0;j<r->OrdSize;j++)
3977  {
3978    Print("  typ %s", TYP[r->typ[j].ord_typ]);
3979
3980    if (r->typ[j].ord_typ==ro_isTemp)
3981    {
3982      Print("  start (level) %d, suffixpos: %d, VO: ",r->typ[j].data.isTemp.start, r->typ[j].data.isTemp.suffixpos);
3983
3984#if MYTEST     
3985      for( int k = 0; k <= r->N; k++)
3986        if (r->typ[j].data.isTemp.pVarOffset[k] != -1)
3987          Print("[%2d]: %09x; ", k, r->typ[j].data.isTemp.pVarOffset[k]);
3988#endif
3989    }
3990    else
3991    if (r->typ[j].ord_typ==ro_is)
3992    {
3993      Print("  start %d, end: %d: ",r->typ[j].data.is.start, r->typ[j].data.is.end);
3994
3995//      for( int k = 0; k <= r->N; k++) if (r->typ[j].data.is.pVarOffset[k] != -1) Print("[%2d]: %04x; ", k, r->typ[j].data.is.pVarOffset[k]);
3996
3997      Print("  limit %d\n  F: ",r->typ[j].data.is.limit); idShow(r->typ[j].data.is.F, r, r, 1);
3998
3999      PrintS("weights: ");
4000     
4001      if( r->typ[j].data.is.componentWeights == NULL )
4002        PrintS("NULL == [0,...0]\n");
4003      else
4004      {
4005        (r->typ[j].data.is.componentWeights)->show(); PrintLn();
4006      }
4007     
4008    } else
4009    {
4010      Print("  place %d",r->typ[j].data.dp.place);
4011
4012      if (r->typ[j].ord_typ!=ro_syzcomp  && r->typ[j].ord_typ!=ro_syz)
4013      {
4014        Print("  start %d",r->typ[j].data.dp.start);
4015        Print("  end %d",r->typ[j].data.dp.end);
4016        if ((r->typ[j].ord_typ==ro_wp)
4017        || (r->typ[j].ord_typ==ro_wp_neg))
4018        {
4019          PrintS(" w:");
4020          for(int l=r->typ[j].data.wp.start;l<=r->typ[j].data.wp.end;l++)
4021            Print(" %d",r->typ[j].data.wp.weights[l-r->typ[j].data.wp.start]);
4022        }
4023        else if (r->typ[j].ord_typ==ro_wp64)
4024        {
4025          PrintS(" w64:");
4026          int l;
4027          for(l=r->typ[j].data.wp64.start;l<=r->typ[j].data.wp64.end;l++)
4028            Print(" %ld",(long)(((int64*)r->typ[j].data.wp64.weights64)+l-r->typ[j].data.wp64.start));
4029          }
4030        }
4031    }
4032    PrintLn();
4033  }
4034  Print("pOrdIndex:%d pCompIndex:%d\n", r->pOrdIndex, r->pCompIndex);
4035  Print("OrdSize:%d\n",r->OrdSize);
4036  PrintS("--------------------\n");
4037  for(j=0;j<r->ExpL_Size;j++)
4038  {
4039    Print("L[%d]: ",j);
4040    if (j< r->CmpL_Size)
4041      Print("ordsgn %ld ", r->ordsgn[j]);
4042    else
4043      PrintS("no comp ");
4044    i=1;
4045    for(;i<=r->N;i++)
4046    {
4047      if( (r->VarOffset[i] & 0xffffff) == j )
4048      {  Print("v%d at e[%d], bit %d; ", i,r->VarOffset[i] & 0xffffff,
4049                                         r->VarOffset[i] >>24 ); }
4050    }
4051    if( r->pCompIndex==j ) PrintS("v0; ");
4052    for(i=0;i<r->OrdSize;i++)
4053    {
4054      if (r->typ[i].data.dp.place == j)
4055      {
4056        Print("ordrec:%s (start:%d, end:%d) ",TYP[r->typ[i].ord_typ],
4057          r->typ[i].data.dp.start, r->typ[i].data.dp.end);
4058      }
4059    }
4060
4061    if (j==r->pOrdIndex)
4062      PrintS("pOrdIndex\n");
4063    else
4064      PrintLn();
4065  }
4066
4067  // p_Procs stuff
4068  p_Procs_s proc_names;
4069  const char* field;
4070  const char* length;
4071  const char* ord;
4072  p_Debug_GetProcNames(r, &proc_names); // changes p_Procs!!!
4073  p_Debug_GetSpecNames(r, field, length, ord);
4074
4075  Print("p_Spec  : %s, %s, %s\n", field, length, ord);
4076  PrintS("p_Procs :\n");
4077  for (i=0; i<(int) (sizeof(p_Procs_s)/sizeof(void*)); i++)
4078  {
4079    Print(" %s,\n", ((char**) &proc_names)[i]);
4080  }
4081}
4082
4083void p_DebugPrint(poly p, const ring r)
4084{
4085  int i,j;
4086  p_Write(p,r);
4087  j=2;
4088  while(p!=NULL)
4089  {
4090    Print("\nexp[0..%d]\n",r->ExpL_Size-1);
4091    for(i=0;i<r->ExpL_Size;i++)
4092      Print("%ld ",p->exp[i]);
4093    PrintLn();
4094    Print("v0:%ld ",p_GetComp(p, r));
4095    for(i=1;i<=r->N;i++) Print(" v%d:%d",i,p_GetExp(p,i, r));
4096    PrintLn();
4097    pIter(p);
4098    j--;
4099    if (j==0) { PrintS("...\n"); break; }
4100  }
4101}
4102
4103void pDebugPrint(poly p)
4104{
4105  p_DebugPrint(p, currRing);
4106}
4107#endif // RDEBUG
4108
4109/// debug-print monomial poly/vector p, assuming that it lives in the ring R
4110inline void m_DebugPrint(const poly p, const ring R)
4111{
4112  Print("\nexp[0..%d]\n", R->ExpL_Size - 1);
4113  for(int i = 0; i < R->ExpL_Size; i++)
4114    Print("%09lx ", p->exp[i]);
4115  PrintLn();
4116  Print("v0:%9ld ", p_GetComp(p, R));
4117  for(int i = 1; i <= R->N; i++) Print(" v%d:%5d",i, p_GetExp(p, i, R));
4118  PrintLn();
4119}
4120
4121
4122/// debug-print at most nTerms (2 by default) terms from poly/vector p,
4123/// assuming that lt(p) lives in lmRing and tail(p) lives in tailRing.
4124void p_DebugPrint(const poly p, const ring lmRing, const ring tailRing, const int nTerms)
4125{
4126  assume( nTerms >= 0 );
4127  if( p != NULL )
4128  {
4129    assume( p != NULL );
4130   
4131    p_Write(p, lmRing, tailRing);
4132
4133    if( (p != NULL) && (nTerms > 0) )
4134    {
4135      assume( p != NULL );
4136      assume( nTerms > 0 );
4137
4138      // debug pring leading term
4139      m_DebugPrint(p, lmRing);
4140
4141      poly q = pNext(p); // q = tail(p)
4142
4143      // debug pring tail (at most nTerms-1 terms from it)
4144      for(int j = nTerms - 1; (q !=NULL) && (j > 0); pIter(q), --j)
4145        m_DebugPrint(q, tailRing);
4146
4147      if (q != NULL)
4148        PrintS("...\n");   
4149    }
4150  }
4151  else
4152    PrintS("0\n");         
4153}
4154
4155
4156
4157
4158/*2
4159* asssume that rComplete was called with r
4160* assume that the first block ist ringorder_S
4161* change the block to reflect the sequence given by appending v
4162*/
4163
4164#ifdef PDEBUG
4165void rDBChangeSComps(int* currComponents,
4166                     long* currShiftedComponents,
4167                     int length,
4168                     ring r)
4169{
4170  r->typ[1].data.syzcomp.length = length;
4171  rNChangeSComps( currComponents, currShiftedComponents, r);
4172}
4173void rDBGetSComps(int** currComponents,
4174                 long** currShiftedComponents,
4175                 int *length,
4176                 ring r)
4177{
4178  *length = r->typ[1].data.syzcomp.length;
4179  rNGetSComps( currComponents, currShiftedComponents, r);
4180}
4181#endif
4182
4183void rNChangeSComps(int* currComponents, long* currShiftedComponents, ring r)
4184{
4185  assume(r->order[1]==ringorder_S);
4186
4187  r->typ[1].data.syzcomp.ShiftedComponents = currShiftedComponents;
4188  r->typ[1].data.syzcomp.Components = currComponents;
4189}
4190
4191void rNGetSComps(int** currComponents, long** currShiftedComponents, ring r)
4192{
4193  assume(r->order[1]==ringorder_S);
4194
4195  *currShiftedComponents = r->typ[1].data.syzcomp.ShiftedComponents;
4196  *currComponents =   r->typ[1].data.syzcomp.Components;
4197}
4198
4199/////////////////////////////////////////////////////////////////////////////
4200//
4201// The following routines all take as input a ring r, and return R
4202// where R has a certain property. R might be equal r in which case r
4203// had already this property
4204//
4205// Without argument, these functions work on currRing and change it,
4206// if necessary
4207
4208// for the time being, this is still here
4209static ring rAssure_SyzComp(const ring r, BOOLEAN complete = TRUE);
4210
4211ring rCurrRingAssure_SyzComp()
4212{
4213#if MYTEST
4214  PrintS("rCurrRingAssure_SyzComp(), currRing:  \n");
4215  rWrite(currRing);
4216#ifdef RDEBUG
4217  rDebugPrint(currRing);
4218#endif
4219  PrintS("\n");
4220#endif
4221
4222  ring r = rAssure_SyzComp(currRing, TRUE);
4223
4224  if( r != currRing )
4225  {
4226    rChangeCurrRing(r);
4227    assume(currRing == r);
4228
4229#if MYTEST
4230  PrintS("\nrCurrRingAssure_SyzComp(): new currRing: \n");
4231  rWrite(currRing);
4232#ifdef RDEBUG
4233  rDebugPrint(currRing);
4234#endif
4235  PrintS("\n");
4236#endif
4237  }
4238
4239  return r;
4240}
4241
4242static ring rAssure_SyzComp(const ring r, BOOLEAN complete)
4243{
4244  if ( (r->order[0] == ringorder_s) ) return r;
4245  if ( (r->order[0] == ringorder_IS) )
4246  {
4247#ifndef NDEBUG
4248    WarnS("rAssure_SyzComp in an IS ring!");
4249#endif
4250//    return r;
4251  }
4252  ring res=rCopy0(r, FALSE, FALSE);
4253  int i=rBlocks(r);
4254  int j;
4255
4256  res->order=(int *)omAlloc((i+1)*sizeof(int));
4257  res->block0=(int *)omAlloc0((i+1)*sizeof(int));
4258  res->block1=(int *)omAlloc0((i+1)*sizeof(int));
4259  int ** wvhdl =(int **)omAlloc0((i+1)*sizeof(int**));
4260  for(j=i;j>0;j--)
4261  {
4262    res->order[j]=r->order[j-1];
4263    res->block0[j]=r->block0[j-1];
4264    res->block1[j]=r->block1[j-1];
4265    if (r->wvhdl[j-1] != NULL)
4266    {
4267      wvhdl[j] = (int*) omMemDup(r->wvhdl[j-1]);
4268    }
4269  }
4270  res->order[0]=ringorder_s;
4271
4272  res->wvhdl = wvhdl;
4273
4274  if (complete)
4275  {
4276    rComplete(res, 1);
4277
4278#ifdef HAVE_PLURAL
4279    if (rIsPluralRing(r))
4280    {
4281      if ( nc_rComplete(r, res, false) ) // no qideal!
4282      {
4283#ifndef NDEBUG
4284        WarnS("error in nc_rComplete");      // cleanup?//      rDelete(res);//      return r;      // just go on..
4285#endif
4286      }
4287    }
4288    assume(rIsPluralRing(r) == rIsPluralRing(res));
4289#endif
4290
4291
4292#ifdef HAVE_PLURAL
4293    ring old_ring = r;
4294
4295#if MYTEST
4296    PrintS("rCurrRingAssure_SyzComp(): temp r': ");
4297    rWrite(r);
4298#ifdef RDEBUG
4299    rDebugPrint(r);
4300#endif
4301    PrintS("\n");
4302#endif
4303#endif
4304
4305
4306    if (r->qideal!=NULL)
4307    {
4308      res->qideal= idrCopyR_NoSort(r->qideal, r, res);
4309
4310      assume(idRankFreeModule(res->qideal, res) == 0);
4311
4312#ifdef HAVE_PLURAL
4313      if( rIsPluralRing(res) )
4314        if( nc_SetupQuotient(res, r, true) )
4315        {
4316//          WarnS("error in nc_SetupQuotient"); // cleanup?      rDelete(res);       return r;  // just go on...?
4317        }
4318
4319#endif
4320      assume(idRankFreeModule(res->qideal, res) == 0);
4321    }
4322
4323#ifdef HAVE_PLURAL
4324    assume((res->qideal==NULL) == (old_ring->qideal==NULL));
4325    assume(rIsPluralRing(res) == rIsPluralRing(old_ring));
4326    assume(rIsSCA(res) == rIsSCA(old_ring));
4327    assume(ncRingType(res) == ncRingType(old_ring));
4328#endif
4329
4330#if MYTEST
4331    PrintS("rCurrRingAssure_SyzComp(): res: ");
4332    rWrite(r);
4333#ifdef RDEBUG
4334    rDebugPrint(r);
4335#endif
4336    PrintS("\n");
4337#endif
4338
4339  }
4340
4341  return res;
4342}
4343
4344ring rAssure_TDeg(ring r, int start_var, int end_var, int &pos)
4345{
4346  int i;
4347  if (r->typ!=NULL)
4348  {
4349    for(i=r->OrdSize-1;i>=0;i--)
4350    {
4351      if ((r->typ[i].ord_typ==ro_dp)
4352      && (r->typ[i].data.dp.start==start_var)
4353      && (r->typ[i].data.dp.end==end_var))
4354      {
4355        pos=r->typ[i].data.dp.place;
4356        //printf("no change, pos=%d\n",pos);
4357        return r;
4358      }
4359    }
4360  }
4361
4362#ifdef HAVE_PLURAL
4363  nc_struct* save=r->GetNC();
4364  r->GetNC()=NULL;
4365#endif
4366  ring res=rCopy(r);
4367
4368  i=rBlocks(r);
4369  int j;
4370
4371  res->ExpL_Size=r->ExpL_Size+1; // one word more in each monom
4372  res->PolyBin=omGetSpecBin(POLYSIZE + (res->ExpL_Size)*sizeof(long));
4373  omFree((ADDRESS)res->ordsgn);
4374  res->ordsgn=(long *)omAlloc0(res->ExpL_Size*sizeof(long));
4375  for(j=0;j<r->CmpL_Size;j++)
4376  {
4377    res->ordsgn[j] = r->ordsgn[j];
4378  }
4379  res->OrdSize=r->OrdSize+1;   // one block more for pSetm
4380  if (r->typ!=NULL)
4381    omFree((ADDRESS)res->typ);
4382  res->typ=(sro_ord*)omAlloc0(res->OrdSize*sizeof(sro_ord));
4383  if (r->typ!=NULL)
4384    memcpy(res->typ,r->typ,r->OrdSize*sizeof(sro_ord));
4385  // the additional block for pSetm: total degree at the last word
4386  // but not included in the compare part
4387  res->typ[res->OrdSize-1].ord_typ=ro_dp;
4388  res->typ[res->OrdSize-1].data.dp.start=start_var;
4389  res->typ[res->OrdSize-1].data.dp.end=end_var;
4390  res->typ[res->OrdSize-1].data.dp.place=res->ExpL_Size-1;
4391  pos=res->ExpL_Size-1;
4392  //if ((start_var==1) && (end_var==res->N)) res->pOrdIndex=pos;
4393  extern void p_Setm_General(poly p, ring r);
4394  res->p_Setm=p_Setm_General;
4395  // ----------------------------
4396  omFree((ADDRESS)res->p_Procs);
4397  res->p_Procs = (p_Procs_s*)omAlloc(sizeof(p_Procs_s));
4398
4399  p_ProcsSet(res, res->p_Procs);
4400  if (res->qideal!=NULL) id_Delete(&res->qideal,res);
4401#ifdef HAVE_PLURAL
4402  r->GetNC()=save;
4403  if (rIsPluralRing(r))
4404  {
4405    if ( nc_rComplete(r, res, false) ) // no qideal!
4406    {
4407#ifndef NDEBUG
4408      WarnS("error in nc_rComplete");
4409#endif
4410      // just go on..
4411    }
4412  }
4413#endif
4414  if (r->qideal!=NULL)
4415  {
4416     res->qideal=idrCopyR_NoSort(r->qideal,r, res);
4417#ifdef HAVE_PLURAL
4418     if (rIsPluralRing(res))
4419     {
4420       nc_SetupQuotient(res, currRing);
4421     }
4422     assume((res->qideal==NULL) == (r->qideal==NULL));
4423#endif
4424  }
4425
4426#ifdef HAVE_PLURAL
4427  assume(rIsPluralRing(res) == rIsPluralRing(r));
4428  assume(rIsSCA(res) == rIsSCA(r));
4429  assume(ncRingType(res) == ncRingType(r));
4430#endif
4431
4432  return res;
4433}
4434
4435ring rAssure_HasComp(ring r)
4436{
4437  int last_block;
4438  int i=0;
4439  do
4440  {
4441     if (r->order[i] == ringorder_c ||
4442        r->order[i] == ringorder_C) return r;
4443     if (r->order[i] == 0)
4444        break;
4445     i++;
4446  } while (1);
4447  //WarnS("re-creating ring with comps");
4448  last_block=i-1;
4449
4450  ring new_r = rCopy0(r, FALSE, FALSE);
4451  i+=2;
4452  new_r->wvhdl=(int **)omAlloc0(i * sizeof(int_ptr));
4453  new_r->order   = (int *) omAlloc0(i * sizeof(int));
4454  new_r->block0   = (int *) omAlloc0(i * sizeof(int));
4455  new_r->block1   = (int *) omAlloc0(i * sizeof(int));
4456  memcpy4(new_r->order,r->order,(i-1) * sizeof(int));
4457  memcpy4(new_r->block0,r->block0,(i-1) * sizeof(int));
4458  memcpy4(new_r->block1,r->block1,(i-1) * sizeof(int));
4459  for (int j=0; j<=last_block; j++)
4460  {
4461    if (r->wvhdl[j]!=NULL)
4462    {
4463      new_r->wvhdl[j] = (int*) omMemDup(r->wvhdl[j]);
4464    }
4465  }
4466  last_block++;
4467  new_r->order[last_block]=ringorder_C;
4468  //new_r->block0[last_block]=0;
4469  //new_r->block1[last_block]=0;
4470  //new_r->wvhdl[last_block]=NULL;
4471
4472  rComplete(new_r, 1);
4473
4474#ifdef HAVE_PLURAL
4475  if (rIsPluralRing(r))
4476  {
4477    if ( nc_rComplete(r, new_r, false) ) // no qideal!
4478    {
4479#ifndef NDEBUG
4480      WarnS("error in nc_rComplete");      // cleanup?//      rDelete(res);//      return r;      // just go on..
4481#endif     
4482    }
4483  }
4484  assume(rIsPluralRing(r) == rIsPluralRing(new_r));
4485#endif
4486
4487  return new_r;
4488}
4489
4490static ring rAssure_CompLastBlock(ring r, BOOLEAN complete = TRUE)
4491{
4492  int last_block = rBlocks(r) - 2;
4493  if (r->order[last_block] != ringorder_c &&
4494      r->order[last_block] != ringorder_C)
4495  {
4496    int c_pos = 0;
4497    int i;
4498
4499    for (i=0; i< last_block; i++)
4500    {
4501      if (r->order[i] == ringorder_c || r->order[i] == ringorder_C)
4502      {
4503        c_pos = i;
4504        break;
4505      }
4506    }
4507    if (c_pos != -1)
4508    {
4509      ring new_r = rCopy0(r, FALSE, TRUE);
4510      for (i=c_pos+1; i<=last_block; i++)
4511      {
4512        new_r->order[i-1] = new_r->order[i];
4513        new_r->block0[i-1] = new_r->block0[i];
4514        new_r->block1[i-1] = new_r->block1[i];
4515        new_r->wvhdl[i-1] = new_r->wvhdl[i];
4516      }
4517      new_r->order[last_block] = r->order[c_pos];
4518      new_r->block0[last_block] = r->block0[c_pos];
4519      new_r->block1[last_block] = r->block1[c_pos];
4520      new_r->wvhdl[last_block] = r->wvhdl[c_pos];
4521      if (complete)
4522      {
4523        rComplete(new_r, 1);
4524
4525#ifdef HAVE_PLURAL
4526        if (rIsPluralRing(r))
4527        {
4528          if ( nc_rComplete(r, new_r, false) ) // no qideal!
4529          {
4530#ifndef NDEBUG
4531            WarnS("error in nc_rComplete");   // cleanup?//      rDelete(res);//      return r;      // just go on..
4532#endif
4533          }
4534        }
4535        assume(rIsPluralRing(r) == rIsPluralRing(new_r));
4536#endif
4537      }
4538      return new_r;
4539    }
4540  }
4541  return r;
4542}
4543
4544ring rCurrRingAssure_CompLastBlock()
4545{
4546  ring new_r = rAssure_CompLastBlock(currRing);
4547  if (currRing != new_r)
4548  {
4549    ring old_r = currRing;
4550    rChangeCurrRing(new_r);
4551    if (old_r->qideal != NULL)
4552    {
4553      new_r->qideal = idrCopyR(old_r->qideal, old_r);
4554      currQuotient = new_r->qideal;
4555#ifdef HAVE_PLURAL
4556      if( rIsPluralRing(new_r) )
4557        if( nc_SetupQuotient(new_r, old_r, true) )
4558        {
4559#ifndef NDEBUG
4560          WarnS("error in nc_SetupQuotient"); // cleanup?      rDelete(res);       return r;  // just go on...?
4561#endif
4562        }
4563#endif
4564    }
4565
4566#ifdef HAVE_PLURAL
4567    assume((new_r->qideal==NULL) == (old_r->qideal==NULL));
4568    assume(rIsPluralRing(new_r) == rIsPluralRing(old_r));
4569    assume(rIsSCA(new_r) == rIsSCA(old_r));
4570    assume(ncRingType(new_r) == ncRingType(old_r));
4571#endif
4572
4573    rTest(new_r);
4574    rTest(old_r);
4575  }
4576  return new_r;
4577}
4578
4579// Moves _c or _C ordering to the last place AND adds _s on the 1st place
4580ring rCurrRingAssure_SyzComp_CompLastBlock()
4581{
4582  ring new_r_1 = rAssure_CompLastBlock(currRing, FALSE); // due to this FALSE - no completion!
4583  ring new_r = rAssure_SyzComp(new_r_1, FALSE); // new_r_1 is used only here!!!
4584
4585  if (new_r != currRing)
4586  {
4587    ring old_r = currRing;
4588    if (new_r_1 != new_r && new_r_1 != old_r) rDelete(new_r_1);
4589    rComplete(new_r, 1);
4590#ifdef HAVE_PLURAL
4591    if (rIsPluralRing(old_r))
4592    {
4593      if ( nc_rComplete(old_r, new_r, false) ) // no qideal!
4594      {
4595#ifndef NDEBUG
4596        WarnS("error in nc_rComplete"); // cleanup?      rDelete(res);       return r;  // just go on...?
4597#endif
4598        }
4599    }
4600    assume(rIsPluralRing(new_r) == rIsPluralRing(old_r));
4601#endif
4602    rChangeCurrRing(new_r);
4603    if (old_r->qideal != NULL)
4604    {
4605      new_r->qideal = idrCopyR(old_r->qideal, old_r);
4606      currQuotient = new_r->qideal;
4607
4608#ifdef HAVE_PLURAL
4609      if( rIsPluralRing(old_r) )
4610        if( nc_SetupQuotient(new_r, old_r, true) )
4611        {
4612#ifndef NDEBUG
4613          WarnS("error in nc_SetupQuotient"); // cleanup?      rDelete(res);       return r;  // just go on...?
4614#endif
4615        }
4616#endif
4617    }
4618
4619#ifdef HAVE_PLURAL
4620    assume((new_r->qideal==NULL) == (old_r->qideal==NULL));
4621    assume(rIsPluralRing(new_r) == rIsPluralRing(old_r));
4622    assume(rIsSCA(new_r) == rIsSCA(old_r));
4623    assume(ncRingType(new_r) == ncRingType(old_r));
4624#endif
4625
4626    rTest(new_r);
4627    rTest(old_r);
4628  }
4629  return new_r;
4630}
4631
4632// use this for global orderings consisting of two blocks
4633static ring rCurrRingAssure_Global(rRingOrder_t b1, rRingOrder_t b2)
4634{
4635  int r_blocks = rBlocks(currRing);
4636  int i;
4637
4638  assume(b1 == ringorder_c || b1 == ringorder_C ||
4639         b2 == ringorder_c || b2 == ringorder_C ||
4640         b2 == ringorder_S);
4641  if ((r_blocks == 3) &&
4642      (currRing->order[0] == b1) &&
4643      (currRing->order[1] == b2) &&
4644      (currRing->order[2] == 0))
4645    return currRing;
4646  ring res = rCopy0(currRing, TRUE, FALSE);
4647  res->order = (int*)omAlloc0(3*sizeof(int));
4648  res->block0 = (int*)omAlloc0(3*sizeof(int));
4649  res->block1 = (int*)omAlloc0(3*sizeof(int));
4650  res->wvhdl = (int**)omAlloc0(3*sizeof(int*));
4651  res->order[0] = b1;
4652  res->order[1] = b2;
4653  if (b1 == ringorder_c || b1 == ringorder_C)
4654  {
4655    res->block0[1] = 1;
4656    res->block1[1] = currRing->N;
4657  }
4658  else
4659  {
4660    res->block0[0] = 1;
4661    res->block1[0] = currRing->N;
4662  }
4663  // HANNES: This sould be set in rComplete
4664  res->OrdSgn = 1;
4665  rComplete(res, 1);
4666  rChangeCurrRing(res);
4667  return res;
4668}
4669
4670
4671ring rAssure_InducedSchreyerOrdering(const ring r, BOOLEAN complete = TRUE, int sgn = 1)
4672{ // TODO: ???? Add leading Syz-comp ordering here...????
4673
4674#if MYTEST
4675    Print("rAssure_InducedSchreyerOrdering(r, complete = %d, sgn = %d): r: \n", complete, sgn);
4676    rWrite(r);
4677#ifdef RDEBUG
4678    rDebugPrint(r);
4679#endif
4680    PrintS("\n");
4681#endif
4682
4683
4684  ring res=rCopy0(r, FALSE, FALSE); // No qideal & ordering copy.
4685
4686  int n = rBlocks(r); // Including trailing zero!
4687
4688  // Create 2 more blocks for prefix/suffix:
4689  res->order=(int *)omAlloc0((n+2)*sizeof(int)); // 0  ..  n+1
4690  res->block0=(int *)omAlloc0((n+2)*sizeof(int));
4691  res->block1=(int *)omAlloc0((n+2)*sizeof(int));
4692  int ** wvhdl =(int **)omAlloc0((n+2)*sizeof(int**));
4693
4694  // Encapsulate all existing blocks between induced Schreyer ordering markers: prefix and suffix!
4695  // Note that prefix and suffix have the same ringorder marker and only differ in block[] parameters!
4696
4697  // new 1st block
4698  int j = 0;
4699  res->order[j] = ringorder_IS; // Prefix
4700  // res->block0[j] = res->block1[j] = 0;
4701  // wvhdl[j] = NULL;
4702  j++;
4703
4704  for(int i = 0; (i <= n) && (r->order[i] != 0); i++, j++) // i = [0 .. n-1] <- non-zero old blocks
4705  {
4706    res->order [j] = r->order [i];
4707    res->block0[j] = r->block0[i];
4708    res->block1[j] = r->block1[i];
4709
4710    if (r->wvhdl[i] != NULL)
4711    {
4712      wvhdl[j] = (int*) omMemDup(r->wvhdl[i]);
4713    } // else wvhdl[j] = NULL;
4714  }
4715
4716  // new last block
4717  res->order [j] = ringorder_IS; // Suffix
4718  res->block0[j] = res->block1[j] = sgn; // Sign of v[o]: 1 for C, -1 for c
4719  // wvhdl[j] = NULL;
4720  j++;
4721
4722  // res->order [j] = 0; // The End!
4723  res->wvhdl = wvhdl;
4724
4725  // j == the last zero block now!
4726  assume(j == (n+1));
4727  assume(res->order[0]==ringorder_IS);
4728  assume(res->order[j-1]==ringorder_IS);
4729  assume(res->order[j]==0);
4730
4731
4732  if (complete)
4733  {
4734    rComplete(res, 1);
4735
4736#if MYTEST
4737    PrintS("rAssure_InducedSchreyerOrdering(): temp res: ");
4738    rWrite(res);
4739#ifdef RDEBUG
4740    rDebugPrint(res);
4741#endif
4742    PrintS("\n");
4743#endif
4744
4745
4746
4747#ifdef HAVE_PLURAL
4748    if (rIsPluralRing(r))
4749    {
4750      if ( nc_rComplete(r, res, false) ) // no qideal!
4751      {
4752#ifndef NDEBUG
4753        WarnS("error in nc_rComplete");      // cleanup?//      rDelete(res);//      return r;      // just go on..
4754#endif
4755      }
4756    }
4757    assume(rIsPluralRing(r) == rIsPluralRing(res));
4758#endif
4759
4760
4761#ifdef HAVE_PLURAL
4762    ring old_ring = r;
4763
4764#if MYTEST
4765    PrintS("rAssure_InducedSchreyerOrdering(): temp nc res: ");
4766    rWrite(res);
4767#ifdef RDEBUG
4768    rDebugPrint(res);
4769#endif
4770    PrintS("\n");
4771#endif
4772#endif
4773
4774
4775    if (r->qideal!=NULL)
4776    {
4777      res->qideal= idrCopyR_NoSort(r->qideal, r, res);
4778
4779      assume(idRankFreeModule(res->qideal, res) == 0);
4780
4781#ifdef HAVE_PLURAL
4782      if( rIsPluralRing(res) )
4783        if( nc_SetupQuotient(res, r, true) )
4784        {
4785//          WarnS("error in nc_SetupQuotient"); // cleanup?      rDelete(res);       return r;  // just go on...?
4786        }
4787
4788#endif
4789      assume(idRankFreeModule(res->qideal, res) == 0);
4790    }
4791
4792#ifdef HAVE_PLURAL
4793    assume((res->qideal==NULL) == (old_ring->qideal==NULL));
4794    assume(rIsPluralRing(res) == rIsPluralRing(old_ring));
4795    assume(rIsSCA(res) == rIsSCA(old_ring));
4796    assume(ncRingType(res) == ncRingType(old_ring));
4797#endif
4798  }
4799
4800  return res;
4801}
4802
4803
4804
4805
4806
4807ring rCurrRingAssure_dp_S()
4808{
4809  return rCurrRingAssure_Global(ringorder_dp, ringorder_S);
4810}
4811
4812ring rCurrRingAssure_dp_C()
4813{
4814  return rCurrRingAssure_Global(ringorder_dp, ringorder_C);
4815}
4816
4817ring rCurrRingAssure_C_dp()
4818{
4819  return rCurrRingAssure_Global(ringorder_C, ringorder_dp);
4820}
4821
4822/// Changes r by setting induced ordering parameters: limit and reference leading terms
4823/// F belong to r, we will DO a copy! (same to componentWeights)
4824/// We will use it AS IS!
4825/// returns true is everything was allright!
4826bool rSetISReference(const ideal F, const int i = 0, const int p = 0, const intvec * componentWeights = NULL, const ring r = currRing)
4827{
4828  // Put the reference set F into the ring -ordering -recor
4829#if MYTEST
4830  Print("rSetISReference(F, i: %d, p: %d, w)\nF:", i, p);
4831  idShow(F, r, r, 1); // currRing!
4832  PrintLn();
4833  PrintS("w: ");
4834  if(componentWeights == NULL)
4835    PrintS("NULL\n");
4836  else
4837    componentWeights->show();
4838#endif
4839
4840  // TEST THAT THERE ARE DEGs!!!
4841  // assume( componentWeights == NULL  ); // ???
4842  if( componentWeights != NULL )
4843  {
4844//    assure that the ring r has degrees!!!
4845//    Add weights to degrees of F[i]
4846  }
4847
4848  if (r->typ==NULL)
4849  {
4850    dReportError("Error: WRONG USE of rSetISReference: wrong ring! (typ == NULL)");
4851    return false;
4852  }
4853
4854  int j = p; // Which IS record to use...
4855  for( int pos = 0; pos < r->OrdSize; pos++ )
4856    if( r->typ[pos].ord_typ == ro_is)
4857      if( j-- == 0 )
4858      {
4859#if MYTEST
4860        Print("Changing record on pos: %d\nOld limit: %d --->> New Limit: %d\n", pos, r->typ[pos].data.is.limit, i);
4861#endif
4862
4863        const ideal FF = idrHeadR(F, r, r);
4864
4865
4866        if( r->typ[pos].data.is.F != NULL)
4867        {
4868#if MYTEST
4869          PrintS("Deleting old reference set F... \n");        // idShow(r->typ[pos].data.is.F, r);         PrintLn();
4870#endif
4871          id_Delete(&r->typ[pos].data.is.F, r);
4872          r->typ[pos].data.is.F = NULL;
4873        }
4874
4875        assume(r->typ[pos].data.is.F == NULL);
4876
4877       
4878        r->typ[pos].data.is.F = FF; // F is owened by ring now! TODO: delete at the end!
4879
4880        if(r->typ[pos].data.is.componentWeights != NULL)
4881        {
4882#if MYTEST
4883          PrintS("Deleting old componentWeights: "); r->typ[pos].data.is.componentWeights->show(); PrintLn();
4884#endif
4885          delete r->typ[pos].data.is.componentWeights;
4886          r->typ[pos].data.is.componentWeights = NULL;
4887        }
4888
4889
4890        assume(r->typ[pos].data.is.componentWeights == NULL);
4891
4892        if( componentWeights != NULL )
4893          componentWeights = ivCopy(componentWeights); // componentWeights is owened by ring now! TODO: delete at the end!
4894
4895        r->typ[pos].data.is.componentWeights = componentWeights;
4896
4897        r->typ[pos].data.is.limit = i; // First induced component
4898
4899#if MYTEST
4900        PrintS("New reference set FF : \n");        idShow(FF, r, r, 1);         PrintLn();
4901#endif
4902
4903        return true;
4904      }
4905
4906  dReportError("Error: WRONG USE of rSetISReference: specified ordering block was not found!!!" );
4907  return false;
4908}
4909
4910
4911void rSetSyzComp(int k)
4912{
4913  if (TEST_OPT_PROT) Print("{%d}", k);
4914  if ((currRing->typ!=NULL) && (currRing->typ[0].ord_typ==ro_syz))
4915  {
4916    assume(k > currRing->typ[0].data.syz.limit);
4917    int i;
4918    if (currRing->typ[0].data.syz.limit == 0)
4919    {
4920      currRing->typ[0].data.syz.syz_index = (int*) omAlloc0((k+1)*sizeof(int));
4921      currRing->typ[0].data.syz.syz_index[0] = 0;
4922      currRing->typ[0].data.syz.curr_index = 1;
4923    }
4924    else
4925    {
4926      currRing->typ[0].data.syz.syz_index = (int*)
4927        omReallocSize(currRing->typ[0].data.syz.syz_index,
4928                (currRing->typ[0].data.syz.limit+1)*sizeof(int),
4929                (k+1)*sizeof(int));
4930    }
4931    for (i=currRing->typ[0].data.syz.limit + 1; i<= k; i++)
4932    {
4933      currRing->typ[0].data.syz.syz_index[i] =
4934        currRing->typ[0].data.syz.curr_index;
4935    }
4936    currRing->typ[0].data.syz.limit = k;
4937    currRing->typ[0].data.syz.curr_index++;
4938     
4939  } else if(
4940            (currRing->typ!=NULL) && 
4941            (currRing->typ[0].ord_typ==ro_isTemp)
4942           )
4943  {
4944//      (currRing->typ[currRing->typ[0].data.isTemp.suffixpos].data.is.limit == k)
4945#ifndef NDEBUG
4946    Warn("rSetSyzComp(%d) in an IS ring! Be careful!", k);
4947#endif
4948  } else
4949  if ((currRing->order[0]!=ringorder_c) && (k!=0)) // ???
4950  {
4951    dReportError("syzcomp in incompatible ring");
4952  }
4953#ifdef PDEBUG
4954  extern int pDBsyzComp;
4955  pDBsyzComp=k;
4956#endif
4957}
4958
4959// return the max-comonent wchich has syzIndex i
4960int rGetMaxSyzComp(int i)
4961{
4962  if ((currRing->typ!=NULL) && (currRing->typ[0].ord_typ==ro_syz) &&
4963      currRing->typ[0].data.syz.limit > 0 && i > 0)
4964  {
4965    assume(i <= currRing->typ[0].data.syz.limit);
4966    int j;
4967    for (j=0; j<currRing->typ[0].data.syz.limit; j++)
4968    {
4969      if (currRing->typ[0].data.syz.syz_index[j] == i  &&
4970          currRing->typ[0].data.syz.syz_index[j+1] != i)
4971      {
4972        assume(currRing->typ[0].data.syz.syz_index[j+1] == i+1);
4973        return j;
4974      }
4975    }
4976    return currRing->typ[0].data.syz.limit;
4977  }
4978  else
4979  {
4980    return 0;
4981  }
4982}
4983
4984BOOLEAN rRing_is_Homog(ring r)
4985{
4986  if (r == NULL) return FALSE;
4987  int i, j, nb = rBlocks(r);
4988  for (i=0; i<nb; i++)
4989  {
4990    if (r->wvhdl[i] != NULL)
4991    {
4992      int length = r->block1[i] - r->block0[i];
4993      int* wvhdl = r->wvhdl[i];
4994      if (r->order[i] == ringorder_M) length *= length;
4995      assume(omSizeOfAddr(wvhdl) >= length*sizeof(int));
4996
4997      for (j=0; j< length; j++)
4998      {
4999        if (wvhdl[j] != 0 && wvhdl[j] != 1) return FALSE;
5000      }
5001    }
5002  }
5003  return TRUE;
5004}
5005
5006BOOLEAN rRing_has_CompLastBlock(ring r)
5007{
5008  assume(r != NULL);
5009  int lb = rBlocks(r) - 2;
5010  return (r->order[lb] == ringorder_c || r->order[lb] == ringorder_C);
5011}
5012
5013n_coeffType rFieldType(ring r)
5014{
5015  if (rField_is_Zp(r))     return n_Zp;
5016  if (rField_is_Q(r))      return n_Q;
5017  if (rField_is_R(r))      return n_R;
5018  if (rField_is_GF(r))     return n_GF;
5019  if (rField_is_long_R(r)) return n_long_R;
5020  if (rField_is_Zp_a(r))   return n_Zp_a;
5021  if (rField_is_Q_a(r))    return n_Q_a;
5022  if (rField_is_long_C(r)) return n_long_C;
5023  return n_unknown;
5024}
5025
5026int64 * rGetWeightVec(ring r)
5027{
5028  assume(r!=NULL);
5029  assume(r->OrdSize>0);
5030  int i=0;
5031  while((r->typ[i].ord_typ!=ro_wp64) && (r->typ[i].ord_typ>0)) i++;
5032  assume(r->typ[i].ord_typ==ro_wp64);
5033  return (int64*)(r->typ[i].data.wp64.weights64);
5034}
5035
5036void rSetWeightVec(ring r, int64 *wv)
5037{
5038  assume(r!=NULL);
5039  assume(r->OrdSize>0);
5040  assume(r->typ[0].ord_typ==ro_wp64);
5041  memcpy(r->typ[0].data.wp64.weights64,wv,r->N*sizeof(int64));
5042}
5043
5044#include <ctype.h>
5045
5046static int rRealloc1(ring r, ring src, int size, int pos)
5047{
5048  r->order=(int*)omReallocSize(r->order, size*sizeof(int), (size+1)*sizeof(int));
5049  r->block0=(int*)omReallocSize(r->block0, size*sizeof(int), (size+1)*sizeof(int));
5050  r->block1=(int*)omReallocSize(r->block1, size*sizeof(int), (size+1)*sizeof(int));
5051  r->wvhdl=(int_ptr*)omReallocSize(r->wvhdl,size*sizeof(int_ptr), (size+1)*sizeof(int_ptr));
5052  for(int k=size; k>pos; k--) r->wvhdl[k]=r->wvhdl[k-1];
5053  r->order[size]=0;
5054  size++;
5055  return size;
5056}
5057static int rReallocM1(ring r, ring src, int size, int pos)
5058{
5059  r->order=(int*)omReallocSize(r->order, size*sizeof(int), (size-1)*sizeof(int));
5060  r->block0=(int*)omReallocSize(r->block0, size*sizeof(int), (size-1)*sizeof(int));
5061  r->block1=(int*)omReallocSize(r->block1, size*sizeof(int), (size-1)*sizeof(int));
5062  r->wvhdl=(int_ptr*)omReallocSize(r->wvhdl,size*sizeof(int_ptr), (size-1)*sizeof(int_ptr));
5063  for(int k=pos+1; k<size; k++) r->wvhdl[k]=r->wvhdl[k+1];
5064  size--;
5065  return size;
5066}
5067static void rOppWeight(int *w, int l)
5068{
5069  int i2=(l+1)/2;
5070  for(int j=0; j<=i2; j++)
5071  {
5072    int t=w[j];
5073    w[j]=w[l-j];
5074    w[l-j]=t;
5075  }
5076}
5077
5078#define rOppVar(R,I) (rVar(R)+1-I)
5079
5080ring rOpposite(ring src)
5081  /* creates an opposite algebra of R */
5082  /* that is R^opp, where f (*^opp) g = g*f  */
5083  /* treats the case of qring */
5084{
5085  if (src == NULL) return(NULL);
5086
5087#ifdef RDEBUG
5088  rTest(src);
5089#endif
5090
5091  ring save = currRing;
5092  rChangeCurrRing(src);
5093
5094#ifdef RDEBUG
5095  rTest(src);
5096//  rWrite(src);
5097//  rDebugPrint(src);
5098#endif
5099
5100
5101//  ring r = rCopy0(src,TRUE); /* TRUE for copy the qideal: Why??? */
5102  ring r = rCopy0(src,FALSE); /* qideal will be deleted later on!!! */
5103
5104  /*  rChangeCurrRing(r); */
5105  // change vars v1..vN -> vN..v1
5106  int i;
5107  int i2 = (rVar(r)-1)/2;
5108  for(i=i2; i>=0; i--)
5109  {
5110    // index: 0..N-1
5111    //Print("ex var names: %d <-> %d\n",i,rOppVar(r,i));
5112    // exchange names
5113    char *p;
5114    p = r->names[rVar(r)-1-i];
5115    r->names[rVar(r)-1-i] = r->names[i];
5116    r->names[i] = p;
5117  }
5118//  i2=(rVar(r)+1)/2;
5119//  for(int i=i2; i>0; i--)
5120//  {
5121//    // index: 1..N
5122//    //Print("ex var places: %d <-> %d\n",i,rVar(r)+1-i);
5123//    // exchange VarOffset
5124//    int t;
5125//    t=r->VarOffset[i];
5126//    r->VarOffset[i]=r->VarOffset[rOppVar(r,i)];
5127//    r->VarOffset[rOppVar(r,i)]=t;
5128//  }
5129  // change names:
5130  for (i=rVar(r)-1; i>=0; i--)
5131  {
5132    char *p=r->names[i];
5133    if(isupper(*p)) *p = tolower(*p);
5134    else            *p = toupper(*p);
5135  }
5136  // change ordering: listing
5137  // change ordering: compare
5138//  for(i=0; i<r->OrdSize; i++)
5139//  {
5140//    int t,tt;
5141//    switch(r->typ[i].ord_typ)
5142//    {
5143//      case ro_dp:
5144//      //
5145//        t=r->typ[i].data.dp.start;
5146//        r->typ[i].data.dp.start=rOppVar(r,r->typ[i].data.dp.end);
5147//        r->typ[i].data.dp.end=rOppVar(r,t);
5148//        break;
5149//      case ro_wp:
5150//      case ro_wp_neg:
5151//      {
5152//        t=r->typ[i].data.wp.start;
5153//        r->typ[i].data.wp.start=rOppVar(r,r->typ[i].data.wp.end);
5154//        r->typ[i].data.wp.end=rOppVar(r,t);
5155//        // invert r->typ[i].data.wp.weights
5156//        rOppWeight(r->typ[i].data.wp.weights,
5157//                   r->typ[i].data.wp.end-r->typ[i].data.wp.start);
5158//        break;
5159//      }
5160//      //case ro_wp64:
5161//      case ro_syzcomp:
5162//      case ro_syz:
5163//         WerrorS("not implemented in rOpposite");
5164//         // should not happen
5165//         break;
5166//
5167//      case ro_cp:
5168//        t=r->typ[i].data.cp.start;
5169//        r->typ[i].data.cp.start=rOppVar(r,r->typ[i].data.cp.end);
5170//        r->typ[i].data.cp.end=rOppVar(r,t);
5171//        break;
5172//      case ro_none:
5173//      default:
5174//       Werror("unknown type in rOpposite(%d)",r->typ[i].ord_typ);
5175//       break;
5176//    }
5177//  }
5178  // Change order/block structures (needed for rPrint, rAdd etc.)
5179  int j=0;
5180  int l=rBlocks(src);
5181  for(i=0; src->order[i]!=0; i++)
5182  {
5183    switch (src->order[i])
5184    {
5185      case ringorder_c: /* c-> c */
5186      case ringorder_C: /* C-> C */
5187      case ringorder_no /*=0*/: /* end-of-block */
5188        r->order[j]=src->order[i];
5189        j++; break;
5190      case ringorder_lp: /* lp -> rp */
5191        r->order[j]=ringorder_rp;
5192        r->block0[j]=rOppVar(r, src->block1[i]);
5193        r->block1[j]=rOppVar(r, src->block0[i]);
5194        break;
5195      case ringorder_rp: /* rp -> lp */
5196        r->order[j]=ringorder_lp;
5197        r->block0[j]=rOppVar(r, src->block1[i]);
5198        r->block1[j]=rOppVar(r, src->block0[i]);
5199        break;
5200      case ringorder_dp: /* dp -> a(1..1),ls */
5201      {
5202        l=rRealloc1(r,src,l,j);
5203        r->order[j]=ringorder_a;
5204        r->block0[j]=rOppVar(r, src->block1[i]);
5205        r->block1[j]=rOppVar(r, src->block0[i]);
5206        r->wvhdl[j]=(int*)omAlloc((r->block1[j]-r->block0[j]+1)*sizeof(int));
5207        for(int k=r->block0[j]; k<=r->block1[j]; k++)
5208          r->wvhdl[j][k-r->block0[j]]=1;
5209        j++;
5210        r->order[j]=ringorder_ls;
5211        r->block0[j]=rOppVar(r, src->block1[i]);
5212        r->block1[j]=rOppVar(r, src->block0[i]);
5213        j++;
5214        break;
5215      }
5216      case ringorder_Dp: /* Dp -> a(1..1),rp */
5217      {
5218        l=rRealloc1(r,src,l,j);
5219        r->order[j]=ringorder_a;
5220        r->block0[j]=rOppVar(r, src->block1[i]);
5221        r->block1[j]=rOppVar(r, src->block0[i]);
5222        r->wvhdl[j]=(int*)omAlloc((r->block1[j]-r->block0[j]+1)*sizeof(int));
5223        for(int k=r->block0[j]; k<=r->block1[j]; k++)
5224          r->wvhdl[j][k-r->block0[j]]=1;
5225        j++;
5226        r->order[j]=ringorder_rp;
5227        r->block0[j]=rOppVar(r, src->block1[i]);
5228        r->block1[j]=rOppVar(r, src->block0[i]);
5229        j++;
5230        break;
5231      }
5232      case ringorder_wp: /* wp -> a(...),ls */
5233      {
5234        l=rRealloc1(r,src,l,j);
5235        r->order[j]=ringorder_a;
5236        r->block0[j]=rOppVar(r, src->block1[i]);
5237        r->block1[j]=rOppVar(r, src->block0[i]);
5238        r->wvhdl[j]=r->wvhdl[j+1]; r->wvhdl[j+1]=r->wvhdl[j+1]=NULL;
5239        rOppWeight(r->wvhdl[j], r->block1[j]-r->block0[j]);
5240        j++;
5241        r->order[j]=ringorder_ls;
5242        r->block0[j]=rOppVar(r, src->block1[i]);
5243        r->block1[j]=rOppVar(r, src->block0[i]);
5244        j++;
5245        break;
5246      }
5247      case ringorder_Wp: /* Wp -> a(...),rp */
5248      {
5249        l=rRealloc1(r,src,l,j);
5250        r->order[j]=ringorder_a;
5251        r->block0[j]=rOppVar(r, src->block1[i]);
5252        r->block1[j]=rOppVar(r, src->block0[i]);
5253        r->wvhdl[j]=r->wvhdl[j+1]; r->wvhdl[j+1]=r->wvhdl[j+1]=NULL;
5254        rOppWeight(r->wvhdl[j], r->block1[j]-r->block0[j]);
5255        j++;
5256        r->order[j]=ringorder_rp;
5257        r->block0[j]=rOppVar(r, src->block1[i]);
5258        r->block1[j]=rOppVar(r, src->block0[i]);
5259        j++;
5260        break;
5261      }
5262      case ringorder_M: /* M -> M */
5263      {
5264        r->order[j]=ringorder_M;
5265        r->block0[j]=rOppVar(r, src->block1[i]);
5266        r->block1[j]=rOppVar(r, src->block0[i]);
5267        int n=r->block1[j]-r->block0[j];
5268        /* M is a (n+1)x(n+1) matrix */
5269        for (int nn=0; nn<=n; nn++)
5270        {
5271          rOppWeight(&(r->wvhdl[j][nn*(n+1)]), n /*r->block1[j]-r->block0[j]*/);
5272        }
5273        j++;
5274        break;
5275      }
5276      case ringorder_a: /*  a(...),ls -> wp/dp */
5277      {
5278        r->block0[j]=rOppVar(r, src->block1[i]);
5279        r->block1[j]=rOppVar(r, src->block0[i]);
5280        rOppWeight(r->wvhdl[j], r->block1[j]-r->block0[j]);
5281        if (src->order[i+1]==ringorder_ls)
5282        {
5283          r->order[j]=ringorder_wp;
5284          i++;
5285          //l=rReallocM1(r,src,l,j);
5286        }
5287        else
5288        {
5289          r->order[j]=ringorder_a;
5290        }
5291        j++;
5292        break;
5293      }
5294      // not yet done:
5295      case ringorder_ls:
5296      case ringorder_rs:
5297      case ringorder_ds:
5298      case ringorder_Ds:
5299      case ringorder_ws:
5300      case ringorder_Ws:
5301      // should not occur:
5302      case ringorder_S:
5303      case ringorder_IS:
5304      case ringorder_s:
5305      case ringorder_aa:
5306      case ringorder_L:
5307      case ringorder_unspec:
5308        Werror("order %s not (yet) supported", rSimpleOrdStr(src->order[i]));
5309        break;
5310    }
5311  }
5312  rComplete(r);
5313
5314
5315#ifdef RDEBUG
5316  rTest(r);
5317#endif
5318
5319  rChangeCurrRing(r);
5320
5321#ifdef RDEBUG
5322  rTest(r);
5323//  rWrite(r);
5324//  rDebugPrint(r);
5325#endif
5326
5327
5328#ifdef HAVE_PLURAL
5329  // now, we initialize a non-comm structure on r
5330  if (rIsPluralRing(src))
5331  {
5332    assume( currRing == r);
5333
5334    int *perm       = (int *)omAlloc0((rVar(r)+1)*sizeof(int));
5335    int *par_perm   = NULL;
5336    nMapFunc nMap   = nSetMap(src);
5337    int ni,nj;
5338    for(i=1; i<=r->N; i++)
5339    {
5340      perm[i] = rOppVar(r,i);
5341    }
5342
5343    matrix C = mpNew(rVar(r),rVar(r));
5344    matrix D = mpNew(rVar(r),rVar(r));
5345
5346    for (i=1; i< rVar(r); i++)
5347    {
5348      for (j=i+1; j<=rVar(r); j++)
5349      {
5350        ni = r->N +1 - i;
5351        nj = r->N +1 - j; /* i<j ==>   nj < ni */
5352
5353        assume(MATELEM(src->GetNC()->C,i,j) != NULL);
5354        MATELEM(C,nj,ni) = pPermPoly(MATELEM(src->GetNC()->C,i,j),perm,src,nMap,par_perm,src->P);
5355
5356        if(MATELEM(src->GetNC()->D,i,j) != NULL)
5357          MATELEM(D,nj,ni) = pPermPoly(MATELEM(src->GetNC()->D,i,j),perm,src,nMap,par_perm,src->P);
5358      }
5359    }
5360
5361    idTest((ideal)C);
5362    idTest((ideal)D);
5363
5364    if (nc_CallPlural(C, D, NULL, NULL, r, false, false, true, r)) // no qring setup!
5365      WarnS("Error initializing non-commutative multiplication!");
5366
5367#ifdef RDEBUG
5368    rTest(r);
5369//    rWrite(r);
5370//    rDebugPrint(r);
5371#endif
5372
5373    assume( r->GetNC()->IsSkewConstant == src->GetNC()->IsSkewConstant);
5374
5375    omFreeSize((ADDRESS)perm,(rVar(r)+1)*sizeof(int));
5376  }
5377#endif /* HAVE_PLURAL */
5378
5379  /* now oppose the qideal for qrings */
5380  if (src->qideal != NULL)
5381  {
5382    id_Delete(&(r->qideal), r);
5383
5384#ifdef HAVE_PLURAL
5385    r->qideal = idOppose(src, src->qideal); // into the currRing: r
5386#else
5387    r->qideal = id_Copy(src->qideal, currRing); // ?
5388#endif
5389
5390#ifdef HAVE_PLURAL
5391    if( rIsPluralRing(r) )
5392    {
5393      nc_SetupQuotient(r);
5394#ifdef RDEBUG
5395      rTest(r);
5396//      rWrite(r);
5397//      rDebugPrint(r);
5398#endif
5399    }
5400#endif
5401  }
5402#ifdef HAVE_PLURAL
5403  if( rIsPluralRing(r) )
5404    assume( ncRingType(r) == ncRingType(src) );
5405#endif
5406  rTest(r);
5407
5408  rChangeCurrRing(save);
5409  return r;
5410}
5411
5412ring rEnvelope(ring R)
5413  /* creates an enveloping algebra of R */
5414  /* that is R^e = R \tensor_K R^opp */
5415{
5416  ring Ropp = rOpposite(R);
5417  ring Renv = NULL;
5418  int stat = rSum(R, Ropp, Renv); /* takes care of qideals */
5419  if ( stat <=0 )
5420    WarnS("Error in rEnvelope at rSum");
5421  rTest(Renv);
5422  return Renv;
5423}
5424
5425#ifdef HAVE_PLURAL
5426BOOLEAN nc_rComplete(const ring src, ring dest, bool bSetupQuotient)
5427/* returns TRUE is there were errors */
5428/* dest is actualy equals src with the different ordering */
5429/* we map src->nc correctly to dest->src */
5430/* to be executed after rComplete, before rChangeCurrRing */
5431{
5432// NOTE: Originally used only by idElimination to transfer NC structure to dest
5433// ring created by dirty hack (without nc_CallPlural)
5434  rTest(src);
5435
5436  assume(!rIsPluralRing(dest)); // destination must be a newly constructed commutative ring
5437
5438  if (!rIsPluralRing(src))
5439  {
5440    return FALSE;
5441  }
5442
5443  const int N = dest->N;
5444
5445  assume(src->N == N);
5446
5447  ring save = currRing;
5448
5449  if (dest != save)
5450    rChangeCurrRing(dest);
5451
5452  const ring srcBase = src->GetNC()->basering;
5453
5454  assume( nSetMap(srcBase) == nSetMap(currRing) ); // currRing is important here!
5455
5456  matrix C = mpNew(N,N); // ring independent
5457  matrix D = mpNew(N,N);
5458
5459  matrix C0 = src->GetNC()->C;
5460  matrix D0 = src->GetNC()->D;
5461
5462
5463  poly p = NULL;
5464  number n = NULL;
5465
5466  // map C and D into dest
5467  for (int i = 1; i < N; i++)
5468  {
5469    for (int j = i + 1; j <= N; j++)
5470    {
5471      const number n = n_Copy(p_GetCoeff(MATELEM(C0,i,j), srcBase), srcBase); // src, mapping for coeffs into currRing = dest!
5472      const poly   p = p_NSet(n, dest);
5473      MATELEM(C,i,j) = p;
5474      if (MATELEM(D0,i,j) != NULL)
5475        MATELEM(D,i,j) = prCopyR(MATELEM(D0,i,j), srcBase, dest); // ?
5476    }
5477  }
5478  /* One must test C and D _only_ in r->GetNC()->basering!!! not in r!!! */
5479
5480  idTest((ideal)C); // in dest!
5481  idTest((ideal)D);
5482
5483  if (nc_CallPlural(C, D, NULL, NULL, dest, bSetupQuotient, false, true, dest)) // also takes care about quotient ideal
5484  {
5485    //WarnS("Error transferring non-commutative structure");
5486    // error message should be in the interpreter interface
5487
5488    mpDelete(&C, dest);
5489    mpDelete(&D, dest);
5490
5491    if (currRing != save)
5492       rChangeCurrRing(save);
5493
5494    return TRUE;
5495  }
5496
5497//  mpDelete(&C, dest); // used by nc_CallPlural!
5498//  mpDelete(&D, dest);
5499
5500  if (dest != save)
5501    rChangeCurrRing(save);
5502
5503  assume(rIsPluralRing(dest));
5504  return FALSE;
5505}
5506#endif
5507
5508void rModify_a_to_A(ring r)
5509// to be called BEFORE rComplete:
5510// changes every Block with a(...) to A(...)
5511{
5512   int i=0;
5513   int j;
5514   while(r->order[i]!=0)
5515   {
5516      if (r->order[i]==ringorder_a)
5517      {
5518        r->order[i]=ringorder_a64;
5519        int *w=r->wvhdl[i];
5520        int64 *w64=(int64 *)omAlloc((r->block1[i]-r->block0[i]+1)*sizeof(int64));
5521        for(j=r->block1[i]-r->block0[i];j>=0;j--)
5522                w64[j]=(int64)w[j];
5523        r->wvhdl[i]=(int*)w64;
5524        omFreeSize(w,(r->block1[i]-r->block0[i]+1)*sizeof(int));
5525      }
5526      i++;
5527   }
5528}
Note: See TracBrowser for help on using the repository browser.