source: git/Singular/ring.cc @ 144103

spielwiese
Last change on this file since 144103 was 144103, checked in by Hans Schönemann <hannes@…>, 25 years ago
* hannes: rField_is_R git-svn-id: file:///usr/local/Singular/svn/trunk@3213 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 45.5 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: ring.cc,v 1.55 1999-07-01 16:13:41 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 "mmemory.h"
14#include "tok.h"
15#include "polys.h"
16#include "numbers.h"
17#include "febase.h"
18#include "ipid.h"
19#include "ipshell.h"
20#include "ipconv.h"
21#include "intvec.h"
22#include "longalg.h"
23#include "ffields.h"
24#include "spolys.h"
25#include "subexpr.h"
26#include "ideals.h"
27#include "lists.h"
28#include "ring.h"
29
30/* global variables */
31#ifdef RDEBUG
32short rNumber=0;
33#endif
34
35// static procedures
36// unconditionally deletes fields in r
37static void rDelete(ring r);
38
39/*0 implementation*/
40BOOLEAN rField_is_R(ring r=currRing)
41{
42  return ((r->ch == -1) && (r->ch_flags==0));
43}
44
45int rBlocks(ring r)
46{
47  int i=0;
48  while (r->order[i]!=0) i++;
49  return i+1;
50}
51
52// internally changes the gloabl ring and resets the relevant
53// global variables:
54// complete == FALSE : only delete operations are enabled
55// complete == TRUE  : full reset of all variables
56#ifdef DRING
57void rChangeCurrRing(ring r, BOOLEAN complete, idhdl h)
58#else
59void rChangeCurrRing(ring r, BOOLEAN complete)
60#endif
61{
62  /*------------ set global ring vars --------------------------------*/
63  currRing = r;
64  currQuotient=NULL;
65
66  if (r != NULL)
67  {
68    rTest(r);
69    if (complete)
70    {
71      /*------------ set global ring vars --------------------------------*/
72      currQuotient=r->qideal;
73      /*------------ set redTail, except reset by nSetChar or pChangeRing */
74      test |= Sy_bit(OPT_REDTAIL);
75    }
76
77    /*------------ global variables related to coefficients ------------*/
78    nSetChar(r, complete);
79
80    /*------------ global variables related to polys -------------------*/
81    pSetGlobals(r, complete);
82
83
84    if (complete)
85    {
86    /*------------ set naMinimalPoly -----------------------------------*/
87      if (r->minpoly!=NULL)
88      {
89        naMinimalPoly=((lnumber)r->minpoly)->z;
90      }
91
92#ifdef DRING
93      pDRING=FALSE;
94      pSDRING=FALSE;
95      if ((h!=NULL) && (hasFlag(h,FLAG_DRING))) rDSet();
96#endif // DRING
97
98#ifdef SRING
99      if ((currRing->partN<=currRing->N)
100#ifdef DRING
101          && ((h==NULL) || (!hasFlag(h,FLAG_DRING)))
102#endif
103          )
104      {
105        pAltVars=currRing->partN;
106        pSRING=TRUE;
107        pSDRING=TRUE;
108      }
109      else
110      {
111        pAltVars=currRing->N+1;
112      }
113#endif // SRING
114
115    /*------------ set spolys ------------------------------------------*/
116      spSet(r);
117    }
118  }
119}
120
121void rSetHdl(idhdl h, BOOLEAN complete)
122{
123  int i;
124  ring rg = NULL;
125  if (h!=NULL)
126  {
127    rg = IDRING(h);
128    mmTestP((ADDRESS)h,sizeof(idrec));
129    mmTestLP((ADDRESS)IDID(h));
130    mmTestP(rg,sizeof(ip_sring));
131#ifdef MDEBUG
132    i=rBlocks(rg);
133#endif
134    mmTestP(rg->order,i*sizeof(int));
135    mmTestP(rg->block0,i*sizeof(int));
136    mmTestP(rg->block1,i*sizeof(int));
137    mmTestP(rg->wvhdl,i*sizeof(short *));
138  }
139  else complete=FALSE;
140
141  // clean up history
142    if (((sLastPrinted.rtyp>BEGIN_RING) && (sLastPrinted.rtyp<END_RING))
143        || ((sLastPrinted.rtyp==LIST_CMD)&&(lRingDependend((lists)sLastPrinted.data))))
144    {
145      sLastPrinted.CleanUp();
146      memset(&sLastPrinted,0,sizeof(sleftv));
147    }
148
149   /*------------ change the global ring -----------------------*/
150  #ifdef DRING
151  rChangeCurrRing(rg,complete,h);
152  #else
153  rChangeCurrRing(rg,complete);
154  #endif
155  currRingHdl = h;
156
157    /*------------ set pShortOut -----------------------*/
158  if (complete /*&&(h!=NULL)*/)
159  {
160    #ifdef HAVE_TCL
161    if (tclmode)
162    {
163      PrintTCLS('R',IDID(h));
164      pShortOut=(int)FALSE;
165    }
166    else
167    #endif
168    {
169      pShortOut=(int)TRUE;
170      if ((rg->parameter!=NULL) && (rg->ch<2))
171      {
172        for (i=0;i<rPar(rg);i++)
173        {
174          if(strlen(rg->parameter[i])>1)
175          {
176            pShortOut=(int)FALSE;
177            break;
178          }
179        }
180      }
181      if (pShortOut)
182      {
183        for (i=(rg->N-1);i>=0;i--)
184        {
185          if(strlen(rg->names[i])>1)
186          {
187            pShortOut=(int)FALSE;
188            break;
189          }
190        }
191      }
192    }
193  }
194
195}
196
197idhdl rDefault(char *s)
198{
199  idhdl tmp=NULL;
200
201  if (s!=NULL) tmp = enterid(s, myynest, RING_CMD, &IDROOT);
202  if (tmp==NULL) return NULL;
203
204  if (ppNoether!=NULL) pDelete(&ppNoether);
205  if ((sLastPrinted.rtyp>BEGIN_RING) && (sLastPrinted.rtyp<END_RING))
206  {
207    sLastPrinted.CleanUp();
208    memset(&sLastPrinted,0,sizeof(sleftv));
209  }
210
211  currRing = IDRING(tmp);
212
213  currRing->ch    = 32003;
214  currRing->N     = 3;
215  /*currRing->P     = 0; Alloc0 in idhdl::set, ipid.cc*/
216#ifdef RDEBUG
217  rNumber++;
218  currRing->no    =rNumber;
219#endif
220#ifdef SRING
221  currRing->partN = 4;
222#endif
223  /*names*/
224  currRing->names = (char **) Alloc(3 * sizeof(char *));
225  currRing->names[0]  = mstrdup("x");
226  currRing->names[1]  = mstrdup("y");
227  currRing->names[2]  = mstrdup("z");
228  /*weights: entries for 3 blocks: NULL*/
229  currRing->wvhdl = (short **)Alloc0(3 * sizeof(short *));
230  /*order: dp,C,0*/
231  currRing->order = (int *) Alloc(3 * sizeof(int *));
232  currRing->block0 = (int *)Alloc(3 * sizeof(int *));
233  currRing->block1 = (int *)Alloc(3 * sizeof(int *));
234  /* ringorder dp for the first block: var 1..3 */
235  currRing->order[0]  = ringorder_dp;
236  currRing->block0[0] = 1;
237  currRing->block1[0] = 3;
238  /* ringorder C for the second block: no vars */
239  currRing->order[1]  = ringorder_C;
240  currRing->block0[1] = 0;
241  currRing->block1[1] = 0;
242  /* the last block: everything is 0 */
243  currRing->order[2]  = 0;
244  currRing->block0[2] = 0;
245  currRing->block1[2] = 0;
246  /*polynomial ring*/
247  currRing->OrdSgn    = 1;
248
249  /* complete ring intializations */
250  rComplete(currRing);
251  rSetHdl(tmp,TRUE);
252  return currRingHdl;
253}
254
255///////////////////////////////////////////////////////////////////////////
256//
257// rInit: define a new ring from sleftv's
258//
259
260/////////////////////////////
261// Auxillary functions
262//
263
264// check intvec, describing the ordering
265static BOOLEAN rCheckIV(intvec *iv)
266{
267  if ((iv->length()!=2)&&(iv->length()!=3))
268  {
269    WerrorS("weights only for orderings wp,ws,Wp,Ws,a,M");
270    return TRUE;
271  }
272  return FALSE;
273}
274
275static int rTypeOfMatrixOrder(intvec * order)
276{
277  int i=0,j,typ=1;
278  int sz = (int)sqrt((double)(order->length()-2));
279
280  while ((i<sz) && (typ==1))
281  {
282    j=0;
283    while ((j<sz) && ((*order)[j*sz+i+2]==0)) j++;
284    if (j>=sz)
285    {
286      typ = 0;
287      WerrorS("Matrix order not complete");
288    }
289    else if ((*order)[j*sz+i+2]<0)
290      typ = -1;
291    else
292      i++;
293  }
294  return typ;
295}
296
297// set R->order, R->block, R->wvhdl, r->OrdSgn from sleftv
298static BOOLEAN rSleftvOrdering2Ordering(sleftv *ord, ring R)
299{
300  int last = 0, o=0, n = 1, i=0, typ = 1, j;
301  sleftv *sl = ord;
302
303  // determine nBlocks
304  while (sl!=NULL)
305  {
306    intvec *iv = (intvec *)(sl->data);
307    if (((*iv)[1]==ringorder_c)||((*iv)[1]==ringorder_C)) i++;
308    else if ((*iv)[1]!=ringorder_a) o++;
309    n++;
310    sl=sl->next;
311  }
312  // check whether at least one real ordering
313  if (o==0)
314  {
315    WerrorS("invalid combination of orderings");
316    return TRUE;
317  }
318  // if no c/C ordering is given, increment n
319  if (i==0) n++;
320  else if (i != 1)
321  {
322    // throw error if more than one is given
323    WerrorS("more than one ordering c/C specified");
324    return TRUE;
325  }
326
327  // initialize fields of R
328  R->order=(int *)Alloc0(n*sizeof(int));
329  R->block0=(int *)Alloc0(n*sizeof(int));
330  R->block1=(int *)Alloc0(n*sizeof(int));
331  R->wvhdl=(short**)Alloc0(n*sizeof(short*));
332
333  // init order, so that rBlocks works correctly
334  for (j=0; j < n-1; j++)
335    R->order[j] = (int) ringorder_unspec;
336  // set last _C order, if no c/C order was given
337  if (i == 0) R->order[n-2] = ringorder_C;
338
339  /* init orders */
340  sl=ord;
341  n=-1;
342  while (sl!=NULL)
343  {
344    intvec *iv;
345    iv = (intvec *)(sl->data);
346    n++;
347
348    /* the format of an ordering:
349     *  iv[0]: factor
350     *  iv[1]: ordering
351     *  iv[2..end]: weights
352     */
353    R->order[n] = (*iv)[1];
354    switch ((*iv)[1])
355    {
356        case ringorder_ws:
357        case ringorder_Ws:
358          typ=-1;
359        case ringorder_wp:
360        case ringorder_Wp:
361          R->wvhdl[n]=(short*)AllocL((iv->length()-1)*sizeof(short));
362          for (i=2; i<iv->length(); i++)
363            R->wvhdl[n][i-2] = (short)(*iv)[i];
364          R->block0[n] = last+1;
365          last += iv->length()-2;
366          R->block1[n] = last;
367          break;
368        case ringorder_ls:
369        case ringorder_ds:
370        case ringorder_Ds:
371          typ=-1;
372        case ringorder_lp:
373        case ringorder_dp:
374        case ringorder_Dp:
375          R->block0[n] = last+1;
376          if (iv->length() == 3) last+=(*iv)[2];
377          else last += (*iv)[0];
378          R->block1[n] = last;
379          if (rCheckIV(iv)) return TRUE;
380          break;
381        case ringorder_c:
382        case ringorder_C:
383          if (rCheckIV(iv)) return TRUE;
384          break;
385        case ringorder_a:
386          R->block0[n] = last+1;
387          R->block1[n] = last + iv->length() - 2;
388          R->wvhdl[n] = (short*)AllocL((iv->length()-1)*sizeof(short));
389          for (i=2; i<iv->length(); i++)
390          {
391            R->wvhdl[n][i-2]=(short)(*iv)[i];
392            if ((*iv)[i]<0) typ=-1;
393          }
394          break;
395        case ringorder_M:
396        {
397          int Mtyp=rTypeOfMatrixOrder(iv);
398          if (Mtyp==0) return TRUE;
399          if (Mtyp==-1) typ = -1;
400
401          R->wvhdl[n] =( short*)AllocL((iv->length()-1)*sizeof(short));
402          for (i=2; i<iv->length();i++)
403            R->wvhdl[n][i-2]=(short)(*iv)[i];
404
405          R->block0[n] = last+1;
406          last += (int)sqrt((double)(iv->length()-2));
407          R->block1[n] = last;
408          break;
409        }
410
411        case ringorder_no:
412           R->order[n] = ringorder_unspec;
413           return TRUE;
414
415        default:
416          Werror("Internal Error: Unknown ordering %d", (*iv)[1]);
417          R->order[n] = ringorder_unspec;
418          return TRUE;
419    }
420    sl=sl->next;
421  }
422
423  // check for complete coverage
424  if ((R->order[n]==ringorder_c) ||  (R->order[n]==ringorder_C)) n--;
425  if (R->block1[n] != R->N)
426  {
427    if (((R->order[n]==ringorder_dp) ||
428         (R->order[n]==ringorder_ds) ||
429         (R->order[n]==ringorder_Dp) ||
430         (R->order[n]==ringorder_Ds) ||
431         (R->order[n]==ringorder_lp) ||
432         (R->order[n]==ringorder_ls))
433        &&
434        R->block0[n] <= R->N)
435    {
436      R->block1[n] = R->N;
437    }
438    else
439    {
440      Werror("mismatch of number of vars (%d) and ordering (%d vars)",
441             R->N,R->block1[n]);
442      return TRUE;
443    }
444  }
445  R->OrdSgn = typ;
446  return FALSE;
447}
448
449// get array of strings from list of sleftv's
450static BOOLEAN rSleftvList2StringArray(sleftv* sl, char** p)
451{
452
453  while(sl!=NULL)
454  {
455    if (sl->Name() == sNoName)
456    {
457      if (sl->Typ()==POLY_CMD)
458      {
459        sleftv s_sl;
460        iiConvert(POLY_CMD,ANY_TYPE,-1,sl,&s_sl);
461        if (s_sl.Name() != sNoName)
462          *p = mstrdup(s_sl.Name());
463        else
464          *p = NULL;
465        sl->next = s_sl.next;
466        s_sl.next = NULL;
467        s_sl.CleanUp();
468        if (*p == NULL) return TRUE;
469      }
470      else
471        return TRUE;
472    }
473    else
474      *p = mstrdup(sl->Name());
475    p++;
476    sl=sl->next;
477  }
478  return FALSE;
479}
480
481
482////////////////////
483//
484// rInit itself:
485//
486// INPUT:  s: name, pn: ch & parameter (names), rv: variable (names)
487//         ord: ordering
488// RETURN: currRingHdl on success
489//         NULL        on error
490// NOTE:   * makes new ring to current ring, on success
491//         * considers input sleftv's as read-only
492idhdl rInit(char *s, sleftv* pn, sleftv* rv, sleftv* ord,
493            BOOLEAN isDRing)
494{
495  int ch;
496  int float_len=0;
497  ring R = NULL;
498  idhdl tmp = NULL;
499  BOOLEAN ffChar=FALSE;
500
501  /* ch -------------------------------------------------------*/
502  // get ch of ground field
503  if (pn->Typ()==INT_CMD)
504  {
505    ch=(int)pn->Data();
506  }
507  else if (pn->name != NULL && strcmp(pn->name,"real")==0)
508  {
509    ch=-1;
510    if ((pn->next!=NULL) && (pn->next->Typ()==INT_CMD))
511    {
512      float_len=(int)pn->next->Data();
513      pn=pn->next;
514    }
515  }
516  else
517  {
518    Werror("Wrong ground field specification");
519    goto rInitError;
520  }
521  pn=pn->next;
522
523  /* characteristic -----------------------------------------------*/
524  /* input: 0 ch=0 : Q     parameter=NULL    ffChar=FALSE
525   *         0    1 : Q(a,...)        *names         FALSE
526   *         0   -1 : R               NULL           FALSE
527   *         0   -1 : C               *names         FALSE
528   *         p    p : Fp              NULL           FALSE
529   *         p   -p : Fp(a)           *names         FALSE
530   *         q    q : GF(q=p^n)       *names         TRUE
531   */
532  if (ch!=-1)
533  {
534    int l = 0;
535
536    if (ch!=0 && (ch<2) || (ch > 32003))
537    {
538      Warn("%d is invalid characteristic of ground field. 32003 is used.", ch);
539      ch=32003;
540    }
541    // load fftable, if necessary
542    if (pn!=NULL)
543    {
544      while ((ch!=fftable[l]) && (fftable[l])) l++;
545      if (fftable[l]==0) ch = IsPrime(ch);
546      else
547      {
548        char *m[1]={(char *)sNoName};
549        nfSetChar(ch,m);
550        if (errorreported) goto rInitError;
551        else ffChar=TRUE;
552      }
553    }
554    else
555      ch = IsPrime(ch);
556  }
557  // allocated ring and set ch
558  R = (ring) Alloc0(sizeof(sip_sring));
559  R->ch = ch;
560  if (ch == -1)
561  {
562    R->ch_flags= float_len;
563  }
564
565  /* parameter -------------------------------------------------------*/
566  if (pn!=NULL)
567  {
568    R->P=pn->listLength();
569    //if ((ffChar|| (ch == 1)) && (R->P > 1))
570    if ((R->P > 1) && (ffChar || (ch == -1)))
571    {
572      WerrorS("too many parameters");
573      goto rInitError;
574    }
575    R->parameter=(char**)Alloc0(R->P*sizeof(char *));
576    if (rSleftvList2StringArray(pn, R->parameter))
577    {
578      WerrorS("parameter expected");
579      goto rInitError;
580    }
581    if (ch>1 && !ffChar) R->ch=-ch;
582    else if (ch==0) R->ch=1;
583  }
584  else if (ffChar)
585  {
586    WerrorS("need one parameter");
587    goto rInitError;
588  }
589
590  /* names and number of variables-------------------------------------*/
591  R->N = rv->listLength();
592  R->names   = (char **)Alloc0(R->N * sizeof(char *));
593  if (rSleftvList2StringArray(rv, R->names))
594  {
595    WerrorS("name of ring variable expected");
596    goto rInitError;
597  }
598
599  /* ordering -------------------------------------------------------------*/
600  if (rSleftvOrdering2Ordering(ord, R))
601    goto rInitError;
602
603  // Complete the initialization
604  if (rComplete(R))
605    goto rInitError;
606
607  // try to enter the ring into the name list //
608  if ((tmp = enterid(s, myynest, RING_CMD, &IDROOT))==NULL)
609    goto rInitError;
610
611  memcpy(IDRING(tmp),R,sizeof(*R));
612  // set current ring
613  Free(R,  sizeof(ip_sring));
614#ifdef RDEBUG
615  rNumber++;
616  R->no    =rNumber;
617#endif
618  return tmp;
619
620  // error case:
621  rInitError:
622  if  (R != NULL) rDelete(R);
623  return NULL;
624}
625
626// set those fields of the ring, which can be computed from other fields:
627// More particularly, sets r->VarOffset
628BOOLEAN rComplete(ring r, int force)
629{
630
631  int VarCompIndex, VarLowIndex, VarHighIndex;
632  // check number of vars and number of params
633  if (r->N + 1 > (int) MAX_EXPONENT_NUMBER)
634  {
635    Werror("Too many ring variables: %d is the maximum",
636           MAX_EXPONENT_NUMBER -1);
637    return TRUE;
638  }
639
640
641  r->VarOffset = (int*) Alloc((r->N + 1)*sizeof(int));
642  pGetVarIndicies(r, r->VarOffset, VarCompIndex,
643                  VarLowIndex, VarHighIndex);
644  r->VarCompIndex = VarCompIndex;
645  r->VarLowIndex = VarLowIndex;
646  r->VarHighIndex = VarHighIndex;
647  return FALSE;
648}
649
650/*2
651 * set a new ring from the data:
652 s: name, chr: ch, varnames: rv, ordering: ord, typ: typ
653 */
654#ifdef DRING
655void rDSet()
656{
657  pDRING=TRUE;
658  pSDRING=TRUE;
659  pdN=currRing->partN;
660  pdK=pVariables-pdN*2-1;
661}
662#endif
663
664int rIsRingVar(char *n)
665{
666  if ((currRing!=NULL) && (currRing->names!=NULL))
667  {
668    for (int i=0; i<currRing->N; i++)
669    {
670      if (currRing->names[i]==NULL) return -1;
671      if (strcmp(n,currRing->names[i]) == 0) return (int)i;
672    }
673  }
674  return -1;
675}
676
677char* RingVar(short i)
678{
679  return currRing->names[i];
680}
681
682void rWrite(ring r)
683{
684  if ((r==NULL)||(r->order==NULL))
685    return; /*to avoid printing after errors....*/
686
687  int nblocks=rBlocks(r);
688
689  mmTestP(r,sizeof(ip_sring));
690  mmTestP(r->order,nblocks*sizeof(int));
691  mmTestP(r->block0,nblocks*sizeof(int));
692  mmTestP(r->block1,nblocks*sizeof(int));
693  mmTestP(r->wvhdl,nblocks*sizeof(short *));
694  mmTestP(r->names,r->N*sizeof(char *));
695
696  nblocks--;
697
698
699  if (rField_is_GF(r))
700  {
701    Print("//   # ground field : %d\n",rInternalChar(r));
702    Print("//   primitive element : %s\n", r->parameter[0]);
703    if (r==currRing)
704    {
705      StringSetS("//   minpoly        : ");
706      nfShowMipo();PrintS(StringAppendS("\n"));
707    }
708  }
709  else
710  {
711    PrintS("//   characteristic : ");
712    if ( rField_is_R(r) )             PrintS("0 (real)\n");  /* R */
713    else if ( rField_is_long_R(r) )
714      Print("0 (real:%d digits)\n",r->ch_flags);  /* long R */
715    else if ( rField_is_long_C(r) )
716      Print("0 (complex:%d digits)\n",r->ch_flags);  /* long C */
717    else
718      Print ("%d\n",rChar(r)); /* Fp(a) */
719    if (r->parameter!=NULL)
720    {
721      Print ("//   %d parameter    : ",rPar(r));
722      char **sp=r->parameter;
723      int nop=0;
724      while (nop<rPar(r))
725      {
726        PrintS(*sp);
727        PrintS(" ");
728        sp++; nop++;
729      }
730      PrintS("\n//   minpoly        : ");
731      if (r->minpoly==NULL)
732      {
733        PrintS("0\n");
734      }
735      else if (r==currRing)
736      {
737        StringSetS(""); nWrite(r->minpoly); PrintS(StringAppendS("\n"));
738      }
739      else
740      {
741        PrintS("...\n");
742      }
743    }
744  }
745  Print("//   number of vars : %d",r->N);
746
747  //for (nblocks=0; r->order[nblocks]; nblocks++);
748  nblocks=rBlocks(r)-1;
749
750  for (int l=0, nlen=0 ; l<nblocks; l++)
751  {
752    int i;
753    Print("\n//        block %3d : ",l+1);
754
755    Print("ordering %c", (" acCMldDwWldDwWu")[r->order[l]]);
756    if ((r->order[l]>=ringorder_lp)&&(r->order[l]!=ringorder_unspec))
757    {
758      if (r->order[l]>=ringorder_ls)
759        PrintS("s");
760      else
761        PrintS("p");
762    }
763
764    if ((r->order[l] != ringorder_c) && (r->order[l] != ringorder_C))
765    {
766      PrintS("\n//                  : names    ");
767      for (i = r->block0[l]-1; i<r->block1[l]; i++)
768      {
769        nlen = strlen(r->names[i]);
770        Print("%s ",r->names[i]);
771      }
772    }
773
774    if (r->wvhdl[l]!=NULL)
775    {
776      for (int j= 0;
777           j<(r->block1[l]-r->block0[l]+1)*(r->block1[l]-r->block0[l]+1);
778           j+=i)
779      {
780        PrintS("\n//                  : weights  ");
781        for (i = 0; i<=r->block1[l]-r->block0[l]; i++)
782        {
783          Print("%*d " ,nlen,r->wvhdl[l][i+j],i+j);
784        }
785        if (r->order[l]!=ringorder_M) break;
786      }
787    }
788  }
789  if (r->qideal!=NULL)
790  {
791    PrintS("\n// quotient ring from ideal");
792    if (r==currRing)
793    {
794      PrintLn();
795      iiWriteMatrix((matrix)r->qideal,"_",1);
796    }
797    else PrintS(" ...");
798  }
799}
800
801static void rDelete(ring r)
802{
803  int i, j;
804
805  if (r == NULL) return;
806
807  // delete order stuff
808  if (r->order != NULL)
809  {
810    i=rBlocks(r);
811    assume(r->block0 != NULL && r->block1 != NULL && r->wvhdl != NULL);
812    // delete order
813    Free((ADDRESS)r->order,i*sizeof(int));
814    Free((ADDRESS)r->block0,i*sizeof(int));
815    Free((ADDRESS)r->block1,i*sizeof(int));
816    // delete weights
817    for (j=0; j<i; j++)
818    {
819      if (r->wvhdl[j]!=NULL)
820        FreeL(r->wvhdl[j]);
821    }
822    Free((ADDRESS)r->wvhdl,i*sizeof(short *));
823  }
824  else
825  {
826    assume(r->block0 == NULL && r->block1 == NULL && r->wvhdl == NULL);
827  }
828
829  // delete varnames
830  if(r->names!=NULL)
831  {
832    for (i=0; i<r->N; i++)
833    {
834      if (r->names[i] != NULL) FreeL((ADDRESS)r->names[i]);
835    }
836    Free((ADDRESS)r->names,r->N*sizeof(char *));
837  }
838
839  // delete parameter
840  if (r->parameter!=NULL)
841  {
842    char **s=r->parameter;
843    j = 0;
844    while (j < rPar(r))
845    {
846      if (*s != NULL) FreeL((ADDRESS)*s);
847      s++;
848      j++;
849    }
850    Free((ADDRESS)r->parameter,rPar(r)*sizeof(char *));
851  }
852  if (r->VarOffset != NULL)
853    Free((ADDRESS)r->VarOffset, (r->N +1)*sizeof(int));
854  Free(r, sizeof(ip_sring));
855}
856
857void rKill(ring r)
858{
859  rTest(r);
860  if ((r->ref<=0)&&(r->order!=NULL))
861  {
862#ifdef RDEBUG
863    if (traceit &TRACE_SHOW_RINGS) Print("kill ring %d\n",r->no);
864#endif
865    if (r==currRing)
866    {
867      if (r->qideal!=NULL)
868      {
869        idDelete(&r->qideal);
870        r->qideal=NULL;
871        currQuotient=NULL;
872      }
873      if (ppNoether!=NULL) pDelete(&ppNoether);
874      if ((sLastPrinted.rtyp>BEGIN_RING) && (sLastPrinted.rtyp<END_RING))
875      {
876        sLastPrinted.CleanUp();
877        memset(&sLastPrinted,0,sizeof(sleftv));
878      }
879      currRing=NULL;
880      currRingHdl=NULL;
881    }
882    else if (r->qideal!=NULL)
883    {
884      ring savecurrRing = currRing;
885      rChangeCurrRing((ring)r,FALSE);
886      idDelete(&r->qideal);
887      r->qideal=NULL;
888      rChangeCurrRing(savecurrRing,FALSE);
889    }
890    int i=1;
891    int j;
892    int *pi=r->order;
893#ifdef USE_IILOCALRING
894    for (j=0;j<iiRETURNEXPR_len;j++)
895    {
896      if (iiLocalRing[j]==r)
897      {
898        if (j<myynest) Warn("killing the basering for level %d",j);
899        iiLocalRing[j]=NULL;
900      }
901    }
902#else /* USE_IILOCALRING */
903    {
904      namehdl nshdl = namespaceroot;
905
906      for(nshdl=namespaceroot; nshdl->isroot != TRUE; nshdl = nshdl->next) {
907        //Print("NSstack: %s:%d, nesting=%d\n", nshdl->name, nshdl->lev, nshdl->myynest);
908        if (nshdl->currRing==r)
909        {
910          if (nshdl->myynest<myynest)
911//            Warn("killing the basering for level %d/%d",nshdl->lev,nshdl->myynest);
912          Warn("killing the basering for level %d",nshdl->myynest);
913          nshdl->currRing=NULL;
914        }
915      }
916      if (nshdl->currRing==r)
917      {
918        //Print("NSstack: %s:%d, nesting=%d\n", nshdl->name, nshdl->lev, nshdl->myynest);
919        if (nshdl->myynest<myynest)
920//          Warn("killing the basering for level %d/%d",nshdl->lev,nshdl->myynest);
921          Warn("killing the basering for level %d",nshdl->myynest);
922        nshdl->currRing=NULL;
923      }
924    }
925#endif /* USE_IILOCALRING */
926
927    rDelete(r);
928    return;
929  }
930  r->ref--;
931}
932
933void rKill(idhdl h)
934{
935#ifndef HAVE_NAMESPACES1
936  ring r = IDRING(h);
937  if (r!=NULL) rKill(r);
938  if (h==currRingHdl)
939  {
940#ifdef HAVE_NAMESPACES
941    namehdl nsHdl = namespaceroot;
942    while(nsHdl!=NULL) {
943      currRingHdl=NSROOT(nsHdl);
944#else /* HAVE_NAMESPACES */
945      currRingHdl=IDROOT;
946#endif /* HAVE_NAMESPACES */
947      while (currRingHdl!=NULL)
948      {
949        if ((currRingHdl!=h)
950            && (IDTYP(currRingHdl)==IDTYP(h))
951            && (h->data.uring==currRingHdl->data.uring))
952          break;
953        currRingHdl=IDNEXT(currRingHdl);
954      }
955#ifdef HAVE_NAMESPACES
956      if ((currRingHdl != NULL) && (currRingHdl!=h)
957          && (IDTYP(currRingHdl)==IDTYP(h))
958          && (h->data.uring==currRingHdl->data.uring))
959        break;
960      nsHdl = nsHdl->next;
961    }
962#endif /* HAVE_NAMESPACES */
963  }
964#else
965    if(currRingHdl==NULL) {
966      namehdl ns = namespaceroot;
967      BOOLEAN found=FALSE;
968
969      while(!ns->isroot) {
970        currRingHdl=NSROOT(namespaceroot->next);
971        while (currRingHdl!=NULL)
972        {
973          if ((currRingHdl!=h)
974              && (IDTYP(currRingHdl)==IDTYP(h))
975              && (h->data.uring==currRingHdl->data.uring))
976          { found=TRUE; break; }
977
978          currRingHdl=IDNEXT(currRingHdl);
979        }
980        if(found) break;
981        ns=IDNEXT(ns);
982      }
983    }
984    if(currRingHdl == NULL || IDRING(h) != IDRING(currRingHdl)) {
985      currRingHdl = namespaceroot->currRingHdl;
986
987/*      PrintS("Running rFind()\n");
988      currRingHdl = rFindHdl(IDRING(h), NULL, NULL);
989      if(currRingHdl == NULL)
990      {
991        PrintS("rFind()return 0\n");
992      }
993      else
994      {
995        PrintS("Huppi rfind return an currRingHDL\n");
996        Print("%x, %x\n", IDRING(h),IDRING(currRingHdl) );
997      }
998*/
999    }
1000    else
1001    {
1002      //PrintS("Huppi found an currRingHDL\n");
1003      //Print("%x, %x\n", IDRING(h),IDRING(currRingHdl) );
1004
1005    }
1006#endif /* HAVE_NAMESPACES */
1007}
1008
1009idhdl rFindHdl(ring r, idhdl n, idhdl w)
1010{
1011#ifdef HAVE_NAMESPACES
1012  idhdl h;
1013  namehdl ns = namespaceroot;
1014
1015  while(!ns->isroot) {
1016    h = NSROOT(ns);
1017    if(w != NULL) h = w;
1018    while (h!=NULL)
1019    {
1020      if (((IDTYP(h)==RING_CMD)||(IDTYP(h)==QRING_CMD))
1021          && (h->data.uring==r)
1022          && (h!=n))
1023        return h;
1024      h=IDNEXT(h);
1025    }
1026    ns = ns->next;
1027  }
1028  h = NSROOT(ns);
1029  if(w != NULL) h = w;
1030  while (h!=NULL)
1031  {
1032    if (((IDTYP(h)==RING_CMD)||(IDTYP(h)==QRING_CMD))
1033        && (h->data.uring==r)
1034        && (h!=n))
1035      return h;
1036    h=IDNEXT(h);
1037  }
1038#if 0
1039  if(namespaceroot->isroot) h = IDROOT;
1040  else h = NSROOT(namespaceroot->next);
1041  if(w != NULL) h = w;
1042  while (h!=NULL)
1043  {
1044    if (((IDTYP(h)==RING_CMD)||(IDTYP(h)==QRING_CMD))
1045        && (h->data.uring==r)
1046        && (h!=n))
1047      return h;
1048    h=IDNEXT(h);
1049  }
1050#endif
1051#else
1052  idhdl h=IDROOT;
1053  if(w != NULL) h = w;
1054  while (h!=NULL)
1055  {
1056    if (((IDTYP(h)==RING_CMD)||(IDTYP(h)==QRING_CMD))
1057        && (h->data.uring==r)
1058        && (h!=n))
1059      return h;
1060    h=IDNEXT(h);
1061  }
1062#endif
1063  return NULL;
1064}
1065
1066int rOrderName(char * ordername)
1067{
1068  int order=0;
1069
1070  switch (*ordername)
1071  {
1072  case 'l':
1073    if (*(ordername+1)=='p') order = ringorder_lp;
1074    else if (*(ordername+1)=='s') order = ringorder_ls;
1075    break;
1076  case 'd':
1077    if (*(ordername+1)=='p') order = ringorder_dp;
1078    else if (*(ordername+1)=='s') order = ringorder_ds;
1079    break;
1080  case 'w':
1081    if (*(ordername+1)=='p') order = ringorder_wp;
1082    else if (*(ordername+1)=='s') order = ringorder_ws;
1083    break;
1084  case 'D':
1085    if (*(ordername+1)=='p') order = ringorder_Dp;
1086    else if (*(ordername+1)=='s') order = ringorder_Ds;
1087    break;
1088  case 'W':
1089    if (*(ordername+1)=='p') order = ringorder_Wp;
1090    else if (*(ordername+1)=='s') order = ringorder_Ws;
1091    break;
1092  case 'c': order = ringorder_c; break;
1093  case 'C': order = ringorder_C; break;
1094  case 'a': order = ringorder_a; break;
1095  case 'M': order = ringorder_M; break;
1096  default: break;
1097  }
1098  if (order==0) Werror("wrong ring order `%s`",ordername);
1099  FreeL((ADDRESS)ordername);
1100  return order;
1101}
1102
1103char * rOrdStr(ring r)
1104{
1105  int nblocks,l,i;
1106
1107  for (nblocks=0; r->order[nblocks]; nblocks++);
1108  nblocks--;
1109
1110  StringSetS("");
1111  for (l=0; ; l++)
1112  {
1113    StringAppend("%c",(" acCMldDwWldDwW")[r->order[l]]);
1114    if (r->order[l]>=ringorder_lp)
1115    {
1116      if (r->order[l]>=ringorder_ls)
1117        StringAppendS("s");
1118      else
1119        StringAppendS("p");
1120    }
1121    if ((r->order[l] != ringorder_c) && (r->order[l] != ringorder_C))
1122    {
1123      if (r->wvhdl[l]!=NULL)
1124      {
1125        StringAppendS("(");
1126        for (int j= 0;
1127             j<(r->block1[l]-r->block0[l]+1)*(r->block1[l]-r->block0[l]+1);
1128             j+=i+1)
1129        {
1130          char c=',';
1131          for (i = 0; i<r->block1[l]-r->block0[l]; i++)
1132          {
1133            StringAppend("%d," ,r->wvhdl[l][i+j]);
1134          }
1135          if (r->order[l]!=ringorder_M)
1136          {
1137            StringAppend("%d)" ,r->wvhdl[l][i+j]);
1138            break;
1139          }
1140          if (j+i+1==(r->block1[l]-r->block0[l]+1)*(r->block1[l]-r->block0[l]+1))
1141            c=')';
1142          StringAppend("%d%c" ,r->wvhdl[l][i+j],c);
1143        }
1144      }
1145      else
1146        StringAppend("(%d)",r->block1[l]-r->block0[l]+1);
1147    }
1148    if (l==nblocks) return mstrdup(StringAppendS(""));
1149    StringAppendS(",");
1150  }
1151}
1152
1153char * rVarStr(ring r)
1154{
1155  int i;
1156  int l=2;
1157  char *s;
1158
1159  for (i=0; i<r->N; i++)
1160  {
1161    l+=strlen(r->names[i])+1;
1162  }
1163  s=(char *)AllocL(l);
1164  s[0]='\0';
1165  for (i=0; i<r->N-1; i++)
1166  {
1167    strcat(s,r->names[i]);
1168    strcat(s,",");
1169  }
1170  strcat(s,r->names[i]);
1171  return s;
1172}
1173
1174char * rCharStr(ring r)
1175{
1176  char *s;
1177  int i;
1178
1179  if (r->parameter==NULL)
1180  {
1181    i=r->ch;
1182    if(i==-1)
1183      s=mstrdup("real");                    /* R */
1184    else
1185    {
1186      s=(char *)AllocL(6);
1187      sprintf(s,"%d",i);                   /* Q, Z/p */
1188    }
1189    return s;
1190  }
1191  int l=0;
1192  for(i=0; i<rPar(r);i++)
1193  {
1194    l+=(strlen(r->parameter[i])+1);
1195  }
1196  s=(char *)AllocL(l+6);
1197  s[0]='\0';
1198  if (r->ch<0)       sprintf(s,"%d",-r->ch); /* Fp(a) */
1199  else if (r->ch==1) sprintf(s,"0");         /* Q(a)  */
1200  else
1201  {
1202    sprintf(s,"%d,%s",r->ch,r->parameter[0]); /* Fq  */
1203    return s;
1204  }
1205  char tt[2];
1206  tt[0]=',';
1207  tt[1]='\0';
1208  for(i=0; i<rPar(r);i++)
1209  {
1210    strcat(s,tt);
1211    strcat(s,r->parameter[i]);
1212  }
1213  return s;
1214}
1215
1216char * rParStr(ring r)
1217{
1218  if (r->parameter==NULL) return mstrdup("");
1219
1220  int i;
1221  int l=2;
1222
1223  for (i=0; i<rPar(r); i++)
1224  {
1225    l+=strlen(r->parameter[i])+1;
1226  }
1227  char *s=(char *)AllocL(l);
1228  s[0]='\0';
1229  for (i=0; i<rPar(r)-1; i++)
1230  {
1231    strcat(s,r->parameter[i]);
1232    strcat(s,",");
1233  }
1234  strcat(s,r->parameter[i]);
1235  return s;
1236}
1237
1238char * rString(ring r)
1239{
1240  char *ch=rCharStr(r);
1241  char *var=rVarStr(r);
1242  char *ord=rOrdStr(r);
1243  char *res=(char *)AllocL(strlen(ch)+strlen(var)+strlen(ord)+9);
1244  sprintf(res,"(%s),(%s),(%s)",ch,var,ord);
1245  FreeL((ADDRESS)ch);
1246  FreeL((ADDRESS)var);
1247  FreeL((ADDRESS)ord);
1248  return res;
1249}
1250
1251int rChar(ring r)
1252{
1253  if (r->ch==-1)
1254    return 0;
1255  if (r->parameter==NULL) /* Q, Fp */
1256    return r->ch;
1257  if (r->ch<0)           /* Fp(a)  */
1258    return -r->ch;
1259  if (r->ch==1)          /* Q(a)  */
1260    return 0;
1261  /*else*/               /* GF(p,n) */
1262  {
1263    if ((r->ch & 1)==0) return 2;
1264    int i=3;
1265    while ((r->ch % i)!=0) i+=2;
1266    return i;
1267  }
1268}
1269
1270int    rIsExtension(ring r)
1271{
1272  if (r->parameter==NULL) /* Q, Fp */
1273    return FALSE;
1274  else
1275    return TRUE;
1276}
1277
1278int    rIsExtension()
1279{
1280  return rIsExtension( currRing );
1281}
1282
1283/*2
1284 *returns -1 for not compatible, (sum is undefined)
1285 *         0 for equal, (and sum)
1286 *         1 for compatible (and sum)
1287 */
1288int rSum(ring r1, ring r2, ring &sum)
1289{
1290  if (r1==r2)
1291  {
1292    sum=r1;
1293    r1->ref++;
1294    return 0;
1295  }
1296  ip_sring tmpR;
1297  memset(&tmpR,0,sizeof(tmpR));
1298  /* check coeff. field =====================================================*/
1299  if (rInternalChar(r1)==rInternalChar(r2))
1300  {
1301    tmpR.ch=rInternalChar(r1);
1302    if (rField_is_Q(r1)||rField_is_Zp(r1)||rField_is_GF(r1)) /*Q, Z/p, GF(p,n)*/
1303    {
1304      if (r1->parameter!=NULL)
1305      {
1306        if (strcmp(r1->parameter[0],r2->parameter[0])==0) /* 1 char */
1307        {
1308          tmpR.parameter=(char **)Alloc(sizeof(char *));
1309          tmpR.parameter[0]=mstrdup(r1->parameter[0]);
1310          tmpR.P=1;
1311        }
1312        else
1313        {
1314          WerrorS("GF(p,n)+GF(p,n)");
1315          return -1;
1316        }
1317      }
1318    }
1319    else if ((r1->ch==1)||(r1->ch<-1)) /* Q(a),Z/p(a) */
1320    {
1321      if (r1->minpoly!=NULL)
1322      {
1323        if (r2->minpoly!=NULL)
1324        {
1325          nSetChar(r1,TRUE);
1326          if ((strcmp(r1->parameter[0],r2->parameter[0])==0) /* 1 char */
1327              && naEqual(r1->minpoly,r2->minpoly))
1328          {
1329            tmpR.parameter=(char **)Alloc(sizeof(char *));
1330            tmpR.parameter[0]=mstrdup(r1->parameter[0]);
1331            tmpR.minpoly=naCopy(r1->minpoly);
1332            tmpR.P=1;
1333            nSetChar(currRing,TRUE);
1334          }
1335          else
1336          {
1337            nSetChar(currRing,TRUE);
1338            WerrorS("different minpolys");
1339            return -1;
1340          }
1341        }
1342        else
1343        {
1344          if ((strcmp(r1->parameter[0],r2->parameter[0])==0) /* 1 char */
1345              && (rPar(r2)==1))
1346          {
1347            tmpR.parameter=(char **)Alloc0(sizeof(char *));
1348            tmpR.parameter[0]=mstrdup(r1->parameter[0]);
1349            tmpR.P=1;
1350            nSetChar(r1,TRUE);
1351            tmpR.minpoly=naCopy(r1->minpoly);
1352            nSetChar(currRing,TRUE);
1353          }
1354          else
1355          {
1356            WerrorS("different parameters and minpoly!=0");
1357            return -1;
1358          }
1359        }
1360      }
1361      else /* r1->minpoly==NULL */
1362      {
1363        if (r2->minpoly!=NULL)
1364        {
1365          if ((strcmp(r1->parameter[0],r2->parameter[0])==0) /* 1 char */
1366              && (rPar(r1)==1))
1367          {
1368            tmpR.parameter=(char **)Alloc(sizeof(char *));
1369            tmpR.parameter[0]=mstrdup(r1->parameter[0]);
1370            tmpR.P=1;
1371            nSetChar(r2,TRUE);
1372            tmpR.minpoly=naCopy(r2->minpoly);
1373            nSetChar(currRing,TRUE);
1374          }
1375          else
1376          {
1377            WerrorS("different parameters and minpoly!=0");
1378            return -1;
1379          }
1380        }
1381        else
1382        {
1383          int len=rPar(r1)+rPar(r2);
1384          tmpR.parameter=(char **)Alloc(len*sizeof(char *));
1385          int i;
1386          for (i=0;i<rPar(r1);i++)
1387          {
1388            tmpR.parameter[i]=mstrdup(r1->parameter[i]);
1389          }
1390          int j,l;
1391          for(j=0;j<rPar(r2);j++)
1392          {
1393            for(l=0;l<i;l++)
1394            {
1395              if(strcmp(tmpR.parameter[l],r2->parameter[j])==0)
1396                break;
1397            }
1398            if (l==i)
1399            {
1400              tmpR.parameter[i]=mstrdup(r2->parameter[j]);
1401              i++;
1402            }
1403          }
1404          if (i!=len)
1405          {
1406            ReAlloc(tmpR.parameter,len*sizeof(char *),i*sizeof(char *));
1407          }
1408        }
1409      }
1410    }
1411  }
1412  else /* r1->ch!=r2->ch */
1413  {
1414    if (r1->ch<-1) /* Z/p(a) */
1415    {
1416      if ((r2->ch==0) /* Q */
1417          || (r2->ch==-r1->ch)) /* Z/p */
1418      {
1419        tmpR.ch=rInternalChar(r1);
1420        tmpR.parameter=(char **)Alloc(rPar(r1)*sizeof(char *));
1421        tmpR.P=rPar(r1);
1422        memcpy(tmpR.parameter,r1->parameter,rPar(r1)*sizeof(char *));
1423        if (r1->minpoly!=NULL)
1424        {
1425          nSetChar(r1,TRUE);
1426          tmpR.minpoly=naCopy(r1->minpoly);
1427          nSetChar(currRing,TRUE);
1428        }
1429      }
1430      else  /* R, Q(a),Z/q,Z/p(a),GF(p,n) */
1431      {
1432        WerrorS("Z/p(a)+(R,Q(a),Z/q(a),GF(q,n))");
1433        return -1;
1434      }
1435    }
1436    else if (r1->ch==-1) /* R */
1437    {
1438      WerrorS("R+..");
1439      return -1;
1440    }
1441    else if (r1->ch==0) /* Q */
1442    {
1443      if ((r2->ch<-1)||(r2->ch==1)) /* Z/p(a),Q(a) */
1444      {
1445        tmpR.ch=rInternalChar(r2);
1446        tmpR.P=rPar(r2);
1447        tmpR.parameter=(char **)Alloc(rPar(r2)*sizeof(char *));
1448        memcpy(tmpR.parameter,r2->parameter,rPar(r2)*sizeof(char *));
1449        if (r2->minpoly!=NULL)
1450        {
1451          nSetChar(r1,TRUE);
1452          tmpR.minpoly=naCopy(r2->minpoly);
1453          nSetChar(currRing,TRUE);
1454        }
1455      }
1456      else if (r2->ch>1) /* Z/p,GF(p,n) */
1457      {
1458        tmpR.ch=r2->ch;
1459        if (r2->parameter!=NULL)
1460        {
1461          tmpR.parameter=(char **)Alloc(sizeof(char *));
1462          tmpR.P=1;
1463          tmpR.parameter[0]=mstrdup(r2->parameter[0]);
1464        }
1465      }
1466      else
1467      {
1468        WerrorS("Q+R");
1469        return -1; /* R */
1470      }
1471    }
1472    else if (r1->ch==1) /* Q(a) */
1473    {
1474      if (r2->ch==0) /* Q */
1475      {
1476        tmpR.ch=rInternalChar(r1);
1477        tmpR.P=rPar(r1);
1478        tmpR.parameter=(char **)Alloc0(rPar(r1)*sizeof(char *));
1479        int i;
1480        for(i=0;i<rPar(r1);i++)
1481        {
1482          tmpR.parameter[i]=mstrdup(r1->parameter[i]);
1483        }
1484        if (r1->minpoly!=NULL)
1485        {
1486          nSetChar(r1,TRUE);
1487          tmpR.minpoly=naCopy(r1->minpoly);
1488          nSetChar(currRing,TRUE);
1489        }
1490      }
1491      else  /* R, Z/p,GF(p,n) */
1492      {
1493        WerrorS("Q(a)+(R,Z/p,GF(p,n))");
1494        return -1;
1495      }
1496    }
1497    else /* r1->ch >=2 , Z/p */
1498    {
1499      if (r2->ch==0) /* Q */
1500      {
1501        tmpR.ch=r1->ch;
1502      }
1503      else if (r2->ch==-r1->ch) /* Z/p(a) */
1504      {
1505        tmpR.ch=rInternalChar(r2);
1506        tmpR.P=rPar(r2);
1507        tmpR.parameter=(char **)Alloc(rPar(r2)*sizeof(char *));
1508        int i;
1509        for(i=0;i<rPar(r2);i++)
1510        {
1511          tmpR.parameter[i]=mstrdup(r2->parameter[i]);
1512        }
1513        if (r2->minpoly!=NULL)
1514        {
1515          nSetChar(r2,TRUE);
1516          tmpR.minpoly=naCopy(r2->minpoly);
1517          nSetChar(currRing,TRUE);
1518        }
1519      }
1520      else
1521      {
1522        WerrorS("Z/p+(GF(q,n),Z/q(a),R,Q(a))");
1523        return -1; /* GF(p,n),Z/q(a),R,Q(a) */
1524      }
1525    }
1526  }
1527  /* variable names ========================================================*/
1528  int i,j,k;
1529  int l=r1->N+r2->N;
1530  char **names=(char **)Alloc0(l*sizeof(char*));
1531  k=0;
1532
1533  // collect all varnames from r1, except those which are parameters
1534  // of r2, or those which are the empty string
1535  for (i=0;i<r1->N;i++)
1536  {
1537    BOOLEAN b=TRUE;
1538
1539    if (*(r1->names[i]) == '\0')
1540      b = FALSE;
1541    else if ((r2->parameter!=NULL) && (strlen(r1->names[i])==1))
1542    {
1543      for(j=0;j<rPar(r2);j++)
1544      {
1545        if (strcmp(r1->names[i],r2->parameter[j])==0)
1546        {
1547          b=FALSE;
1548          break;
1549        }
1550      }
1551    }
1552
1553    if (b)
1554    {
1555      //Print("name : %d: %s\n",k,r1->names[i]);
1556      names[k]=mstrdup(r1->names[i]);
1557      k++;
1558    }
1559    //else
1560    //  Print("no name (par1) %s\n",r1->names[i]);
1561  }
1562  // Add variables from r2, except those which are parameters of r1
1563  // those which are empty strings, and those which equal a var of r1
1564  for(i=0;i<r2->N;i++)
1565  {
1566    BOOLEAN b=TRUE;
1567
1568    if (*(r2->names[i]) == '\0')
1569      b = FALSE;
1570    else if ((r1->parameter!=NULL) && (strlen(r2->names[i])==1))
1571    {
1572      for(j=0;j<rPar(r1);j++)
1573      {
1574        if (strcmp(r2->names[i],r1->parameter[j])==0)
1575        {
1576          b=FALSE;
1577          break;
1578        }
1579      }
1580    }
1581
1582    if (b)
1583    {
1584      for(j=0;j<r1->N;j++)
1585      {
1586        if (strcmp(r1->names[j],r2->names[i])==0)
1587        {
1588          b=FALSE;
1589          break;
1590        }
1591      }
1592      if (b)
1593      {
1594        names[k]=mstrdup(r2->names[i]);
1595        //Print("name : %d : %s\n",k,r2->names[i]);
1596        k++;
1597      }
1598      //else
1599      //  Print("no name (var): %s\n",r2->names[i]);
1600    }
1601    //else
1602    //  Print("no name (par): %s\n",r2->names[i]);
1603  }
1604  // check whether we found any vars at all
1605  if (k == 0)
1606  {
1607    names[k]=mstrdup("");
1608    k=1;
1609  }
1610  tmpR.N=k;
1611  tmpR.names=names;
1612  /* ordering *======================================================== */
1613  tmpR.OrdSgn=1;
1614  if ((r1->order[0]==ringorder_unspec)
1615      && (r2->order[0]==ringorder_unspec))
1616  {
1617    tmpR.order=(int*)Alloc(3*sizeof(int));
1618    tmpR.block0=(int*)Alloc(3*sizeof(int));
1619    tmpR.block1=(int*)Alloc(3*sizeof(int));
1620    tmpR.wvhdl=(short**)Alloc0(3*sizeof(short*));
1621    tmpR.order[0]=ringorder_unspec;
1622    tmpR.order[1]=ringorder_C;
1623    tmpR.order[2]=0;
1624    tmpR.block0[0]=1;
1625    tmpR.block1[0]=tmpR.N;
1626  }
1627  else if (l==k) /* r3=r1+r2 */
1628  {
1629    int b;
1630    ring rb;
1631    if (r1->order[0]==ringorder_unspec)
1632    {
1633      /* extend order of r2 to r3 */
1634      b=rBlocks(r2);
1635      rb=r2;
1636      tmpR.OrdSgn=r2->OrdSgn;
1637    }
1638    else if (r2->order[0]==ringorder_unspec)
1639    {
1640      /* extend order of r1 to r3 */
1641      b=rBlocks(r1);
1642      rb=r1;
1643      tmpR.OrdSgn=r1->OrdSgn;
1644    }
1645    else
1646    {
1647      b=rBlocks(r1)+rBlocks(r2)-2; /* for only one order C, only one 0 */
1648      rb=NULL;
1649    }
1650    tmpR.order=(int*)Alloc0(b*sizeof(int));
1651    tmpR.block0=(int*)Alloc0(b*sizeof(int));
1652    tmpR.block1=(int*)Alloc0(b*sizeof(int));
1653    tmpR.wvhdl=(short**)Alloc0(b*sizeof(short*));
1654    if (rb!=NULL)
1655    {
1656      for (i=0;i<b;i++)
1657      {
1658        tmpR.order[i]=rb->order[i];
1659        tmpR.block0[i]=rb->block0[i];
1660        tmpR.block1[i]=rb->block1[i];
1661        if (rb->wvhdl[i]!=NULL)
1662          WarnS("rSum: weights not implemented");
1663      }
1664      tmpR.block0[0]=1;
1665    }
1666    else /* ring sum for complete rings */
1667    {
1668      for (i=0;r1->order[i]!=0;i++)
1669      {
1670        tmpR.order[i]=r1->order[i];
1671        tmpR.block0[i]=r1->block0[i];
1672        tmpR.block1[i]=r1->block1[i];
1673        if (r1->wvhdl[i]!=NULL)
1674        {
1675          int l=mmSizeL(r1->wvhdl[i]);
1676          tmpR.wvhdl[i]=(short *)AllocL(l);
1677          memcpy(tmpR.wvhdl[i],r1->wvhdl[i],l);
1678        }
1679      }
1680      j=i;
1681      i--;
1682      if ((r1->order[i]==ringorder_c)
1683          ||(r1->order[i]==ringorder_C))
1684      {
1685        j--;
1686        tmpR.order[b-2]=r1->order[i];
1687      }
1688      for (i=0;r2->order[i]!=0;i++,j++)
1689      {
1690        if ((r2->order[i]!=ringorder_c)
1691            &&(r2->order[i]!=ringorder_C))
1692        {
1693          tmpR.order[j]=r2->order[i];
1694          tmpR.block0[j]=r2->block0[i]+r1->N;
1695          tmpR.block1[j]=r2->block1[i]+r1->N;
1696          if (r2->wvhdl[i]!=NULL)
1697          {
1698            int l=mmSizeL(r2->wvhdl[i]);
1699            tmpR.wvhdl[j]=(short *)AllocL(l);
1700            memcpy(tmpR.wvhdl[j],r2->wvhdl[i],l);
1701          }
1702        }
1703      }
1704      if((r1->OrdSgn==-1)||(r2->OrdSgn==-1))
1705        tmpR.OrdSgn=-1;
1706    }
1707  }
1708  else if ((k==r1->N) && (k==r2->N)) /* r1 and r2 are "quite" the same ring */
1709    /* copy r1, because we have the variables from r1 */
1710  {
1711    int b=rBlocks(r1);
1712
1713    tmpR.order=(int*)Alloc0(b*sizeof(int));
1714    tmpR.block0=(int*)Alloc0(b*sizeof(int));
1715    tmpR.block1=(int*)Alloc0(b*sizeof(int));
1716    tmpR.wvhdl=(short**)Alloc0(b*sizeof(short*));
1717    for (i=0;i<b;i++)
1718    {
1719      tmpR.order[i]=r1->order[i];
1720      tmpR.block0[i]=r1->block0[i];
1721      tmpR.block1[i]=r1->block1[i];
1722      if (r1->wvhdl[i]!=NULL)
1723      {
1724        int l=mmSizeL(r1->wvhdl[i]);
1725        tmpR.wvhdl[i]=(short *)AllocL(l);
1726        memcpy(tmpR.wvhdl[i],r1->wvhdl[i],l);
1727      }
1728    }
1729    tmpR.OrdSgn=r1->OrdSgn;
1730  }
1731  else
1732  {
1733    for(i=0;i<k;i++) FreeL((ADDRESS)tmpR.names[i]);
1734    Free((ADDRESS)names,tmpR.N*sizeof(char *));
1735    Werror("difficulties with variables: %d,%d -> %d",r1->N,r2->N,k);
1736    return -1;
1737  }
1738  sum=(ring)Alloc(sizeof(ip_sring));
1739  memcpy(sum,&tmpR,sizeof(ip_sring));
1740  rComplete(sum);
1741  return 1;
1742}
1743
1744/*2
1745 * create a copy of the ring r, which must be equivalent to currRing
1746 * used for qring definition,..
1747 * (i.e.: normal rings: same nCopy as currRing;
1748 *        qring:        same nCopy, same idCopy as currRing)
1749 */
1750ring rCopy(ring r)
1751{
1752  if (r == NULL) return NULL;
1753  int i,j;
1754  int *pi;
1755  ring res=(ring)Alloc(sizeof(ip_sring));
1756
1757  memcpy4(res,r,sizeof(ip_sring));
1758  res->ref=0;
1759  if (r->parameter!=NULL)
1760  {
1761    res->minpoly=nCopy(r->minpoly);
1762    int l=rPar(r);
1763    res->parameter=(char **)Alloc(l*sizeof(char *));
1764    int i;
1765    for(i=0;i<rPar(r);i++)
1766    {
1767      res->parameter[i]=mstrdup(r->parameter[i]);
1768    }
1769  }
1770  res->names   = (char **)Alloc(r->N * sizeof(char *));
1771  i=1;
1772  pi=r->order;
1773  while ((*pi)!=0) { i++;pi++; }
1774  res->wvhdl   = (short **)Alloc(i * sizeof(short *));
1775  res->order   = (int *)   Alloc(i * sizeof(int));
1776  res->block0  = (int *)   Alloc(i * sizeof(int));
1777  res->block1  = (int *)   Alloc(i * sizeof(int));
1778  for (j=0; j<i; j++)
1779  {
1780    if (r->wvhdl[j]!=NULL)
1781    {
1782      res->wvhdl[j]=(short*)AllocL(mmSizeL((ADDRESS)r->wvhdl[j]));
1783      memcpy(res->wvhdl[j],r->wvhdl[j],mmSizeL((ADDRESS)r->wvhdl[j]));
1784    }
1785    else
1786      res->wvhdl[j]=NULL;
1787  }
1788  memcpy4(res->order,r->order,i * sizeof(int));
1789  memcpy4(res->block0,r->block0,i * sizeof(int));
1790  memcpy4(res->block1,r->block1,i * sizeof(int));
1791  for (i=0; i<res->N; i++)
1792  {
1793    res->names[i] = mstrdup(r->names[i]);
1794  }
1795  res->idroot = NULL;
1796  if (r->qideal!=NULL) res->qideal= idCopy(r->qideal);
1797  res->VarOffset = (int*) Alloc((r->N + 1)*sizeof(int));
1798  memcpy4(res->VarOffset, r->VarOffset, (r->N + 1)*sizeof(int));
1799
1800#ifdef RDEBUG
1801  rNumber++;
1802  res->no=rNumber;
1803#endif
1804
1805  return res;
1806}
1807
1808rOrderType_t rGetOrderType(ring r)
1809{
1810  // check for simple ordering
1811  if (rHasSimpleOrder(r))
1812  {
1813    if ((r->order[1] == ringorder_c) || (r->order[1] == ringorder_C))
1814    {
1815      switch(r->order[0])
1816      {
1817          case ringorder_dp:
1818          case ringorder_wp:
1819          case ringorder_ds:
1820          case ringorder_ws:
1821          case ringorder_ls:
1822          case ringorder_unspec:
1823            if (r->order[1] == ringorder_C ||  r->order[0] == ringorder_unspec)
1824              return rOrderType_ExpComp;
1825            return rOrderType_Exp;
1826
1827          default:
1828            assume(r->order[0] == ringorder_lp ||
1829                   r->order[0] == ringorder_Dp ||
1830                   r->order[0] == ringorder_Wp ||
1831                   r->order[0] == ringorder_Ds ||
1832                   r->order[0] == ringorder_Ws);
1833
1834            if (r->order[1] == ringorder_c) return rOrderType_ExpComp;
1835            return rOrderType_Exp;
1836      }
1837    }
1838    else
1839    {
1840      assume((r->order[0]==ringorder_c)||(r->order[0]==ringorder_C));
1841      return rOrderType_CompExp;
1842    }
1843  }
1844  else
1845    return rOrderType_General;
1846}
1847
1848BOOLEAN rHasSimpleOrder(ring r)
1849{
1850  return
1851    (r->order[0] == ringorder_unspec) ||
1852    ((r->order[2] == 0) &&
1853     (r->order[1] != ringorder_M &&
1854      r->order[0] != ringorder_M));
1855}
1856
1857// returns TRUE, if simple lp or ls ordering
1858BOOLEAN rHasSimpleLexOrder(ring r)
1859{
1860  return rHasSimpleOrder(r) &&
1861    (r->order[0] == ringorder_ls ||
1862     r->order[0] == ringorder_lp ||
1863     r->order[1] == ringorder_ls ||
1864     r->order[1] == ringorder_lp);
1865}
1866
1867BOOLEAN rIsPolyVar(int v)
1868{
1869  int  i=0;
1870  while(currRing->order[i]!=0)
1871  {
1872    if((currRing->block0[i]<=v)
1873    && (currRing->block1[i]>=v))
1874    {
1875      switch(currRing->order[i])
1876      {
1877        case ringorder_a:
1878          return (currRing->wvhdl[i][v-currRing->block0[i]]>0);
1879        case ringorder_M:
1880          return 2; /*don't know*/
1881        case ringorder_lp:
1882        case ringorder_dp:
1883        case ringorder_Dp:
1884        case ringorder_wp:
1885        case ringorder_Wp:
1886          return TRUE;
1887        case ringorder_ls:
1888        case ringorder_ds:
1889        case ringorder_Ds:
1890        case ringorder_ws:
1891        case ringorder_Ws:
1892          return FALSE;
1893        default:
1894          break;
1895      }
1896    }
1897    i++;
1898  }
1899  return 3; /* could not find var v*/
1900}
1901
1902void rUnComplete(ring r)
1903{
1904  Free((ADDRESS)r->VarOffset,(r->N + 1)*sizeof(int));
1905  r->VarOffset=NULL;
1906}
1907
1908#ifdef RDEBUG
1909// This should eventually become a full-fledge ring check, like pTest
1910BOOLEAN rDBTest(ring r, char* fn, int l)
1911{
1912  if (r == NULL)
1913  {
1914    Werror("Null ring in %s:%l\n", fn, l);
1915    return false;
1916  }
1917
1918  if (r->N == 0) return true;
1919
1920  if (r->VarOffset == NULL)
1921  {
1922    Werror("Null ring VarOffset -- no rComplete (?) in n %s:%d\n", fn, l);
1923    assume(0);
1924    return false;
1925  }
1926
1927  int
1928    VarCompIndex = r->VarCompIndex,
1929    VarLowIndex  = r->VarLowIndex,
1930    VarHighIndex = r->VarHighIndex,
1931    i;
1932  BOOLEAN ok = false;
1933  int* VarOffset = r->VarOffset;
1934
1935  rComplete(r);
1936
1937  if (   VarCompIndex != r->VarCompIndex ||
1938         VarLowIndex  != r->VarLowIndex ||
1939         VarHighIndex != r->VarHighIndex)
1940  {
1941    Werror("Wrong ring VarIndicies -- no rComplete (?) in n %s:%d\n", fn, l);
1942    assume(0);
1943    ok = FALSE;
1944  }
1945
1946  for (i=0; i<=r->N; i++)
1947  {
1948    if (VarOffset[i] != r->VarOffset[i])
1949    {
1950      Werror("Wrong VarOffset value at %d in %s:%d\n", i, fn, l);
1951      assume(0);
1952      ok = FALSE;
1953    }
1954  }
1955  Free(r->VarOffset, (r->N + 1)*sizeof(int));
1956  r->VarOffset = VarOffset;
1957  return ok;
1958}
1959#endif
Note: See TracBrowser for help on using the repository browser.