source: git/kernel/ring.cc @ 0654a8b

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