source: git/Singular/longrat.cc @ 50cbdc

spielwiese
Last change on this file since 50cbdc was 50cbdc, checked in by Hans Schönemann <hannes@…>, 23 years ago
*hannes: merge-2-0-2 git-svn-id: file:///usr/local/Singular/svn/trunk@5619 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 49.0 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: longrat.cc,v 1.41 2001-08-27 14:47:09 Singular Exp $ */
5/*
6* ABSTRACT: computation with long rational numbers (Hubert Grassmann)
7*/
8
9#ifndef LONGRAT_CC
10#define LONGRAT_CC
11
12#include <string.h>
13#include <float.h>
14#include "mod2.h"
15#include "tok.h"
16#include "omalloc.h"
17#include "febase.h"
18#include "numbers.h"
19#include "modulop.h"
20#include "ring.h"
21#include "shortfl.h"
22#include "mpr_complex.h"
23#include "longrat.h"
24
25
26#ifndef BYTES_PER_MP_LIMB
27#ifdef HAVE_LIBGMP2
28#define BYTES_PER_MP_LIMB sizeof(mp_limb_t)
29#else
30#define BYTES_PER_MP_LIMB sizeof(mp_limb)
31#endif
32#endif
33
34/*-----------------------------------------------------------------*/
35/*3
36* parameter s in number:
37* 0 (or FALSE): not normalised rational
38* 1 (or TRUE):  normalised rational
39* 3          :  integer with n==NULL
40*/
41/*3
42**  'SR_INT' is the type of those integers small enough to fit into  29  bits.
43**  Therefor the value range of this small integers is: $-2^{28}...2^{28}-1$.
44**
45**  Small integers are represented by an immediate integer handle, containing
46**  the value instead of pointing  to  it,  which  has  the  following  form:
47**
48**      +-------+-------+-------+-------+- - - -+-------+-------+-------+
49**      | guard | sign  | bit   | bit   |       | bit   | tag   | tag   |
50**      | bit   | bit   | 27    | 26    |       | 0     | 0     | 1     |
51**      +-------+-------+-------+-------+- - - -+-------+-------+-------+
52**
53**  Immediate integers handles carry the tag 'SR_INT', i.e. the last bit is 1.
54**  This distuingishes immediate integers from other handles which  point  to
55**  structures aligned on 4 byte boundaries and therefor have last bit  zero.
56**  (The second bit is reserved as tag to allow extensions of  this  scheme.)
57**  Using immediates as pointers and dereferencing them gives address errors.
58**
59**  To aid overflow check the most significant two bits must always be equal,
60**  that is to say that the sign bit of immediate integers has a  guard  bit.
61**
62**  The macros 'INT_TO_SR' and 'SR_TO_INT' should be used to convert  between
63**  a small integer value and its representation as immediate integer handle.
64**
65**  Large integers and rationals are represented by z and n
66**  where n may be undefined (if s==3)
67**  NULL represents only deleted values
68*/
69#define SR_HDL(A) ((long)(A))
70/*#define SR_INT    1*/
71/*#define INT_TO_SR(INT)  ((number) (((long)INT << 2) + SR_INT))*/
72// #define SR_TO_INT(SR)   (((long)SR) >> 2)
73
74#define MP_SMALL 1
75//#define mpz_isNeg(A) (mpz_cmp_si(A,(long)0)<0)
76#ifdef HAVE_LIBGMP1
77#define mpz_isNeg(A) ((A)->size<0)
78#define mpz_limb_size(A) ((A)->size)
79#define mpz_limb_d(A) ((A)->d)
80#define MPZ_DIV(A,B,C) mpz_div((A),(B),(C))
81#define MPZ_EXACTDIV(A,B,C) mpz_div((A),(B),(C))
82#else
83#define mpz_isNeg(A) ((A)->_mp_size<0)
84#define mpz_limb_size(A) ((A)->_mp_size)
85#define mpz_limb_d(A) ((A)->_mp_d)
86#define MPZ_DIV(A,B,C) mpz_tdiv_q((A),(B),(C))
87#ifdef HAVE_SMALLGMP
88#define MPZ_EXACTDIV(A,B,C) mpz_tdiv_q((A),(B),(C))
89#else
90#define MPZ_EXACTDIV(A,B,C) mpz_divexact((A),(B),(C))
91#endif
92#define nlGmpSimple(A)
93#endif
94
95#ifdef LDEBUG
96#define nlTest(a) nlDBTest(a,__FILE__,__LINE__)
97BOOLEAN nlDBTest(number a, char *f,int l);
98#else
99#define nlTest(a) ((void)0)
100#endif
101
102
103/***************************************************************
104 *
105 * Routines which are never inlined by p_Numbers.h
106 *
107 *******************************************************************/
108#ifndef P_NUMBERS_H
109
110omBin rnumber_bin = omGetSpecBin(sizeof(rnumber));
111
112number nlOne=nlInit(1);
113
114static int nlPrimeM;
115static number nlMapP(number from)
116{
117  number to;
118  int save=npPrimeM;
119  npPrimeM=nlPrimeM;
120  to = nlInit(npInt(from));
121  npPrimeM=save;
122  return to;
123}
124
125static number nlMapLongR(number from);
126static number nlMapR(number from);
127
128nMapFunc nlSetMap(ring src, ring dst)
129{
130  if (rField_is_Q(src))
131  {
132    return nlCopy;
133  }
134  if (rField_is_Zp(src))
135  {
136    nlPrimeM=rChar(src);
137    return nlMapP;
138  }
139  if (rField_is_R(src))
140  {
141    return nlMapR;
142  }
143  if (rField_is_long_R(src))
144  {
145    return nlMapLongR; /* long R -> Q */
146  }
147  return NULL;
148}
149
150#ifdef LDEBUG
151BOOLEAN nlDBTest(number a, char *f,int l)
152{
153  if (a==NULL)
154  {
155    Print("!!longrat: NULL in %s:%d\n",f,l);
156    return FALSE;
157  }
158  //if ((int)a==1) Print("!! 0x1 as number ? %s %d\n",f,l);
159  if ((((int)a)&3)==3)
160  {
161    Print(" !!longrat:ptr(3) in %s:%d\n",f,l);
162    return FALSE;
163  }
164  if ((((int)a)&3)==1)
165  {
166    if (((((int)a)<<1)>>1)!=((int)a))
167    {
168      Print(" !!longrat:arith:%x in %s:%d\n",(int)a, f,l);
169      return FALSE;
170    }
171    return TRUE;
172  }
173  omCheckIf(omCheckAddrSize(a,sizeof(*a)), return FALSE);
174  if (a->debug!=123456)
175  {
176    Print("!!longrat:debug:%d in %s:%d\n",a->debug,f,l);
177    a->debug=123456;
178    return FALSE;
179  }
180  if ((a->s<0)||(a->s>4))
181  {
182    Print("!!longrat:s=%d in %s:%d\n",a->s,f,l);
183    return FALSE;
184  }
185#ifdef HAVE_LIBGMP2
186  omCheckAddrSize(a->z._mp_d,a->z._mp_alloc*BYTES_PER_MP_LIMB);
187  if (a->z._mp_alloc==0)
188#else
189  omCheckIf(omCheckAddrSize(a->z.d,a->z.alloc*BYTES_PER_MP_LIMB), return FALSE);
190  if(a->z.alloc==0)
191#endif
192    Print("!!longrat:z->alloc=0 in %s:%l\n",f,l);
193
194  if (a->s<2)
195  {
196#ifdef HAVE_LIBGMP2
197    omCheckIf(omCheckAddrSize(a->n._mp_d,a->n._mp_alloc*BYTES_PER_MP_LIMB), return FALSE);
198    if (a->z._mp_alloc==0)
199#else
200    omCheckIf(omCheckAddrSize(a->n.d,a->n.alloc*BYTES_PER_MP_LIMB), return FALSE);
201    if(a->z.alloc==0)
202#endif
203      Print("!!longrat:n->alloc=0 in %s:%l\n",f,l);
204    if (mpz_cmp_si(&a->n,(long)1)==0)
205    {
206      Print("!!longrat:integer as rational in %s:%d\n",f,l);
207      mpz_clear(&a->n);
208      a->s=3;
209      return FALSE;
210    }
211    else if (mpz_isNeg(&a->n))
212    {
213      Print("!!longrat:div. by negative in %s:%d\n",f,l);
214      mpz_neg(&a->z,&a->z);
215      mpz_neg(&a->n,&a->n);
216      return FALSE;
217    }
218    return TRUE;
219  }
220  if (a->s==2)
221  {
222    Print("!!longrat:s=2 in %s:%d\n",f,l);
223    return FALSE;
224  }
225  if (mpz_size1(&a->z)>MP_SMALL) return TRUE;
226  int ui=(int)mpz_get_si(&a->z);
227  if ((((ui<<3)>>3)==ui)
228  && (mpz_cmp_si(&a->z,(long)ui)==0))
229  {
230    Print("!!longrat:im int %d in %s:%d\n",ui,f,l);
231    f=NULL;
232    return FALSE;
233  }
234  return TRUE;
235}
236#endif
237
238
239number nlRInit (int i);
240
241number nlInit (number u)
242{
243  if (u->s == 3 && mpz_size1(&u->z)<=MP_SMALL)
244  {
245    int ui=(int)mpz_get_si(&u->z);
246    if ((((ui<<3)>>3)==ui)
247        && (mpz_cmp_si(&u->z,(long)ui)==0))
248    {
249      mpz_clear(&u->z);
250      omFreeBin((ADDRESS)u, rnumber_bin);
251      return INT_TO_SR(ui);
252    }
253  }
254  return u;
255}
256
257static number nlMapR(number from)
258{
259  double f=nrFloat(from);
260  if (f==0.0) return nlInit(0);
261  int f_sign=1;
262  if (f<0.0)
263  {
264    f_sign=-1;
265    f=-f;
266  }
267  int i=0;
268  mpz_t h1;
269  mpz_init_set_ui(h1,1);
270  while((FLT_RADIX*f) < DBL_MAX && i<DBL_MANT_DIG)
271  {
272    f*=FLT_RADIX;
273    mpz_mul_ui(h1,h1,FLT_RADIX);
274    i++;
275  }
276  number r=nlRInit(1);
277  mpz_set_d(&(r->z),f);
278  memcpy(&(r->n),&h1,sizeof(h1));
279  r->s=0; /* not normalized */
280  nlNormalize(r);
281  return r;
282}
283
284static number nlMapLongR(number from)
285{
286  gmp_float *ff=(gmp_float*)from;
287  mpf_t *f=ff->_mpfp();
288  number res;
289  lint *dest,*ndest;
290  int size, i,negative;
291  int e,al,bl;
292  mp_ptr qp,dd,nn;
293
294  size = (*f)[0]._mp_size;
295  if (size == 0)
296    return nlInit(0);
297  if(size<0)
298  {
299    negative = 1;
300    size = -size;
301  }
302  else
303    negative = 0;
304
305  qp = (*f)[0]._mp_d;
306  while(qp[0]==0)
307  {
308    qp++;
309    size--;
310  }
311
312  e=(*f)[0]._mp_exp-size;
313  res = (number)omAllocBin(rnumber_bin);
314#if defined(LDEBUG)
315  res->debug=123456;
316#endif
317  dest = &(res->z);
318
319  if (e<0)
320  {
321    al = dest->_mp_size = size;
322    if (al<2) al = 2;
323    dd = (mp_ptr)omAlloc(sizeof(mp_limb_t)*al);
324    for (i=0;i<size;i++) dd[i] = qp[i];
325    bl = 1-e;
326    nn = (mp_ptr)omAlloc(sizeof(mp_limb_t)*bl);
327    nn[bl-1] = 1;
328    for (i=bl-2;i>=0;i--) nn[i] = 0;
329    ndest = &(res->n);
330    ndest->_mp_d = nn;
331    ndest->_mp_alloc = ndest->_mp_size = bl;
332    res->s = 0;
333  }
334  else
335  {
336    al = dest->_mp_size = size+e;
337    if (al<2) al = 2;
338    dd = (mp_ptr)omAlloc(sizeof(mp_limb_t)*al);
339    for (i=0;i<size;i++) dd[i+e] = qp[i];
340    for (i=0;i<e;i++) dd[i] = 0;
341    res->s = 3;
342  }
343
344  dest->_mp_d = dd;
345  dest->_mp_alloc = al;
346  if (negative) dest->_mp_size = -dest->_mp_size;
347
348  if (res->s==0)
349    nlNormalize(res);
350  else if (mpz_size1(&res->z)<=MP_SMALL)
351  {
352    int ui=(int)mpz_get_si(&res->z);
353    if ((((ui<<3)>>3)==ui)
354       && (mpz_cmp_si(&res->z,(long)ui)==0))
355    {
356       mpz_clear(&res->z);
357       omFreeBin((ADDRESS)res, rnumber_bin);
358       return INT_TO_SR(ui);
359    }
360  }
361#if defined(LDEBUG)
362  nlTest(res);
363#endif
364  return res;
365}
366
367//static number nlMapLongR(number from)
368//{
369//  gmp_float *ff=(gmp_float*)from;
370//  const mpf_t *f=ff->mpfp();
371//  int f_size=ABS((*f)[0]._mp_size);
372//  if (f_size==0)
373//    return nlInit(0);
374//  int f_sign=1;
375//  number work=ngcCopy(from);
376//  if (!ngcGreaterZero(work))
377//  {
378//    f_sign=-1;
379//    work=ngcNeg(work);
380//  }
381//  int i=0;
382//  mpz_t h1;
383//  mpz_init_set_ui(h1,1);
384//  while((FLT_RADIX*f) < DBL_MAX && i<DBL_MANT_DIG)
385//  {
386//    f*=FLT_RADIX;
387//    mpz_mul_ui(h1,h1,FLT_RADIX);
388//    i++;
389//  }
390//  number r=nlRInit(1);
391//  mpz_set_d(&(r->z),f);
392//  memcpy(&(r->n),&h1,sizeof(h1));
393//  r->s=0; /* not normalized */
394//  nlNormalize(r);
395//  return r;
396//
397//
398//  number r=nlRInit(1);
399//  int f_shift=f_size+(*f)[0]._mp_exp;
400//  if ( f_shift > 0)
401//  {
402//    r->s=0;
403//    mpz_init(&r->n);
404//    mpz_setbit(&r->n,f_shift*BYTES_PER_MP_LIMB*8);
405//    mpz_setbit(&r->z,f_size*BYTES_PER_MP_LIMB*8-1);
406//    // now r->z has enough space
407//    memcpy(mpz_limb_d(&r->z),((*f)[0]._mp_d),f_size*BYTES_PER_MP_LIMB);
408//    nlNormalize(r);
409//  }
410//  else
411//  {
412//    r->s=3;
413//    if (f_shift==0)
414//    {
415//      mpz_setbit(&r->z,f_size*BYTES_PER_MP_LIMB*8-1);
416//      // now r->z has enough space
417//      memcpy(mpz_limb_d(&r->z),((*f)[0]._mp_d),f_size*BYTES_PER_MP_LIMB);
418//    }
419//    else /* f_shift < 0 */
420//    {
421//      mpz_setbit(&r->z,(f_size-f_shift)*BYTES_PER_MP_LIMB*8-1);
422//      // now r->z has enough space
423//      memcpy(mpz_limb_d(&r->z)-f_shift,((*f)[0]._mp_d),
424//        f_size*BYTES_PER_MP_LIMB);
425//    }
426//  }
427//  if ((*f)[0]._mp_size<0);
428//    r=nlNeg(r);
429//  return r;
430//}
431
432int nlSize(number a)
433{
434  if (a==INT_TO_SR(0))
435     return 0; /* rational 0*/
436  if (SR_HDL(a) & SR_INT)
437     return 1; /* immidiate int */
438#ifdef HAVE_LIBGMP2
439  int s=a->z._mp_alloc;
440#else
441  int s=a->z.alloc;
442#endif
443  if (a->s<2)
444  {
445#ifdef HAVE_LIBGMP2
446    s+=a->n._mp_alloc;
447#else
448    s+=a->n.alloc;
449#endif
450  }
451  return s;
452}
453
454/*
455* delete leading 0s from a gmp number
456*/
457#ifdef HAVE_LIBGMP1
458static void nlGmpSimple(MP_INT *z)
459{
460  int k;
461  if (mpz_limb_size(z)<0)
462  {
463    k=-mpz_limb_size(z)-1;
464    while ((k>0) && (mpz_limb_d(z)[k]==0))
465    { k--;printf("X"); }
466    k++;
467    mpz_limb_size(z)=-k;
468  }
469  else
470  {
471    k=mpz_limb_size(z)-1;
472    while ((k>0) && (mpz_limb_d(z)[k]==0))
473    { k--;printf("X"); }
474    k++;
475    mpz_limb_size(z)=k;
476  }
477}
478#endif
479
480/*2
481* convert number to int
482*/
483int nlInt(number &i)
484{
485#ifdef LDEBUG
486  nlTest(i);
487#endif
488  nlNormalize(i);
489  if (SR_HDL(i) &SR_INT) return SR_TO_INT(i);
490  nlGmpSimple(&i->z);
491  if (i->s==3)
492  {
493    if(mpz_size1(&i->z)>MP_SMALL) return 0;
494    int ul=(int)mpz_get_si(&i->z);
495    if (mpz_cmp_si(&i->z,(long)ul)!=0) return 0;
496    return ul;
497  }
498  lint tmp;
499  int ul;
500  mpz_init(&tmp);
501  MPZ_DIV(&tmp,&i->z,&i->n);
502  if(mpz_size1(&tmp)>MP_SMALL) ul=0;
503  else
504  {
505    ul=(int)mpz_get_si(&tmp);
506    if (mpz_cmp_si(&tmp,(long)ul)!=0) ul=0;
507  }
508  mpz_clear(&tmp);
509  return ul;
510}
511
512/*
513* 1/a
514*/
515number nlInvers(number a)
516{
517#ifdef LDEBUG
518  nlTest(a);
519#endif
520  number n;
521  if (SR_HDL(a) & SR_INT)
522  {
523    if ((a==INT_TO_SR(1)) || (a==INT_TO_SR(-1)))
524    {
525      return a;
526    }
527    if (nlIsZero(a))
528    {
529      WerrorS("div. 1/0");
530      return INT_TO_SR(0);
531    }
532    n=(number)omAllocBin(rnumber_bin);
533#if defined(LDEBUG)
534    n->debug=123456;
535#endif
536    n->s=1;
537    if ((int)a>0)
538    {
539      mpz_init_set_si(&n->z,(long)1);
540      mpz_init_set_si(&n->n,(long)SR_TO_INT(a));
541    }
542    else
543    {
544      mpz_init_set_si(&n->z,(long)-1);
545      mpz_init_set_si(&n->n,(long)-SR_TO_INT(a));
546#ifdef LDEBUG
547    nlTest(n);
548#endif
549    }
550#ifdef LDEBUG
551    nlTest(n);
552#endif
553    return n;
554  }
555  n=(number)omAllocBin(rnumber_bin);
556#if defined(LDEBUG)
557  n->debug=123456;
558#endif
559  {
560    n->s=a->s;
561    mpz_init_set(&n->n,&a->z);
562    switch (a->s)
563    {
564      case 0:
565      case 1:
566              mpz_init_set(&n->z,&a->n);
567              if (mpz_isNeg(&n->n)) /* && n->s<2*/
568              {
569                mpz_neg(&n->z,&n->z);
570                mpz_neg(&n->n,&n->n);
571              }
572              if (mpz_cmp_si(&n->n,(long)1)==0)
573              {
574                mpz_clear(&n->n);
575                n->s=3;
576                if (mpz_size1(&n->z)<=MP_SMALL)
577                {
578                  int ui=(int)mpz_get_si(&n->z);
579                  if ((((ui<<3)>>3)==ui)
580                  && (mpz_cmp_si(&n->z,(long)ui)==0))
581                  {
582                    mpz_clear(&n->z);
583                    omFreeBin((ADDRESS)n, rnumber_bin);
584                    n=INT_TO_SR(ui);
585                  }
586                }
587              }
588              break;
589      case 3:
590              n->s=1;
591              if (mpz_isNeg(&n->n)) /* && n->s<2*/
592              {
593                mpz_neg(&n->n,&n->n);
594                mpz_init_set_si(&n->z,(long)-1);
595              }
596              else
597              {
598                mpz_init_set_si(&n->z,(long)1);
599              }
600              break;
601    }
602  }
603#ifdef LDEBUG
604  nlTest(n);
605#endif
606  return n;
607}
608
609
610/*2
611* u := a / b in Z, if b | a (else undefined)
612*/
613number   nlExactDiv(number a, number b)
614{
615  if (b==INT_TO_SR(0))
616  {
617    WerrorS("div. by 0");
618    return INT_TO_SR(0);
619  }
620  if (a==INT_TO_SR(0))
621    return INT_TO_SR(0);
622  number u;
623  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
624  {
625    /* the small int -(1<<28) divided by -1 is the large int (1<<28)   */
626    if ((a==INT_TO_SR(-(1<<28)))&&(b==INT_TO_SR(-1)))
627    {
628      return nlRInit(1<<28);
629    }
630    int aa=SR_TO_INT(a);
631    int bb=SR_TO_INT(b);
632    return INT_TO_SR(aa/bb);
633  }
634  number bb=NULL;
635  if (SR_HDL(b) & SR_INT)
636  {
637    bb=nlRInit(SR_TO_INT(b));
638    b=bb;
639  }
640  u=(number)omAllocBin(rnumber_bin);
641#if defined(LDEBUG)
642  u->debug=123456;
643#endif
644  mpz_init(&u->z);
645  /* u=a/b */
646  u->s = 3;
647  MPZ_EXACTDIV(&u->z,&a->z,&b->z);
648  if (bb!=NULL)
649  {
650    mpz_clear(&bb->z);
651    omFreeBin((ADDRESS)bb, rnumber_bin);
652  }
653  if (mpz_size1(&u->z)<=MP_SMALL)
654  {
655    int ui=(int)mpz_get_si(&u->z);
656    if ((((ui<<3)>>3)==ui)
657    && (mpz_cmp_si(&u->z,(long)ui)==0))
658    {
659      mpz_clear(&u->z);
660      omFreeBin((ADDRESS)u, rnumber_bin);
661      u=INT_TO_SR(ui);
662    }
663  }
664#ifdef LDEBUG
665  nlTest(u);
666#endif
667  return u;
668}
669
670/*2
671* u := a / b in Z
672*/
673number nlIntDiv (number a, number b)
674{
675  if (b==INT_TO_SR(0))
676  {
677    WerrorS("div. by 0");
678    return INT_TO_SR(0);
679  }
680  if (a==INT_TO_SR(0))
681    return INT_TO_SR(0);
682  number u;
683  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
684  {
685    /* the small int -(1<<28) divided by -1 is the large int (1<<28)   */
686    if ((a==INT_TO_SR(-(1<<28)))&&(b==INT_TO_SR(-1)))
687    {
688      return nlRInit(1<<28);
689    }
690    /* consider the signs of a and b:
691    *  + + -> u=a+b-1
692    *  + - -> u=a-b-1
693    *  - + -> u=a-b+1
694    *  - - -> u=a+b+1
695    */
696    int aa=SR_TO_INT(a);
697    int bb=SR_TO_INT(b);
698    if (aa>0)
699    {
700      if (bb>0)
701        return INT_TO_SR((aa+bb-1)/bb);
702      else
703        return INT_TO_SR((aa-bb-1)/bb);
704    }
705    else
706    {
707      if (bb>0)
708      {
709        return INT_TO_SR((aa-bb+1)/bb);
710      }
711      else
712      {
713        return INT_TO_SR((aa+bb+1)/bb);
714      }
715    }
716  }
717  if (SR_HDL(a) & SR_INT)
718  {
719    /* the small int -(1<<28) divided by 2^28 is 1   */
720    if (a==INT_TO_SR(-(1<<28)))
721    {
722      if(mpz_cmp_si(&b->z,(long)(1<<28))==0)
723      {
724        return INT_TO_SR(-1);
725      }
726    }
727    /* a is a small and b is a large int: -> 0 */
728    return INT_TO_SR(0);
729  }
730  number bb=NULL;
731  if (SR_HDL(b) & SR_INT)
732  {
733    bb=nlRInit(SR_TO_INT(b));
734    b=bb;
735  }
736  u=(number)omAllocBin(rnumber_bin);
737#if defined(LDEBUG)
738  u->debug=123456;
739#endif
740  mpz_init_set(&u->z,&a->z);
741  /* consider the signs of a and b:
742  *  + + -> u=a+b-1
743  *  + - -> u=a-b-1
744  *  - + -> u=a-b+1
745  *  - - -> u=a+b+1
746  */
747  if (mpz_isNeg(&a->z))
748  {
749    if (mpz_isNeg(&b->z))
750    {
751      mpz_add(&u->z,&u->z,&b->z);
752    }
753    else
754    {
755      mpz_sub(&u->z,&u->z,&b->z);
756    }
757    mpz_add_ui(&u->z,&u->z,1);
758  }
759  else
760  {
761    if (mpz_isNeg(&b->z))
762    {
763      mpz_sub(&u->z,&u->z,&b->z);
764    }
765    else
766    {
767      mpz_add(&u->z,&u->z,&b->z);
768    }
769    mpz_sub_ui(&u->z,&u->z,1);
770  }
771  /* u=u/b */
772  u->s = 3;
773  MPZ_DIV(&u->z,&u->z,&b->z);
774  nlGmpSimple(&u->z);
775  if (bb!=NULL)
776  {
777    mpz_clear(&bb->z);
778    omFreeBin((ADDRESS)bb, rnumber_bin);
779  }
780  if (mpz_size1(&u->z)<=MP_SMALL)
781  {
782    int ui=(int)mpz_get_si(&u->z);
783    if ((((ui<<3)>>3)==ui)
784    && (mpz_cmp_si(&u->z,(long)ui)==0))
785    {
786      mpz_clear(&u->z);
787      omFreeBin((ADDRESS)u, rnumber_bin);
788      u=INT_TO_SR(ui);
789    }
790  }
791#ifdef LDEBUG
792  nlTest(u);
793#endif
794  return u;
795}
796
797/*2
798* u := a mod b in Z, u>=0
799*/
800number nlIntMod (number a, number b)
801{
802  if (b==INT_TO_SR(0))
803  {
804    WerrorS("div. by 0");
805    return INT_TO_SR(0);
806  }
807  if (a==INT_TO_SR(0))
808    return INT_TO_SR(0);
809  number u;
810  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
811  {
812    if ((int)a>0)
813    {
814      if ((int)b>0)
815        return INT_TO_SR(SR_TO_INT(a)%SR_TO_INT(b));
816      else
817        return INT_TO_SR(SR_TO_INT(a)%(-SR_TO_INT(b)));
818    }
819    else
820    {
821      if ((int)b>0)
822      {
823        int i=(-SR_TO_INT(a))%SR_TO_INT(b);
824        if ( i != 0 ) i = (SR_TO_INT(b))-i;
825        return INT_TO_SR(i);
826      }
827      else
828      {
829        int i=(-SR_TO_INT(a))%(-SR_TO_INT(b));
830        if ( i != 0 ) i = (-SR_TO_INT(b))-i;
831        return INT_TO_SR(i);
832      }
833    }
834  }
835  if (SR_HDL(a) & SR_INT)
836  {
837    /* a is a small and b is a large int: -> a or (a+b) or (a-b) */
838    if ((int)a<0)
839    {
840      if (mpz_isNeg(&b->z))
841        return nlSub(a,b);
842      /*else*/
843        return nlAdd(a,b);
844    }
845    /*else*/
846      return a;
847  }
848  number bb=NULL;
849  if (SR_HDL(b) & SR_INT)
850  {
851    bb=nlRInit(SR_TO_INT(b));
852    b=bb;
853  }
854  u=(number)omAllocBin(rnumber_bin);
855#if defined(LDEBUG)
856  u->debug=123456;
857#endif
858  mpz_init(&u->z);
859  u->s = 3;
860  mpz_mod(&u->z,&a->z,&b->z);
861  if (bb!=NULL)
862  {
863    mpz_clear(&bb->z);
864    omFreeBin((ADDRESS)bb, rnumber_bin);
865  }
866  if (mpz_isNeg(&u->z))
867  {
868    if (mpz_isNeg(&b->z))
869      mpz_sub(&u->z,&u->z,&b->z);
870    else
871      mpz_add(&u->z,&u->z,&b->z);
872  }
873  nlGmpSimple(&u->z);
874  if (mpz_size1(&u->z)<=MP_SMALL)
875  {
876    int ui=(int)mpz_get_si(&u->z);
877    if ((((ui<<3)>>3)==ui)
878    && (mpz_cmp_si(&u->z,(long)ui)==0))
879    {
880      mpz_clear(&u->z);
881      omFreeBin((ADDRESS)u, rnumber_bin);
882      u=INT_TO_SR(ui);
883    }
884  }
885#ifdef LDEBUG
886  nlTest(u);
887#endif
888  return u;
889}
890
891/*2
892* u := a / b
893*/
894number nlDiv (number a, number b)
895{
896  number u;
897  if (nlIsZero(b))
898  {
899    WerrorS("div. by 0");
900    return INT_TO_SR(0);
901  }
902  u=(number)omAllocBin(rnumber_bin);
903  u->s=0;
904#if defined(LDEBUG)
905  u->debug=123456;
906#endif
907// ---------- short / short ------------------------------------
908  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
909  {
910    int i=SR_TO_INT(a);
911    int j=SR_TO_INT(b);
912    int r=i%j;
913    if (r==0)
914    {
915      omFreeBin((ADDRESS)u, rnumber_bin);
916      return INT_TO_SR(i/j);
917    }
918    mpz_init_set_si(&u->z,(long)i);
919    mpz_init_set_si(&u->n,(long)j);
920  }
921  else
922  {
923    mpz_init(&u->z);
924// ---------- short / long ------------------------------------
925    if (SR_HDL(a) & SR_INT)
926    {
927      // short a / (z/n) -> (a*n)/z
928      if (b->s<2)
929      {
930        if ((int)a>=0)
931          mpz_mul_ui(&u->z,&b->n,SR_TO_INT(a));
932        else
933        {
934          mpz_mul_ui(&u->z,&b->n,-SR_TO_INT(a));
935          mpz_neg(&u->z,&u->z);
936        }
937      }
938      else
939      // short a / long z -> a/z
940      {
941        mpz_set_si(&u->z,SR_TO_INT(a));
942      }
943      if (mpz_cmp(&u->z,&b->z)==0)
944      {
945        mpz_clear(&u->z);
946        omFreeBin((ADDRESS)u, rnumber_bin);
947        return INT_TO_SR(1);
948      }
949      mpz_init_set(&u->n,&b->z);
950    }
951// ---------- long / short ------------------------------------
952    else if (SR_HDL(b) & SR_INT)
953    {
954      mpz_set(&u->z,&a->z);
955      // (z/n) / b -> z/(n*b)
956      if (a->s<2)
957      {
958        mpz_init_set(&u->n,&a->n);
959        if ((int)b>0)
960          mpz_mul_ui(&u->n,&u->n,SR_TO_INT(b));
961        else
962        {
963          mpz_mul_ui(&u->n,&u->n,-SR_TO_INT(b));
964          mpz_neg(&u->z,&u->z);
965        }
966      }
967      else
968      // long z / short b -> z/b
969      {
970        //mpz_set(&u->z,&a->z);
971        mpz_init_set_si(&u->n,SR_TO_INT(b));
972      }
973    }
974// ---------- long / long ------------------------------------
975    else
976    {
977      //u->s=0;
978      mpz_set(&u->z,&a->z);
979      mpz_init_set(&u->n,&b->z);
980      if (a->s<2) mpz_mul(&u->n,&u->n,&a->n);
981      if (b->s<2) mpz_mul(&u->z,&u->z,&b->n);
982    }
983  }
984  if (mpz_isNeg(&u->n))
985  {
986    mpz_neg(&u->z,&u->z);
987    mpz_neg(&u->n,&u->n);
988  }
989  if (mpz_cmp_si(&u->n,(long)1)==0)
990  {
991    mpz_clear(&u->n);
992    if (mpz_size1(&u->z)<=MP_SMALL)
993    {
994      int ui=(int)mpz_get_si(&u->z);
995      if ((((ui<<3)>>3)==ui)
996      && (mpz_cmp_si(&u->z,(long)ui)==0))
997      {
998        mpz_clear(&u->z);
999        omFreeBin((ADDRESS)u, rnumber_bin);
1000        return INT_TO_SR(ui);
1001      }
1002    }
1003    u->s=3;
1004  }
1005#ifdef LDEBUG
1006  nlTest(u);
1007#endif
1008  return u;
1009}
1010
1011#if (defined(i386)) && (defined(HAVE_LIBGMP1))
1012/*
1013* compute x^exp for x in Z
1014* there seems to be an bug in mpz_pow_ui for i386
1015*/
1016static inline void nlPow (MP_INT * res,MP_INT * x,int exp)
1017{
1018  if (exp==0)
1019  {
1020    mpz_set_si(res,(long)1);
1021  }
1022  else
1023  {
1024    MP_INT xh;
1025    mpz_init(&xh);
1026    mpz_set(res,x);
1027    exp--;
1028    while (exp!=0)
1029    {
1030      mpz_mul(&xh,res,x);
1031      mpz_set(res,&xh);
1032      exp--;
1033    }
1034    mpz_clear(&xh);
1035  }
1036}
1037#endif
1038
1039/*2
1040* u:= x ^ exp
1041*/
1042void nlPower (number x,int exp,number * u)
1043{
1044  if (!nlIsZero(x))
1045  {
1046#ifdef LDEBUG
1047    nlTest(x);
1048#endif
1049    number aa=NULL;
1050    if (SR_HDL(x) & SR_INT)
1051    {
1052      aa=nlRInit(SR_TO_INT(x));
1053      x=aa;
1054    }
1055    *u=(number)omAllocBin(rnumber_bin);
1056#if defined(LDEBUG)
1057    (*u)->debug=123456;
1058#endif
1059    mpz_init(&(*u)->z);
1060    (*u)->s = x->s;
1061#if (!defined(i386)) || (defined(HAVE_LIBGMP2))
1062    mpz_pow_ui(&(*u)->z,&x->z,(unsigned long)exp);
1063#else
1064    nlPow(&(*u)->z,&x->z,exp);
1065#endif
1066    if (x->s<2)
1067    {
1068      mpz_init(&(*u)->n);
1069#if (!defined(i386)) || (defined(HAVE_LIBGMP2))
1070      mpz_pow_ui(&(*u)->n,&x->n,(unsigned long)exp);
1071#else
1072      nlPow(&(*u)->n,&x->n,exp);
1073#endif
1074    }
1075    if (aa!=NULL)
1076    {
1077      mpz_clear(&aa->z);
1078      omFreeBin((ADDRESS)aa, rnumber_bin);
1079    }
1080    if (((*u)->s<=2) && (mpz_cmp_si(&(*u)->n,(long)1)==0))
1081    {
1082      mpz_clear(&(*u)->n);
1083      (*u)->s=3;
1084    }
1085    if (((*u)->s==3) && (mpz_size1(&(*u)->z)<=MP_SMALL))
1086    {
1087      int ui=(int)mpz_get_si(&(*u)->z);
1088      if ((((ui<<3)>>3)==ui)
1089      && (mpz_cmp_si(&(*u)->z,(long)ui)==0))
1090      {
1091        mpz_clear(&(*u)->z);
1092        omFreeBin((ADDRESS)*u, rnumber_bin);
1093        *u=INT_TO_SR(ui);
1094      }
1095    }
1096  }
1097  else
1098    *u = INT_TO_SR(0);
1099#ifdef LDEBUG
1100  nlTest(*u);
1101#endif
1102}
1103
1104
1105/*2
1106* za >= 0 ?
1107*/
1108BOOLEAN nlGreaterZero (number a)
1109{
1110#ifdef LDEBUG
1111  nlTest(a);
1112#endif
1113  if (SR_HDL(a) & SR_INT) return SR_HDL(a)>=0;
1114  return (!mpz_isNeg(&a->z));
1115}
1116
1117/*2
1118* a > b ?
1119*/
1120BOOLEAN nlGreater (number a, number b)
1121{
1122#ifdef LDEBUG
1123  nlTest(a);
1124  nlTest(b);
1125#endif
1126  number r;
1127  BOOLEAN rr;
1128  r=nlSub(a,b);
1129  rr=(!nlIsZero(r)) && (nlGreaterZero(r));
1130  nlDelete(&r,currRing);
1131  return rr;
1132}
1133
1134/*2
1135* a == -1 ?
1136*/
1137BOOLEAN nlIsMOne (number a)
1138{
1139#ifdef LDEBUG
1140  if (a==NULL) return FALSE;
1141  nlTest(a);
1142#endif
1143  if (SR_HDL(a) & SR_INT) return (a==INT_TO_SR(-1));
1144  return FALSE;
1145}
1146
1147/*2
1148* result =gcd(a,b)
1149*/
1150number nlGcd(number a, number b, const ring r)
1151{
1152  number result;
1153#ifdef LDEBUG
1154  nlTest(a);
1155  nlTest(b);
1156#endif
1157  //nlNormalize(a);
1158  //nlNormalize(b);
1159  if ((SR_HDL(a)==5)||(a==INT_TO_SR(-1))
1160  ||  (SR_HDL(b)==5)||(b==INT_TO_SR(-1))) return INT_TO_SR(1);
1161  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
1162  {
1163    int i=SR_TO_INT(a);
1164    int j=SR_TO_INT(b);
1165    if((i==0)||(j==0))
1166      return INT_TO_SR(1);
1167    int l;
1168    i=ABS(i);
1169    j=ABS(j);
1170    do
1171    {
1172      l=i%j;
1173      i=j;
1174      j=l;
1175    } while (l!=0);
1176    return INT_TO_SR(i);
1177  }
1178  if (((!(SR_HDL(a) & SR_INT))&&(a->s<2))
1179  ||  ((!(SR_HDL(b) & SR_INT))&&(b->s<2))) return INT_TO_SR(1);
1180  number aa=NULL;
1181  if (SR_HDL(a) & SR_INT)
1182  {
1183    aa=nlRInit(SR_TO_INT(a));
1184    a=aa;
1185  }
1186  else
1187  if (SR_HDL(b) & SR_INT)
1188  {
1189    aa=nlRInit(SR_TO_INT(b));
1190    b=aa;
1191  }
1192  result=(number)omAllocBin(rnumber_bin);
1193#if defined(LDEBUG)
1194  result->debug=123456;
1195#endif
1196  mpz_init(&result->z);
1197  mpz_gcd(&result->z,&a->z,&b->z);
1198  nlGmpSimple(&result->z);
1199  result->s = 3;
1200  if (mpz_size1(&result->z)<=MP_SMALL)
1201  {
1202    int ui=(int)mpz_get_si(&result->z);
1203    if ((((ui<<3)>>3)==ui)
1204    && (mpz_cmp_si(&result->z,(long)ui)==0))
1205    {
1206      mpz_clear(&result->z);
1207      omFreeBin((ADDRESS)result, rnumber_bin);
1208      result=INT_TO_SR(ui);
1209    }
1210  }
1211  if (aa!=NULL)
1212  {
1213    mpz_clear(&aa->z);
1214    omFreeBin((ADDRESS)aa, rnumber_bin);
1215  }
1216#ifdef LDEBUG
1217  nlTest(result);
1218#endif
1219  return result;
1220}
1221
1222/*2
1223* simplify x
1224*/
1225void nlNormalize (number &x)
1226{
1227  if ((SR_HDL(x) & SR_INT) ||(x==NULL))
1228    return;
1229#ifdef LDEBUG
1230  if (!nlTest(x)) return;
1231#endif
1232  if (x->s==3)
1233  {
1234    if (mpz_cmp_ui(&x->z,(long)0)==0)
1235    {
1236      nlDelete(&x,currRing);
1237      x=nlInit(0);
1238      return;
1239    }
1240    if (mpz_size1(&x->z)<=MP_SMALL)
1241    {
1242      int ui=(int)mpz_get_si(&x->z);
1243      if ((((ui<<3)>>3)==ui)
1244      && (mpz_cmp_si(&x->z,(long)ui)==0))
1245      {
1246        mpz_clear(&x->z);
1247        omFreeBin((ADDRESS)x, rnumber_bin);
1248        x=INT_TO_SR(ui);
1249        return;
1250      }
1251    }
1252  }
1253  if (x->s!=1) nlGmpSimple(&x->z);
1254  if (x->s==0)
1255  {
1256    BOOLEAN divided=FALSE;
1257    MP_INT gcd;
1258    mpz_init(&gcd);
1259    mpz_gcd(&gcd,&x->z,&x->n);
1260    x->s=1;
1261    if (mpz_cmp_si(&gcd,(long)1)!=0)
1262    {
1263      MP_INT r;
1264      mpz_init(&r);
1265      MPZ_EXACTDIV(&r,&x->z,&gcd);
1266      mpz_set(&x->z,&r);
1267      MPZ_EXACTDIV(&r,&x->n,&gcd);
1268      mpz_set(&x->n,&r);
1269      mpz_clear(&r);
1270      nlGmpSimple(&x->z);
1271      divided=TRUE;
1272    }
1273    mpz_clear(&gcd);
1274    nlGmpSimple(&x->n);
1275    if (mpz_cmp_si(&x->n,(long)1)==0)
1276    {
1277      mpz_clear(&x->n);
1278      if (mpz_size1(&x->z)<=MP_SMALL)
1279      {
1280        int ui=(int)mpz_get_si(&x->z);
1281        if ((((ui<<3)>>3)==ui)
1282        && (mpz_cmp_si(&x->z,(long)ui)==0))
1283        {
1284          mpz_clear(&x->z);
1285#if defined(LDEBUG)
1286          x->debug=654324;
1287#endif
1288          omFreeBin((ADDRESS)x, rnumber_bin);
1289          x=INT_TO_SR(ui);
1290          return;
1291        }
1292      }
1293      x->s=3;
1294    }
1295    else if (divided)
1296    {
1297      _mpz_realloc(&x->n,mpz_size1(&x->n));
1298    }
1299    if (divided) _mpz_realloc(&x->z,mpz_size1(&x->z));
1300  }
1301#ifdef LDEBUG
1302  nlTest(x);
1303#endif
1304}
1305
1306/*2
1307* returns in result->z the lcm(a->z,b->n)
1308*/
1309number nlLcm(number a, number b, const ring r)
1310{
1311  number result;
1312#ifdef LDEBUG
1313  nlTest(a);
1314  nlTest(b);
1315#endif
1316  if ((SR_HDL(b) & SR_INT)
1317  || (b->s==3))
1318  {
1319    // b is 1/(b->n) => b->n is 1 => result is a
1320    return nlCopy(a);
1321  }
1322  number aa=NULL;
1323  if (SR_HDL(a) & SR_INT)
1324  {
1325    aa=nlRInit(SR_TO_INT(a));
1326    a=aa;
1327  }
1328  result=(number)omAllocBin(rnumber_bin);
1329#if defined(LDEBUG)
1330  result->debug=123456;
1331#endif
1332  result->s=3;
1333  MP_INT gcd;
1334  mpz_init(&gcd);
1335  mpz_init(&result->z);
1336  mpz_gcd(&gcd,&a->z,&b->n);
1337  if (mpz_cmp_si(&gcd,(long)1)!=0)
1338  {
1339    MP_INT bt;
1340    mpz_init_set(&bt,&b->n);
1341    MPZ_EXACTDIV(&bt,&bt,&gcd);
1342    mpz_mul(&result->z,&a->z,&bt);
1343    mpz_clear(&bt);
1344  }
1345  else
1346    mpz_mul(&result->z,&a->z,&b->n);
1347  mpz_clear(&gcd);
1348  if (aa!=NULL)
1349  {
1350    mpz_clear(&aa->z);
1351    omFreeBin((ADDRESS)aa, rnumber_bin);
1352  }
1353  nlGmpSimple(&result->z);
1354  if (mpz_size1(&result->z)<=MP_SMALL)
1355  {
1356    int ui=(int)mpz_get_si(&result->z);
1357    if ((((ui<<3)>>3)==ui)
1358    && (mpz_cmp_si(&result->z,(long)ui)==0))
1359    {
1360      mpz_clear(&result->z);
1361      omFreeBin((ADDRESS)result, rnumber_bin);
1362      return INT_TO_SR(ui);
1363    }
1364  }
1365#ifdef LDEBUG
1366  nlTest(result);
1367#endif
1368  return result;
1369}
1370
1371int nlModP(number n, int p)
1372{
1373  if (SR_HDL(n) & SR_INT)
1374  {
1375    int i=SR_TO_INT(n);
1376    if (i<0) return (p-((-i)%p));
1377    return i%p;
1378  }
1379  int iz=mpz_mmod_ui(NULL,&n->z,(unsigned long)p);
1380  if (n->s!=3)
1381  {
1382    int in=mpz_mmod_ui(NULL,&n->n,(unsigned long)p);
1383    return (int)npDiv((number)iz,(number)in);
1384  }
1385  return iz;
1386}
1387
1388/*2
1389* acces to denominator, other 1 for integers
1390*/
1391number   nlGetDenom(number &n)
1392{
1393  if (!(SR_HDL(n) & SR_INT))
1394  {
1395    if (n->s==0)
1396    {
1397      nlNormalize(n);
1398    }
1399    if (!(SR_HDL(n) & SR_INT))
1400    {
1401      if (n->s!=3)
1402      {
1403        number u=(number)omAllocBin(rnumber_bin);
1404        u->s=3;
1405#if defined(LDEBUG)
1406        u->debug=123456;
1407#endif
1408
1409        mpz_init_set(&u->z,&n->n);
1410        {
1411          int ui=(int)mpz_get_si(&u->z);
1412          if ((((ui<<3)>>3)==ui)
1413          && (mpz_cmp_si(&u->z,(long)ui)==0))
1414          {
1415            mpz_clear(&u->z);
1416            omFreeBin((ADDRESS)u, rnumber_bin);
1417            return INT_TO_SR(ui);
1418          }
1419        }
1420        return u;
1421      }
1422    }
1423  }
1424  return INT_TO_SR(1);
1425}
1426
1427/***************************************************************
1428 *
1429 * routines which are needed by Inline(d) routines
1430 *
1431 *******************************************************************/
1432BOOLEAN _nlEqual_aNoImm_OR_bNoImm(number a, number b)
1433{
1434  assume(! (SR_HDL(a) & SR_HDL(b) & SR_INT));
1435//  long - short
1436  BOOLEAN bo;
1437  if (SR_HDL(b) & SR_INT)
1438  {
1439    if (a->s!=0) return FALSE;
1440    number n=b; b=a; a=n;
1441  }
1442//  short - long
1443  if (SR_HDL(a) & SR_INT)
1444  {
1445    if (b->s!=0)
1446      return FALSE;
1447    if (((int)a > 0) && (mpz_isNeg(&b->z)))
1448      return FALSE;
1449    if (((int)a < 0) && (!mpz_isNeg(&b->z)))
1450      return FALSE;
1451    MP_INT  bb;
1452    mpz_init_set(&bb,&b->n);
1453    if ((int)a<0)
1454    {
1455      mpz_neg(&bb,&bb);
1456      mpz_mul_ui(&bb,&bb,(long)-SR_TO_INT(a));
1457    }
1458    else
1459    {
1460      mpz_mul_ui(&bb,&bb,(long)SR_TO_INT(a));
1461    }
1462    bo=(mpz_cmp(&bb,&b->z)==0);
1463    mpz_clear(&bb);
1464    return bo;
1465  }
1466// long - long
1467  if (((a->s==1) && (b->s==3))
1468  ||  ((b->s==1) && (a->s==3)))
1469    return FALSE;
1470  if (mpz_isNeg(&a->z)&&(!mpz_isNeg(&b->z)))
1471    return FALSE;
1472  if (mpz_isNeg(&b->z)&&(!mpz_isNeg(&a->z)))
1473    return FALSE;
1474  nlGmpSimple(&a->z);
1475  nlGmpSimple(&b->z);
1476  if (a->s<2)
1477    nlGmpSimple(&a->n);
1478  if (b->s<2)
1479    nlGmpSimple(&b->n);
1480  MP_INT  aa;
1481  MP_INT  bb;
1482  mpz_init_set(&aa,&a->z);
1483  mpz_init_set(&bb,&b->z);
1484  if (a->s<2) mpz_mul(&bb,&bb,&a->n);
1485  if (b->s<2) mpz_mul(&aa,&aa,&b->n);
1486  bo=(mpz_cmp(&aa,&bb)==0);
1487  mpz_clear(&aa);
1488  mpz_clear(&bb);
1489  return bo;
1490}
1491
1492// copy not immediate number a
1493number _nlCopy_NoImm(number a)
1494{
1495  assume(!((SR_HDL(a) & SR_INT)||(a==NULL)));
1496#ifdef LDEBUG
1497  nlTest(a);
1498#endif
1499  number b=(number)omAllocBin(rnumber_bin);
1500#if defined(LDEBUG)
1501  b->debug=123456;
1502#endif
1503  switch (a->s)
1504  {
1505    case 0:
1506    case 1:
1507            nlGmpSimple(&a->n);
1508            mpz_init_set(&b->n,&a->n);
1509    case 3:
1510            nlGmpSimple(&a->z);
1511            mpz_init_set(&b->z,&a->z);
1512            break;
1513  }
1514  b->s = a->s;
1515#ifdef LDEBUG
1516  nlTest(b);
1517#endif
1518  return b;
1519}
1520
1521void _nlDelete_NoImm(number *a, const ring r)
1522{
1523  switch ((*a)->s)
1524  {
1525      case 0:
1526      case 1:
1527        mpz_clear(&(*a)->n);
1528      case 3:
1529        mpz_clear(&(*a)->z);
1530#ifdef LDEBUG
1531        (*a)->s=2;
1532#endif
1533  }
1534  omFreeBin((ADDRESS) *a, rnumber_bin);
1535}
1536
1537number _nlNeg_NoImm(number a)
1538{
1539  mpz_neg(&a->z,&a->z);
1540  if ((a->s==3) && (mpz_size1(&a->z)<=MP_SMALL))
1541  {
1542    int ui=(int)mpz_get_si(&a->z);
1543    if ((((ui<<3)>>3)==ui)
1544        && (mpz_cmp_si(&a->z,(long)ui)==0))
1545    {
1546      mpz_clear(&a->z);
1547      omFreeBin((ADDRESS)a, rnumber_bin);
1548      a=INT_TO_SR(ui);
1549    }
1550  }
1551#ifdef LDEBUG
1552  nlTest(a);
1553#endif
1554  return a;
1555}
1556
1557number _nlAdd_aNoImm_OR_bNoImm(number a, number b)
1558{
1559  number u=(number)omAllocBin(rnumber_bin);
1560#if defined(LDEBUG)
1561  u->debug=123456;
1562#endif
1563  mpz_init(&u->z);
1564  if (SR_HDL(b) & SR_INT)
1565  {
1566    number x=a;
1567    a=b;
1568    b=x;
1569  }
1570  if (SR_HDL(a) & SR_INT)
1571  {
1572    switch (b->s)
1573    {
1574      case 0:
1575      case 1:/* a:short, b:1 */
1576      {
1577        MP_INT x;
1578        mpz_init(&x);
1579        if ((int)a>0)
1580        {
1581          mpz_mul_ui(&x,&b->n,SR_TO_INT(a));
1582        }
1583        else
1584        {
1585          mpz_mul_ui(&x,&b->n,-SR_TO_INT(a));
1586          mpz_neg(&x,&x);
1587        }
1588        mpz_add(&u->z,&b->z,&x);
1589        mpz_clear(&x);
1590        nlGmpSimple(&u->z);
1591        if (mpz_cmp_ui(&u->z,(long)0)==0)
1592        {
1593          mpz_clear(&u->z);
1594          omFreeBin((ADDRESS)u, rnumber_bin);
1595          return INT_TO_SR(0);
1596        }
1597        if (mpz_cmp(&u->z,&b->n)==0)
1598        {
1599          mpz_clear(&u->z);
1600          omFreeBin((ADDRESS)u, rnumber_bin);
1601          return INT_TO_SR(1);
1602        }
1603        mpz_init_set(&u->n,&b->n);
1604        u->s = 0;
1605        break;
1606      }
1607      case 3:
1608      {
1609        if ((int)a>0)
1610          mpz_add_ui(&u->z,&b->z,SR_TO_INT(a));
1611        else
1612          mpz_sub_ui(&u->z,&b->z,-SR_TO_INT(a));
1613        nlGmpSimple(&u->z);
1614        if (mpz_cmp_ui(&u->z,(long)0)==0)
1615        {
1616          mpz_clear(&u->z);
1617          omFreeBin((ADDRESS)u, rnumber_bin);
1618          return INT_TO_SR(0);
1619        }
1620        //u->s = 3;
1621        if (mpz_size1(&u->z)<=MP_SMALL)
1622        {
1623          int ui=(int)mpz_get_si(&u->z);
1624          if ((((ui<<3)>>3)==ui)
1625          && (mpz_cmp_si(&u->z,(long)ui)==0))
1626          {
1627            mpz_clear(&u->z);
1628            omFreeBin((ADDRESS)u, rnumber_bin);
1629            return INT_TO_SR(ui);
1630          }
1631        }
1632        u->s = 3;
1633        break;
1634      }
1635    }
1636  }
1637  else
1638  {
1639    switch (a->s)
1640    {
1641      case 0:
1642      case 1:
1643      {
1644        switch(b->s)
1645        {
1646          case 0:
1647          case 1:
1648          {
1649            MP_INT x;
1650            MP_INT y;
1651            mpz_init(&x);
1652            mpz_init(&y);
1653            mpz_mul(&x,&b->z,&a->n);
1654            mpz_mul(&y,&a->z,&b->n);
1655            mpz_add(&u->z,&x,&y);
1656            nlGmpSimple(&u->z);
1657            mpz_clear(&x);
1658            mpz_clear(&y);
1659            if (mpz_cmp_ui(&u->z,(long)0)==0)
1660            {
1661              mpz_clear(&u->z);
1662              omFreeBin((ADDRESS)u, rnumber_bin);
1663              return INT_TO_SR(0);
1664            }
1665            mpz_init(&u->n);
1666            mpz_mul(&u->n,&a->n,&b->n);
1667            nlGmpSimple(&u->n);
1668            if (mpz_cmp(&u->z,&u->n)==0)
1669            {
1670               mpz_clear(&u->z);
1671               mpz_clear(&u->n);
1672               omFreeBin((ADDRESS)u, rnumber_bin);
1673               return INT_TO_SR(1);
1674            }
1675            u->s = 0;
1676            break;
1677          }
1678          case 3: /* a:1 b:3 */
1679          {
1680            MP_INT x;
1681            mpz_init(&x);
1682            mpz_mul(&x,&b->z,&a->n);
1683            mpz_add(&u->z,&a->z,&x);
1684            nlGmpSimple(&u->z);
1685            mpz_clear(&x);
1686            if (mpz_cmp_ui(&u->z,(long)0)==0)
1687            {
1688              mpz_clear(&u->z);
1689              omFreeBin((ADDRESS)u, rnumber_bin);
1690              return INT_TO_SR(0);
1691            }
1692            if (mpz_cmp(&u->z,&a->n)==0)
1693            {
1694              mpz_clear(&u->z);
1695              omFreeBin((ADDRESS)u, rnumber_bin);
1696              return INT_TO_SR(1);
1697            }
1698            mpz_init_set(&u->n,&a->n);
1699            u->s = 0;
1700            break;
1701          }
1702        } /*switch (b->s) */
1703        break;
1704      }
1705      case 3:
1706      {
1707        switch(b->s)
1708        {
1709          case 0:
1710          case 1:/* a:3, b:1 */
1711          {
1712            MP_INT x;
1713            mpz_init(&x);
1714            mpz_mul(&x,&a->z,&b->n);
1715            mpz_add(&u->z,&b->z,&x);
1716            nlGmpSimple(&u->z);
1717            mpz_clear(&x);
1718            if (mpz_cmp_ui(&u->z,(long)0)==0)
1719            {
1720              mpz_clear(&u->z);
1721              omFreeBin((ADDRESS)u, rnumber_bin);
1722              return INT_TO_SR(0);
1723            }
1724            if (mpz_cmp(&u->z,&b->n)==0)
1725            {
1726              mpz_clear(&u->z);
1727              omFreeBin((ADDRESS)u, rnumber_bin);
1728              return INT_TO_SR(1);
1729            }
1730            mpz_init_set(&u->n,&b->n);
1731            u->s = 0;
1732            break;
1733          }
1734          case 3:
1735          {
1736            mpz_add(&u->z,&a->z,&b->z);
1737            nlGmpSimple(&u->z);
1738            if (mpz_cmp_ui(&u->z,(long)0)==0)
1739            {
1740              mpz_clear(&u->z);
1741              omFreeBin((ADDRESS)u, rnumber_bin);
1742              return INT_TO_SR(0);
1743            }
1744            if (mpz_size1(&u->z)<=MP_SMALL)
1745            {
1746              int ui=(int)mpz_get_si(&u->z);
1747              if ((((ui<<3)>>3)==ui)
1748              && (mpz_cmp_si(&u->z,(long)ui)==0))
1749              {
1750                mpz_clear(&u->z);
1751                omFreeBin((ADDRESS)u, rnumber_bin);
1752                return INT_TO_SR(ui);
1753              }
1754            }
1755            u->s = 3;
1756            break;
1757          }
1758        }
1759        break;
1760      }
1761    }
1762  }
1763#ifdef LDEBUG
1764  nlTest(u);
1765#endif
1766  return u;
1767}
1768
1769number _nlSub_aNoImm_OR_bNoImm(number a, number b)
1770{
1771  number u=(number)omAllocBin(rnumber_bin);
1772#if defined(LDEBUG)
1773  u->debug=123456;
1774#endif
1775  mpz_init(&u->z);
1776  if (SR_HDL(a) & SR_INT)
1777  {
1778    switch (b->s)
1779    {
1780      case 0:
1781      case 1:/* a:short, b:1 */
1782      {
1783        MP_INT x;
1784        mpz_init(&x);
1785        if ((int)a>0)
1786        {
1787          mpz_mul_ui(&x,&b->n,SR_TO_INT(a));
1788        }
1789        else
1790        {
1791          mpz_mul_ui(&x,&b->n,-SR_TO_INT(a));
1792          mpz_neg(&x,&x);
1793        }
1794        mpz_sub(&u->z,&x,&b->z);
1795        mpz_clear(&x);
1796        if (mpz_cmp_ui(&u->z,(long)0)==0)
1797        {
1798          mpz_clear(&u->z);
1799          omFreeBin((ADDRESS)u, rnumber_bin);
1800          return INT_TO_SR(0);
1801        }
1802        if (mpz_cmp(&u->z,&b->n)==0)
1803        {
1804          mpz_clear(&u->z);
1805          omFreeBin((ADDRESS)u, rnumber_bin);
1806          return INT_TO_SR(1);
1807        }
1808        mpz_init_set(&u->n,&b->n);
1809        u->s = 0;
1810        break;
1811      }
1812      case 3:
1813      {
1814        if ((int)a>0)
1815        {
1816          mpz_sub_ui(&u->z,&b->z,SR_TO_INT(a));
1817          mpz_neg(&u->z,&u->z);
1818        }
1819        else
1820        {
1821          mpz_add_ui(&u->z,&b->z,-SR_TO_INT(a));
1822          mpz_neg(&u->z,&u->z);
1823        }
1824        nlGmpSimple(&u->z);
1825        if (mpz_cmp_ui(&u->z,(long)0)==0)
1826        {
1827          mpz_clear(&u->z);
1828          omFreeBin((ADDRESS)u, rnumber_bin);
1829          return INT_TO_SR(0);
1830        }
1831        //u->s = 3;
1832        if (mpz_size1(&u->z)<=MP_SMALL)
1833        {
1834          int ui=(int)mpz_get_si(&u->z);
1835          if ((((ui<<3)>>3)==ui)
1836          && (mpz_cmp_si(&u->z,(long)ui)==0))
1837          {
1838            mpz_clear(&u->z);
1839            omFreeBin((ADDRESS)u, rnumber_bin);
1840            return INT_TO_SR(ui);
1841          }
1842        }
1843        u->s = 3;
1844        break;
1845      }
1846    }
1847  }
1848  else if (SR_HDL(b) & SR_INT)
1849  {
1850    switch (a->s)
1851    {
1852      case 0:
1853      case 1:/* b:short, a:1 */
1854      {
1855        MP_INT x;
1856        mpz_init(&x);
1857        if ((int)b>0)
1858        {
1859          mpz_mul_ui(&x,&a->n,SR_TO_INT(b));
1860        }
1861        else
1862        {
1863          mpz_mul_ui(&x,&a->n,-SR_TO_INT(b));
1864          mpz_neg(&x,&x);
1865        }
1866        mpz_sub(&u->z,&a->z,&x);
1867        mpz_clear(&x);
1868        if (mpz_cmp_ui(&u->z,(long)0)==0)
1869        {
1870          mpz_clear(&u->z);
1871          omFreeBin((ADDRESS)u, rnumber_bin);
1872          return INT_TO_SR(0);
1873        }
1874        if (mpz_cmp(&u->z,&a->n)==0)
1875        {
1876          mpz_clear(&u->z);
1877          omFreeBin((ADDRESS)u, rnumber_bin);
1878          return INT_TO_SR(1);
1879        }
1880        mpz_init_set(&u->n,&a->n);
1881        u->s = 0;
1882        break;
1883      }
1884      case 3:
1885      {
1886        if ((int)b>0)
1887        {
1888          mpz_sub_ui(&u->z,&a->z,SR_TO_INT(b));
1889        }
1890        else
1891        {
1892          mpz_add_ui(&u->z,&a->z,-SR_TO_INT(b));
1893        }
1894        if (mpz_cmp_ui(&u->z,(long)0)==0)
1895        {
1896          mpz_clear(&u->z);
1897          omFreeBin((ADDRESS)u, rnumber_bin);
1898          return INT_TO_SR(0);
1899        }
1900        //u->s = 3;
1901        nlGmpSimple(&u->z);
1902        if (mpz_size1(&u->z)<=MP_SMALL)
1903        {
1904          int ui=(int)mpz_get_si(&u->z);
1905          if ((((ui<<3)>>3)==ui)
1906          && (mpz_cmp_si(&u->z,(long)ui)==0))
1907          {
1908            mpz_clear(&u->z);
1909            omFreeBin((ADDRESS)u, rnumber_bin);
1910            return INT_TO_SR(ui);
1911          }
1912        }
1913        u->s = 3;
1914        break;
1915      }
1916    }
1917  }
1918  else
1919  {
1920    switch (a->s)
1921    {
1922      case 0:
1923      case 1:
1924      {
1925        switch(b->s)
1926        {
1927          case 0:
1928          case 1:
1929          {
1930            MP_INT x;
1931            MP_INT y;
1932            mpz_init(&x);
1933            mpz_init(&y);
1934            mpz_mul(&x,&b->z,&a->n);
1935            mpz_mul(&y,&a->z,&b->n);
1936            mpz_sub(&u->z,&y,&x);
1937            mpz_clear(&x);
1938            mpz_clear(&y);
1939            if (mpz_cmp_ui(&u->z,(long)0)==0)
1940            {
1941              mpz_clear(&u->z);
1942              omFreeBin((ADDRESS)u, rnumber_bin);
1943              return INT_TO_SR(0);
1944            }
1945            mpz_init(&u->n);
1946            mpz_mul(&u->n,&a->n,&b->n);
1947            if (mpz_cmp(&u->z,&u->n)==0)
1948            {
1949              mpz_clear(&u->z);
1950              mpz_clear(&u->n);
1951              omFreeBin((ADDRESS)u, rnumber_bin);
1952              return INT_TO_SR(1);
1953            }
1954            u->s = 0;
1955            break;
1956          }
1957          case 3: /* a:1, b:3 */
1958          {
1959            MP_INT x;
1960            mpz_init(&x);
1961            mpz_mul(&x,&b->z,&a->n);
1962            mpz_sub(&u->z,&a->z,&x);
1963            mpz_clear(&x);
1964            if (mpz_cmp_ui(&u->z,(long)0)==0)
1965            {
1966              mpz_clear(&u->z);
1967              omFreeBin((ADDRESS)u, rnumber_bin);
1968              return INT_TO_SR(0);
1969            }
1970            if (mpz_cmp(&u->z,&a->n)==0)
1971            {
1972              mpz_clear(&u->z);
1973              omFreeBin((ADDRESS)u, rnumber_bin);
1974              return INT_TO_SR(1);
1975            }
1976            mpz_init_set(&u->n,&a->n);
1977            u->s = 0;
1978            break;
1979          }
1980        }
1981        break;
1982      }
1983      case 3:
1984      {
1985        switch(b->s)
1986        {
1987          case 0:
1988          case 1: /* a:3, b:1 */
1989          {
1990            MP_INT x;
1991            mpz_init(&x);
1992            mpz_mul(&x,&a->z,&b->n);
1993            mpz_sub(&u->z,&x,&b->z);
1994            mpz_clear(&x);
1995            if (mpz_cmp_ui(&u->z,(long)0)==0)
1996            {
1997              mpz_clear(&u->z);
1998              omFreeBin((ADDRESS)u, rnumber_bin);
1999              return INT_TO_SR(0);
2000            }
2001            if (mpz_cmp(&u->z,&b->n)==0)
2002            {
2003              mpz_clear(&u->z);
2004              omFreeBin((ADDRESS)u, rnumber_bin);
2005              return INT_TO_SR(1);
2006            }
2007            mpz_init_set(&u->n,&b->n);
2008            u->s = 0;
2009            break;
2010          }
2011          case 3: /* a:3 , b:3 */
2012          {
2013            mpz_sub(&u->z,&a->z,&b->z);
2014            nlGmpSimple(&u->z);
2015            if (mpz_cmp_ui(&u->z,(long)0)==0)
2016            {
2017              mpz_clear(&u->z);
2018              omFreeBin((ADDRESS)u, rnumber_bin);
2019              return INT_TO_SR(0);
2020            }
2021            //u->s = 3;
2022            if (mpz_size1(&u->z)<=MP_SMALL)
2023            {
2024              int ui=(int)mpz_get_si(&u->z);
2025              if ((((ui<<3)>>3)==ui)
2026              && (mpz_cmp_si(&u->z,(long)ui)==0))
2027              {
2028                mpz_clear(&u->z);
2029                omFreeBin((ADDRESS)u, rnumber_bin);
2030                return INT_TO_SR(ui);
2031              }
2032            }
2033            u->s = 3;
2034            break;
2035          }
2036        }
2037        break;
2038      }
2039    }
2040  }
2041#ifdef LDEBUG
2042  nlTest(u);
2043#endif
2044  return u;
2045}
2046
2047// a and b are intermediate, but a*b not
2048number _nlMult_aImm_bImm_rNoImm(number a, number b)
2049{
2050  number u=(number)omAllocBin(rnumber_bin);
2051#if defined(LDEBUG)
2052  u->debug=123456;
2053#endif
2054  u->s=3;
2055  if ((int)b>0)
2056  {
2057    mpz_init_set_si(&u->z,(long)SR_TO_INT(a));
2058    mpz_mul_ui(&u->z,&u->z,(unsigned long)SR_TO_INT(b));
2059  }
2060  else
2061  {
2062    mpz_init_set_si(&u->z,(long)(-SR_TO_INT(a)));
2063    mpz_mul_ui(&u->z,&u->z,(long)(-SR_TO_INT(b)));
2064  }
2065#ifdef LDEBUG
2066  nlTest(u);
2067#endif
2068  return u;
2069}
2070
2071// a or b are not immediate
2072number _nlMult_aNoImm_OR_bNoImm(number a, number b)
2073{
2074  assume(! (SR_HDL(a) & SR_HDL(b) & SR_INT));
2075  number u=(number)omAllocBin(rnumber_bin);
2076#if defined(LDEBUG)
2077  u->debug=123456;
2078#endif
2079  mpz_init(&u->z);
2080  if (SR_HDL(b) & SR_INT)
2081  {
2082    number x=a;
2083    a=b;
2084    b=x;
2085  }
2086  if (SR_HDL(a) & SR_INT)
2087  {
2088    u->s=b->s;
2089    if (u->s==1) u->s=0;
2090    if ((int)a>0)
2091    {
2092      mpz_mul_ui(&u->z,&b->z,(unsigned long)SR_TO_INT(a));
2093    }
2094    else
2095    {
2096      if (a==INT_TO_SR(-1))
2097      {
2098        mpz_set(&u->z,&b->z);
2099        mpz_neg(&u->z,&u->z);
2100        u->s=b->s;
2101      }
2102      else
2103      {
2104        mpz_mul_ui(&u->z,&b->z,(unsigned long)-SR_TO_INT(a));
2105        mpz_neg(&u->z,&u->z);
2106      }
2107    }
2108    nlGmpSimple(&u->z);
2109    if (u->s<2)
2110    {
2111      if (mpz_cmp(&u->z,&b->n)==0)
2112      {
2113        mpz_clear(&u->z);
2114        omFreeBin((ADDRESS)u, rnumber_bin);
2115        return INT_TO_SR(1);
2116      }
2117      mpz_init_set(&u->n,&b->n);
2118    }
2119    else //u->s==3
2120    {
2121      if (mpz_size1(&u->z)<=MP_SMALL)
2122      {
2123        int ui=(int)mpz_get_si(&u->z);
2124        if ((((ui<<3)>>3)==ui)
2125            && (mpz_cmp_si(&u->z,(long)ui)==0))
2126        {
2127          mpz_clear(&u->z);
2128          omFreeBin((ADDRESS)u, rnumber_bin);
2129          return INT_TO_SR(ui);
2130        }
2131      }
2132    }
2133  }
2134  else
2135  {
2136    mpz_mul(&u->z,&a->z,&b->z);
2137    u->s = 0;
2138    if(a->s==3)
2139    {
2140      if(b->s==3)
2141      {
2142        u->s = 3;
2143      }
2144      else
2145      {
2146        if (mpz_cmp(&u->z,&b->n)==0)
2147        {
2148          mpz_clear(&u->z);
2149          omFreeBin((ADDRESS)u, rnumber_bin);
2150          return INT_TO_SR(1);
2151        }
2152        mpz_init_set(&u->n,&b->n);
2153      }
2154    }
2155    else
2156    {
2157      if(b->s==3)
2158      {
2159        if (mpz_cmp(&u->z,&a->n)==0)
2160        {
2161          mpz_clear(&u->z);
2162          omFreeBin((ADDRESS)u, rnumber_bin);
2163          return INT_TO_SR(1);
2164        }
2165        mpz_init_set(&u->n,&a->n);
2166      }
2167      else
2168      {
2169        mpz_init(&u->n);
2170        mpz_mul(&u->n,&a->n,&b->n);
2171        if (mpz_cmp(&u->z,&u->n)==0)
2172        {
2173          mpz_clear(&u->z);
2174          mpz_clear(&u->n);
2175          omFreeBin((ADDRESS)u, rnumber_bin);
2176          return INT_TO_SR(1);
2177        }
2178      }
2179    }
2180  }
2181#ifdef LDEBUG
2182  nlTest(u);
2183#endif
2184  return u;
2185}
2186
2187/*2
2188* z := i
2189*/
2190number nlRInit (int i)
2191{
2192  number z=(number)omAllocBin(rnumber_bin);
2193#if defined(LDEBUG)
2194  z->debug=123456;
2195#endif
2196  mpz_init_set_si(&z->z,(long)i);
2197  z->s = 3;
2198  return z;
2199}
2200
2201/*2
2202* z := i/j
2203*/
2204number nlInit2 (int i, int j)
2205{
2206  number z=(number)omAllocBin(rnumber_bin);
2207#if defined(LDEBUG)
2208  z->debug=123456;
2209#endif
2210  mpz_init_set_si(&z->z,(long)i);
2211  mpz_init_set_si(&z->n,(long)j);
2212  z->s = 0;
2213  nlNormalize(z);
2214  return z;
2215}
2216
2217#else // DO_LINLINE
2218
2219// declare immedate routines
2220number nlRInit (int i);
2221BOOLEAN _nlEqual_aNoImm_OR_bNoImm(number a, number b);
2222number  _nlCopy_NoImm(number a);
2223void    _nlDelete_NoImm(number *a, const ring r);
2224number  _nlNeg_NoImm(number a);
2225number  _nlAdd_aNoImm_OR_bNoImm(number a, number b);
2226number  _nlSub_aNoImm_OR_bNoImm(number a, number b);
2227number  _nlMult_aNoImm_OR_bNoImm(number a, number b);
2228number  _nlMult_aImm_bImm_rNoImm(number a, number b);
2229
2230#endif
2231
2232
2233/***************************************************************
2234 *
2235 * Routines which might be inlined by p_Numbers.h
2236 *
2237 *******************************************************************/
2238#if defined(DO_LINLINE) || !defined(P_NUMBERS_H)
2239
2240// routines which are always inlined/static
2241
2242/*2
2243* a = b ?
2244*/
2245LINLINE BOOLEAN nlEqual (number a, number b)
2246{
2247#ifdef LDEBUG
2248  nlTest(a);
2249  nlTest(b);
2250#endif
2251// short - short
2252  if (SR_HDL(a) & SR_HDL(b) & SR_INT) return a==b;
2253  return _nlEqual_aNoImm_OR_bNoImm(a, b);
2254}
2255
2256
2257LINLINE number nlInit (int i)
2258{
2259  number n;
2260  if ( ((i << 3) >> 3) == i ) n=INT_TO_SR(i);
2261  else                        n=nlRInit(i);
2262#ifdef LDEBUG
2263  nlTest(n);
2264#endif
2265  return n;
2266}
2267
2268
2269/*2
2270* a == 1 ?
2271*/
2272LINLINE BOOLEAN nlIsOne (number a)
2273{
2274#ifdef LDEBUG
2275  if (a==NULL) return FALSE;
2276  nlTest(a);
2277#endif
2278  if (SR_HDL(a) & SR_INT) return (a==INT_TO_SR(1));
2279  return FALSE;
2280}
2281
2282LINLINE BOOLEAN nlIsZero (number a)
2283{
2284  return (a==INT_TO_SR(0));
2285}
2286
2287/*2
2288* copy a to b
2289*/
2290LINLINE number nlCopy(number a)
2291{
2292  if ((SR_HDL(a) & SR_INT)||(a==NULL))
2293  {
2294    return a;
2295  }
2296  return _nlCopy_NoImm(a);
2297}
2298
2299LINLINE number nl_Copy(number a, ring r)
2300{
2301  if ((SR_HDL(a) & SR_INT)||(a==NULL))
2302  {
2303    return a;
2304  }
2305  return _nlCopy_NoImm(a);
2306}
2307
2308
2309LINLINE void nlNew (number * r)
2310{
2311  *r=NULL;
2312}
2313
2314/*2
2315* delete a
2316*/
2317LINLINE void nlDelete (number * a, const ring r)
2318{
2319  if (*a!=NULL)
2320  {
2321#ifdef LDEBUG
2322    nlTest(*a);
2323#endif
2324    if ((SR_HDL(*a) & SR_INT)==0)
2325      _nlDelete_NoImm(a,r);
2326    *a=NULL;
2327  }
2328}
2329
2330/*2
2331* za:= - za
2332*/
2333LINLINE number nlNeg (number a)
2334{
2335#ifdef LDEBUG
2336  nlTest(a);
2337#endif
2338  if(SR_HDL(a) &SR_INT)
2339  {
2340    int r=SR_TO_INT(a);
2341    if (r==(-(1<<28))) a=nlRInit(1<<28);
2342    else               a=INT_TO_SR(-r);
2343    return a;
2344  }
2345  return _nlNeg_NoImm(a);
2346}
2347
2348/*2
2349* u:= a + b
2350*/
2351LINLINE number nlAdd (number a, number b)
2352{
2353  number u;
2354  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2355  {
2356    int r=SR_HDL(a)+SR_HDL(b)-1;
2357    if ( ((r << 1) >> 1) == r )
2358      return (number)r;
2359    else
2360      return nlRInit(SR_TO_INT(r));
2361  }
2362  return _nlAdd_aNoImm_OR_bNoImm(a, b);
2363}
2364
2365LINLINE number nlMult (number a, number b)
2366{
2367#ifdef LDEBUG
2368  nlTest(a);
2369  nlTest(b);
2370#endif
2371  if (a==INT_TO_SR(0)) return INT_TO_SR(0);
2372  if (b==INT_TO_SR(0)) return INT_TO_SR(0);
2373  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2374  {
2375    int r=(SR_HDL(a)-1)*(SR_HDL(b)>>1);
2376    if ((r/(SR_HDL(b)>>1))==(SR_HDL(a)-1))
2377    {
2378      number u=((number) ((r>>1)+SR_INT));
2379      if (((SR_HDL(u)<<1)>>1)==SR_HDL(u)) return (u);
2380      return nlRInit(SR_HDL(u)>>2);
2381    }
2382    return _nlMult_aImm_bImm_rNoImm(a, b);
2383  }
2384  return _nlMult_aNoImm_OR_bNoImm(a, b);
2385}
2386
2387
2388/*2
2389* u:= a - b
2390*/
2391LINLINE number nlSub (number a, number b)
2392{
2393  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2394  {
2395    int r=SR_HDL(a)-SR_HDL(b)+1;
2396    if ( ((r << 1) >> 1) == r )
2397    {
2398      return (number)r;
2399    }
2400    else
2401      return nlRInit(SR_TO_INT(r));
2402  }
2403  return _nlSub_aNoImm_OR_bNoImm(a, b);
2404}
2405
2406
2407
2408#endif // DO_LINLINE
2409
2410#endif // LONGRAT_CC
Note: See TracBrowser for help on using the repository browser.