source: git/kernel/ring.cc @ f15ef1

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