source: git/kernel/ring.cc @ 936551

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