source: git/Singular/ring.cc @ 8a150b

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