source: git/Singular/ring.cc @ 6de26a0

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