source: git/kernel/ring.cc @ 022ef5

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