source: git/kernel/ring.cc @ 585bbcb

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