source: git/Singular/longrat.cc @ ed7cb5

spielwiese
Last change on this file since ed7cb5 was ed7cb5, checked in by Hans Schönemann <hannes@…>, 23 years ago
*hannes: int(z/n) return trunc(z/n) instead of 0 for z/n not in Z git-svn-id: file:///usr/local/Singular/svn/trunk@5607 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 48.8 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: longrat.cc,v 1.39 2001-08-24 13:41:35 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
514/*
515* 1/a
516*/
517number nlInvers(number a)
518{
519#ifdef LDEBUG
520  nlTest(a);
521#endif
522  number n;
523  if (SR_HDL(a) & SR_INT)
524  {
525    if ((a==INT_TO_SR(1)) || (a==INT_TO_SR(-1)))
526    {
527      return a;
528    }
529    if (nlIsZero(a))
530    {
531      WerrorS("div. 1/0");
532      return INT_TO_SR(0);
533    }
534    n=(number)omAllocBin(rnumber_bin);
535#if defined(LDEBUG)
536    n->debug=123456;
537#endif
538    n->s=1;
539    if ((int)a>0)
540    {
541      mpz_init_set_si(&n->z,(long)1);
542      mpz_init_set_si(&n->n,(long)SR_TO_INT(a));
543    }
544    else
545    {
546      mpz_init_set_si(&n->z,(long)-1);
547      mpz_init_set_si(&n->n,(long)-SR_TO_INT(a));
548#ifdef LDEBUG
549    nlTest(n);
550#endif
551    }
552#ifdef LDEBUG
553    nlTest(n);
554#endif
555    return n;
556  }
557  n=(number)omAllocBin(rnumber_bin);
558#if defined(LDEBUG)
559  n->debug=123456;
560#endif
561  {
562    n->s=a->s;
563    mpz_init_set(&n->n,&a->z);
564    switch (a->s)
565    {
566      case 0:
567      case 1:
568              mpz_init_set(&n->z,&a->n);
569              if (mpz_isNeg(&n->n)) /* && n->s<2*/
570              {
571                mpz_neg(&n->z,&n->z);
572                mpz_neg(&n->n,&n->n);
573              }
574              if (mpz_cmp_si(&n->n,(long)1)==0)
575              {
576                mpz_clear(&n->n);
577                n->s=3;
578                if (mpz_size1(&n->z)<=MP_SMALL)
579                {
580                  int ui=(int)mpz_get_si(&n->z);
581                  if ((((ui<<3)>>3)==ui)
582                  && (mpz_cmp_si(&n->z,(long)ui)==0))
583                  {
584                    mpz_clear(&n->z);
585                    omFreeBin((ADDRESS)n, rnumber_bin);
586                    n=INT_TO_SR(ui);
587                  }
588                }
589              }
590              break;
591      case 3:
592              n->s=1;
593              if (mpz_isNeg(&n->n)) /* && n->s<2*/
594              {
595                mpz_neg(&n->n,&n->n);
596                mpz_init_set_si(&n->z,(long)-1);
597              }
598              else
599              {
600                mpz_init_set_si(&n->z,(long)1);
601              }
602              break;
603    }
604  }
605#ifdef LDEBUG
606  nlTest(n);
607#endif
608  return n;
609}
610
611
612/*2
613* u := a / b in Z, if b | a (else undefined)
614*/
615number   nlExactDiv(number a, number b)
616{
617  if (b==INT_TO_SR(0))
618  {
619    WerrorS("div. by 0");
620    return INT_TO_SR(0);
621  }
622  if (a==INT_TO_SR(0))
623    return INT_TO_SR(0);
624  number u;
625  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
626  {
627    /* the small int -(1<<28) divided by -1 is the large int (1<<28)   */
628    if ((a==INT_TO_SR(-(1<<28)))&&(b==INT_TO_SR(-1)))
629    {
630      return nlRInit(1<<28);
631    }
632    int aa=SR_TO_INT(a);
633    int bb=SR_TO_INT(b);
634    return INT_TO_SR(aa/bb);
635  }
636  number bb=NULL;
637  if (SR_HDL(b) & SR_INT)
638  {
639    bb=nlRInit(SR_TO_INT(b));
640    b=bb;
641  }
642  u=(number)omAllocBin(rnumber_bin);
643#if defined(LDEBUG)
644  u->debug=123456;
645#endif
646  mpz_init(&u->z);
647  /* u=a/b */
648  u->s = 3;
649  MPZ_EXACTDIV(&u->z,&a->z,&b->z);
650  if (bb!=NULL)
651  {
652    mpz_clear(&bb->z);
653    omFreeBin((ADDRESS)bb, rnumber_bin);
654  }
655  if (mpz_size1(&u->z)<=MP_SMALL)
656  {
657    int ui=(int)mpz_get_si(&u->z);
658    if ((((ui<<3)>>3)==ui)
659    && (mpz_cmp_si(&u->z,(long)ui)==0))
660    {
661      mpz_clear(&u->z);
662      omFreeBin((ADDRESS)u, rnumber_bin);
663      u=INT_TO_SR(ui);
664    }
665  }
666#ifdef LDEBUG
667  nlTest(u);
668#endif
669  return u;
670}
671
672/*2
673* u := a / b in Z
674*/
675number nlIntDiv (number a, number b)
676{
677  if (b==INT_TO_SR(0))
678  {
679    WerrorS("div. by 0");
680    return INT_TO_SR(0);
681  }
682  if (a==INT_TO_SR(0))
683    return INT_TO_SR(0);
684  number u;
685  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
686  {
687    /* the small int -(1<<28) divided by -1 is the large int (1<<28)   */
688    if ((a==INT_TO_SR(-(1<<28)))&&(b==INT_TO_SR(-1)))
689    {
690      return nlRInit(1<<28);
691    }
692    /* consider the signs of a and b:
693    *  + + -> u=a+b-1
694    *  + - -> u=a-b-1
695    *  - + -> u=a-b+1
696    *  - - -> u=a+b+1
697    */
698    int aa=SR_TO_INT(a);
699    int bb=SR_TO_INT(b);
700    if (aa>0)
701    {
702      if (bb>0)
703        return INT_TO_SR((aa+bb-1)/bb);
704      else
705        return INT_TO_SR((aa-bb-1)/bb);
706    }
707    else
708    {
709      if (bb>0)
710      {
711        return INT_TO_SR((aa-bb+1)/bb);
712      }
713      else
714      {
715        return INT_TO_SR((aa+bb+1)/bb);
716      }
717    }
718  }
719  if (SR_HDL(a) & SR_INT)
720  {
721    /* the small int -(1<<28) divided by 2^28 is 1   */
722    if (a==INT_TO_SR(-(1<<28)))
723    {
724      if(mpz_cmp_si(&b->z,(long)(1<<28))==0)
725      {
726        return INT_TO_SR(-1);
727      }
728    }
729    /* a is a small and b is a large int: -> 0 */
730    return INT_TO_SR(0);
731  }
732  number bb=NULL;
733  if (SR_HDL(b) & SR_INT)
734  {
735    bb=nlRInit(SR_TO_INT(b));
736    b=bb;
737  }
738  u=(number)omAllocBin(rnumber_bin);
739#if defined(LDEBUG)
740  u->debug=123456;
741#endif
742  mpz_init_set(&u->z,&a->z);
743  /* consider the signs of a and b:
744  *  + + -> u=a+b-1
745  *  + - -> u=a-b-1
746  *  - + -> u=a-b+1
747  *  - - -> u=a+b+1
748  */
749  if (mpz_isNeg(&a->z))
750  {
751    if (mpz_isNeg(&b->z))
752    {
753      mpz_add(&u->z,&u->z,&b->z);
754    }
755    else
756    {
757      mpz_sub(&u->z,&u->z,&b->z);
758    }
759    mpz_add_ui(&u->z,&u->z,1);
760  }
761  else
762  {
763    if (mpz_isNeg(&b->z))
764    {
765      mpz_sub(&u->z,&u->z,&b->z);
766    }
767    else
768    {
769      mpz_add(&u->z,&u->z,&b->z);
770    }
771    mpz_sub_ui(&u->z,&u->z,1);
772  }
773  /* u=u/b */
774  u->s = 3;
775  MPZ_DIV(&u->z,&u->z,&b->z);
776  nlGmpSimple(&u->z);
777  if (bb!=NULL)
778  {
779    mpz_clear(&bb->z);
780    omFreeBin((ADDRESS)bb, rnumber_bin);
781  }
782  if (mpz_size1(&u->z)<=MP_SMALL)
783  {
784    int ui=(int)mpz_get_si(&u->z);
785    if ((((ui<<3)>>3)==ui)
786    && (mpz_cmp_si(&u->z,(long)ui)==0))
787    {
788      mpz_clear(&u->z);
789      omFreeBin((ADDRESS)u, rnumber_bin);
790      u=INT_TO_SR(ui);
791    }
792  }
793#ifdef LDEBUG
794  nlTest(u);
795#endif
796  return u;
797}
798
799/*2
800* u := a mod b in Z, u>=0
801*/
802number nlIntMod (number a, number b)
803{
804  if (b==INT_TO_SR(0))
805  {
806    WerrorS("div. by 0");
807    return INT_TO_SR(0);
808  }
809  if (a==INT_TO_SR(0))
810    return INT_TO_SR(0);
811  number u;
812  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
813  {
814    if ((int)a>0)
815    {
816      if ((int)b>0)
817        return INT_TO_SR(SR_TO_INT(a)%SR_TO_INT(b));
818      else
819        return INT_TO_SR(SR_TO_INT(a)%(-SR_TO_INT(b)));
820    }
821    else
822    {
823      if ((int)b>0)
824      {
825        int i=(-SR_TO_INT(a))%SR_TO_INT(b);
826        if ( i != 0 ) i = (SR_TO_INT(b))-i;
827        return INT_TO_SR(i);
828      }
829      else
830      {
831        int i=(-SR_TO_INT(a))%(-SR_TO_INT(b));
832        if ( i != 0 ) i = (-SR_TO_INT(b))-i;
833        return INT_TO_SR(i);
834      }
835    }
836  }
837  if (SR_HDL(a) & SR_INT)
838  {
839    /* a is a small and b is a large int: -> a or (a+b) or (a-b) */
840    if ((int)a<0)
841    {
842      if (mpz_isNeg(&b->z))
843        return nlSub(a,b);
844      /*else*/
845        return nlAdd(a,b);
846    }
847    /*else*/
848      return a;
849  }
850  number bb=NULL;
851  if (SR_HDL(b) & SR_INT)
852  {
853    bb=nlRInit(SR_TO_INT(b));
854    b=bb;
855  }
856  u=(number)omAllocBin(rnumber_bin);
857#if defined(LDEBUG)
858  u->debug=123456;
859#endif
860  mpz_init(&u->z);
861  u->s = 3;
862  mpz_mod(&u->z,&a->z,&b->z);
863  if (bb!=NULL)
864  {
865    mpz_clear(&bb->z);
866    omFreeBin((ADDRESS)bb, rnumber_bin);
867  }
868  if (mpz_isNeg(&u->z))
869  {
870    if (mpz_isNeg(&b->z))
871      mpz_sub(&u->z,&u->z,&b->z);
872    else
873      mpz_add(&u->z,&u->z,&b->z);
874  }
875  nlGmpSimple(&u->z);
876  if (mpz_size1(&u->z)<=MP_SMALL)
877  {
878    int ui=(int)mpz_get_si(&u->z);
879    if ((((ui<<3)>>3)==ui)
880    && (mpz_cmp_si(&u->z,(long)ui)==0))
881    {
882      mpz_clear(&u->z);
883      omFreeBin((ADDRESS)u, rnumber_bin);
884      u=INT_TO_SR(ui);
885    }
886  }
887#ifdef LDEBUG
888  nlTest(u);
889#endif
890  return u;
891}
892
893/*2
894* u := a / b
895*/
896number nlDiv (number a, number b)
897{
898  number u;
899  if (nlIsZero(b))
900  {
901    WerrorS("div. by 0");
902    return INT_TO_SR(0);
903  }
904  u=(number)omAllocBin(rnumber_bin);
905  u->s=0;
906#if defined(LDEBUG)
907  u->debug=123456;
908#endif
909// ---------- short / short ------------------------------------
910  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
911  {
912    int i=SR_TO_INT(a);
913    int j=SR_TO_INT(b);
914    int r=i%j;
915    if (r==0)
916    {
917      omFreeBin((ADDRESS)u, rnumber_bin);
918      return INT_TO_SR(i/j);
919    }
920    mpz_init_set_si(&u->z,(long)i);
921    mpz_init_set_si(&u->n,(long)j);
922  }
923  else
924  {
925    mpz_init(&u->z);
926// ---------- short / long ------------------------------------
927    if (SR_HDL(a) & SR_INT)
928    {
929      // short a / (z/n) -> (a*n)/z
930      if (b->s<2)
931      {
932        if ((int)a>=0)
933          mpz_mul_ui(&u->z,&b->n,SR_TO_INT(a));
934        else
935        {
936          mpz_mul_ui(&u->z,&b->n,-SR_TO_INT(a));
937          mpz_neg(&u->z,&u->z);
938        }
939      }
940      else
941      // short a / long z -> a/z
942      {
943        mpz_set_si(&u->z,SR_TO_INT(a));
944      }
945      if (mpz_cmp(&u->z,&b->z)==0)
946      {
947        mpz_clear(&u->z);
948        omFreeBin((ADDRESS)u, rnumber_bin);
949        return INT_TO_SR(1);
950      }
951      mpz_init_set(&u->n,&b->z);
952    }
953// ---------- long / short ------------------------------------
954    else if (SR_HDL(b) & SR_INT)
955    {
956      mpz_set(&u->z,&a->z);
957      // (z/n) / b -> z/(n*b)
958      if (a->s<2)
959      {
960        mpz_init_set(&u->n,&a->n);
961        if ((int)b>0)
962          mpz_mul_ui(&u->n,&u->n,SR_TO_INT(b));
963        else
964        {
965          mpz_mul_ui(&u->n,&u->n,-SR_TO_INT(b));
966          mpz_neg(&u->z,&u->z);
967        }
968      }
969      else
970      // long z / short b -> z/b
971      {
972        //mpz_set(&u->z,&a->z);
973        mpz_init_set_si(&u->n,SR_TO_INT(b));
974      }
975    }
976// ---------- long / long ------------------------------------
977    else
978    {
979      //u->s=0;
980      mpz_set(&u->z,&a->z);
981      mpz_init_set(&u->n,&b->z);
982      if (a->s<2) mpz_mul(&u->n,&u->n,&a->n);
983      if (b->s<2) mpz_mul(&u->z,&u->z,&b->n);
984    }
985  }
986  if (mpz_isNeg(&u->n))
987  {
988    mpz_neg(&u->z,&u->z);
989    mpz_neg(&u->n,&u->n);
990  }
991  if (mpz_cmp_si(&u->n,(long)1)==0)
992  {
993    mpz_clear(&u->n);
994    if (mpz_size1(&u->z)<=MP_SMALL)
995    {
996      int ui=(int)mpz_get_si(&u->z);
997      if ((((ui<<3)>>3)==ui)
998      && (mpz_cmp_si(&u->z,(long)ui)==0))
999      {
1000        mpz_clear(&u->z);
1001        omFreeBin((ADDRESS)u, rnumber_bin);
1002        return INT_TO_SR(ui);
1003      }
1004    }
1005    u->s=3;
1006  }
1007#ifdef LDEBUG
1008  nlTest(u);
1009#endif
1010  return u;
1011}
1012
1013#if (defined(i386)) && (defined(HAVE_LIBGMP1))
1014/*
1015* compute x^exp for x in Z
1016* there seems to be an bug in mpz_pow_ui for i386
1017*/
1018static inline void nlPow (MP_INT * res,MP_INT * x,int exp)
1019{
1020  if (exp==0)
1021  {
1022    mpz_set_si(res,(long)1);
1023  }
1024  else
1025  {
1026    MP_INT xh;
1027    mpz_init(&xh);
1028    mpz_set(res,x);
1029    exp--;
1030    while (exp!=0)
1031    {
1032      mpz_mul(&xh,res,x);
1033      mpz_set(res,&xh);
1034      exp--;
1035    }
1036    mpz_clear(&xh);
1037  }
1038}
1039#endif
1040
1041/*2
1042* u:= x ^ exp
1043*/
1044void nlPower (number x,int exp,number * u)
1045{
1046  if (!nlIsZero(x))
1047  {
1048#ifdef LDEBUG
1049    nlTest(x);
1050#endif
1051    number aa=NULL;
1052    if (SR_HDL(x) & SR_INT)
1053    {
1054      aa=nlRInit(SR_TO_INT(x));
1055      x=aa;
1056    }
1057    *u=(number)omAllocBin(rnumber_bin);
1058#if defined(LDEBUG)
1059    (*u)->debug=123456;
1060#endif
1061    mpz_init(&(*u)->z);
1062    (*u)->s = x->s;
1063#if (!defined(i386)) || (defined(HAVE_LIBGMP2))
1064    mpz_pow_ui(&(*u)->z,&x->z,(unsigned long)exp);
1065#else
1066    nlPow(&(*u)->z,&x->z,exp);
1067#endif
1068    if (x->s<2)
1069    {
1070      mpz_init(&(*u)->n);
1071#if (!defined(i386)) || (defined(HAVE_LIBGMP2))
1072      mpz_pow_ui(&(*u)->n,&x->n,(unsigned long)exp);
1073#else
1074      nlPow(&(*u)->n,&x->n,exp);
1075#endif
1076    }
1077    if (aa!=NULL)
1078    {
1079      mpz_clear(&aa->z);
1080      omFreeBin((ADDRESS)aa, rnumber_bin);
1081    }
1082    if (((*u)->s<=2) && (mpz_cmp_si(&(*u)->n,(long)1)==0))
1083    {
1084      mpz_clear(&(*u)->n);
1085      (*u)->s=3;
1086    }
1087    if (((*u)->s==3) && (mpz_size1(&(*u)->z)<=MP_SMALL))
1088    {
1089      int ui=(int)mpz_get_si(&(*u)->z);
1090      if ((((ui<<3)>>3)==ui)
1091      && (mpz_cmp_si(&(*u)->z,(long)ui)==0))
1092      {
1093        mpz_clear(&(*u)->z);
1094        omFreeBin((ADDRESS)*u, rnumber_bin);
1095        *u=INT_TO_SR(ui);
1096      }
1097    }
1098  }
1099  else
1100    *u = INT_TO_SR(0);
1101#ifdef LDEBUG
1102  nlTest(*u);
1103#endif
1104}
1105
1106
1107/*2
1108* za >= 0 ?
1109*/
1110BOOLEAN nlGreaterZero (number a)
1111{
1112#ifdef LDEBUG
1113  nlTest(a);
1114#endif
1115  if (SR_HDL(a) & SR_INT) return SR_HDL(a)>=0;
1116  return (!mpz_isNeg(&a->z));
1117}
1118
1119/*2
1120* a > b ?
1121*/
1122BOOLEAN nlGreater (number a, number b)
1123{
1124#ifdef LDEBUG
1125  nlTest(a);
1126  nlTest(b);
1127#endif
1128  number r;
1129  BOOLEAN rr;
1130  r=nlSub(a,b);
1131  rr=(!nlIsZero(r)) && (nlGreaterZero(r));
1132  nlDelete(&r,currRing);
1133  return rr;
1134}
1135
1136/*2
1137* a == -1 ?
1138*/
1139BOOLEAN nlIsMOne (number a)
1140{
1141#ifdef LDEBUG
1142  if (a==NULL) return FALSE;
1143  nlTest(a);
1144#endif
1145  if (SR_HDL(a) & SR_INT) return (a==INT_TO_SR(-1));
1146  return FALSE;
1147}
1148
1149/*2
1150* result =gcd(a,b)
1151*/
1152number nlGcd(number a, number b, const ring r)
1153{
1154  number result;
1155#ifdef LDEBUG
1156  nlTest(a);
1157  nlTest(b);
1158#endif
1159  //nlNormalize(a);
1160  //nlNormalize(b);
1161  if ((SR_HDL(a)==5)||(a==INT_TO_SR(-1))
1162  ||  (SR_HDL(b)==5)||(b==INT_TO_SR(-1))) return INT_TO_SR(1);
1163  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
1164  {
1165    int i=SR_TO_INT(a);
1166    int j=SR_TO_INT(b);
1167    if((i==0)||(j==0))
1168      return INT_TO_SR(1);
1169    int l;
1170    i=ABS(i);
1171    j=ABS(j);
1172    do
1173    {
1174      l=i%j;
1175      i=j;
1176      j=l;
1177    } while (l!=0);
1178    return INT_TO_SR(i);
1179  }
1180  if (((!(SR_HDL(a) & SR_INT))&&(a->s<2))
1181  ||  ((!(SR_HDL(b) & SR_INT))&&(b->s<2))) return INT_TO_SR(1);
1182  number aa=NULL;
1183  if (SR_HDL(a) & SR_INT)
1184  {
1185    aa=nlRInit(SR_TO_INT(a));
1186    a=aa;
1187  }
1188  else
1189  if (SR_HDL(b) & SR_INT)
1190  {
1191    aa=nlRInit(SR_TO_INT(b));
1192    b=aa;
1193  }
1194  result=(number)omAllocBin(rnumber_bin);
1195#if defined(LDEBUG)
1196  result->debug=123456;
1197#endif
1198  mpz_init(&result->z);
1199  mpz_gcd(&result->z,&a->z,&b->z);
1200  nlGmpSimple(&result->z);
1201  result->s = 3;
1202  if (mpz_size1(&result->z)<=MP_SMALL)
1203  {
1204    int ui=(int)mpz_get_si(&result->z);
1205    if ((((ui<<3)>>3)==ui)
1206    && (mpz_cmp_si(&result->z,(long)ui)==0))
1207    {
1208      mpz_clear(&result->z);
1209      omFreeBin((ADDRESS)result, rnumber_bin);
1210      result=INT_TO_SR(ui);
1211    }
1212  }
1213  if (aa!=NULL)
1214  {
1215    mpz_clear(&aa->z);
1216    omFreeBin((ADDRESS)aa, rnumber_bin);
1217  }
1218#ifdef LDEBUG
1219  nlTest(result);
1220#endif
1221  return result;
1222}
1223
1224/*2
1225* simplify x
1226*/
1227void nlNormalize (number &x)
1228{
1229  if ((SR_HDL(x) & SR_INT) ||(x==NULL))
1230    return;
1231#ifdef LDEBUG
1232  if (!nlTest(x)) return;
1233#endif
1234  if (x->s==3)
1235  {
1236    if (mpz_cmp_ui(&x->z,(long)0)==0)
1237    {
1238      nlDelete(&x,currRing);
1239      x=nlInit(0);
1240      return;
1241    }
1242    if (mpz_size1(&x->z)<=MP_SMALL)
1243    {
1244      int ui=(int)mpz_get_si(&x->z);
1245      if ((((ui<<3)>>3)==ui)
1246      && (mpz_cmp_si(&x->z,(long)ui)==0))
1247      {
1248        mpz_clear(&x->z);
1249        omFreeBin((ADDRESS)x, rnumber_bin);
1250        x=INT_TO_SR(ui);
1251        return;
1252      }
1253    }
1254  }
1255  if (x->s!=1) nlGmpSimple(&x->z);
1256  if (x->s==0)
1257  {
1258    BOOLEAN divided=FALSE;
1259    MP_INT gcd;
1260    mpz_init(&gcd);
1261    mpz_gcd(&gcd,&x->z,&x->n);
1262    x->s=1;
1263    if (mpz_cmp_si(&gcd,(long)1)!=0)
1264    {
1265      MP_INT r;
1266      mpz_init(&r);
1267      MPZ_EXACTDIV(&r,&x->z,&gcd);
1268      mpz_set(&x->z,&r);
1269      MPZ_EXACTDIV(&r,&x->n,&gcd);
1270      mpz_set(&x->n,&r);
1271      mpz_clear(&r);
1272      nlGmpSimple(&x->z);
1273      divided=TRUE;
1274    }
1275    mpz_clear(&gcd);
1276    nlGmpSimple(&x->n);
1277    if (mpz_cmp_si(&x->n,(long)1)==0)
1278    {
1279      mpz_clear(&x->n);
1280      if (mpz_size1(&x->z)<=MP_SMALL)
1281      {
1282        int ui=(int)mpz_get_si(&x->z);
1283        if ((((ui<<3)>>3)==ui)
1284        && (mpz_cmp_si(&x->z,(long)ui)==0))
1285        {
1286          mpz_clear(&x->z);
1287#if defined(LDEBUG)
1288          x->debug=654324;
1289#endif
1290          omFreeBin((ADDRESS)x, rnumber_bin);
1291          x=INT_TO_SR(ui);
1292          return;
1293        }
1294      }
1295      x->s=3;
1296    }
1297    else if (divided)
1298    {
1299      _mpz_realloc(&x->n,mpz_size1(&x->n));
1300    }
1301    if (divided) _mpz_realloc(&x->z,mpz_size1(&x->z));
1302  }
1303#ifdef LDEBUG
1304  nlTest(x);
1305#endif
1306}
1307
1308/*2
1309* returns in result->z the lcm(a->z,b->n)
1310*/
1311number nlLcm(number a, number b, const ring r)
1312{
1313  number result;
1314#ifdef LDEBUG
1315  nlTest(a);
1316  nlTest(b);
1317#endif
1318  if ((SR_HDL(b) & SR_INT)
1319  || (b->s==3))
1320  {
1321    // b is 1/(b->n) => b->n is 1 => result is a
1322    return nlCopy(a);
1323  }
1324  number aa=NULL;
1325  if (SR_HDL(a) & SR_INT)
1326  {
1327    aa=nlRInit(SR_TO_INT(a));
1328    a=aa;
1329  }
1330  result=(number)omAllocBin(rnumber_bin);
1331#if defined(LDEBUG)
1332  result->debug=123456;
1333#endif
1334  result->s=3;
1335  MP_INT gcd;
1336  mpz_init(&gcd);
1337  mpz_init(&result->z);
1338  mpz_gcd(&gcd,&a->z,&b->n);
1339  if (mpz_cmp_si(&gcd,(long)1)!=0)
1340  {
1341    MP_INT bt;
1342    mpz_init_set(&bt,&b->n);
1343    MPZ_EXACTDIV(&bt,&bt,&gcd);
1344    mpz_mul(&result->z,&a->z,&bt);
1345    mpz_clear(&bt);
1346  }
1347  else
1348    mpz_mul(&result->z,&a->z,&b->n);
1349  mpz_clear(&gcd);
1350  if (aa!=NULL)
1351  {
1352    mpz_clear(&aa->z);
1353    omFreeBin((ADDRESS)aa, rnumber_bin);
1354  }
1355  nlGmpSimple(&result->z);
1356  if (mpz_size1(&result->z)<=MP_SMALL)
1357  {
1358    int ui=(int)mpz_get_si(&result->z);
1359    if ((((ui<<3)>>3)==ui)
1360    && (mpz_cmp_si(&result->z,(long)ui)==0))
1361    {
1362      mpz_clear(&result->z);
1363      omFreeBin((ADDRESS)result, rnumber_bin);
1364      return INT_TO_SR(ui);
1365    }
1366  }
1367#ifdef LDEBUG
1368  nlTest(result);
1369#endif
1370  return result;
1371}
1372
1373int nlModP(number n, int p)
1374{
1375  if (SR_HDL(n) & SR_INT)
1376  {
1377    int i=SR_TO_INT(n);
1378    if (i<0) return (p-((-i)%p));
1379    return i%p;
1380  }
1381  int iz=mpz_mmod_ui(NULL,&n->z,(unsigned long)p);
1382  if (n->s!=3)
1383  {
1384    int in=mpz_mmod_ui(NULL,&n->n,(unsigned long)p);
1385    return (int)npDiv((number)iz,(number)in);
1386  }
1387  return iz;
1388}
1389
1390/*2
1391* acces to denominator, other 1 for integers
1392*/
1393number   nlGetDenom(number &n)
1394{
1395  if (!(SR_HDL(n) & SR_INT))
1396  {
1397    if (n->s==0)
1398    {
1399      nlNormalize(n);
1400    }
1401    if (!(SR_HDL(n) & SR_INT))
1402    {
1403      if (n->s!=3)
1404      {
1405        number u=(number)omAllocBin(rnumber_bin);
1406        u->s=3;
1407#if defined(LDEBUG)
1408        u->debug=123456;
1409#endif
1410
1411        mpz_init_set(&u->z,&n->n);
1412        {
1413          int ui=(int)mpz_get_si(&u->z);
1414          if ((((ui<<3)>>3)==ui)
1415          && (mpz_cmp_si(&u->z,(long)ui)==0))
1416          {
1417            mpz_clear(&u->z);
1418            omFreeBin((ADDRESS)u, rnumber_bin);
1419            return INT_TO_SR(ui);
1420          }
1421        }
1422        return u;
1423      }
1424    }
1425  }
1426  return INT_TO_SR(1);
1427}
1428
1429/***************************************************************
1430 *
1431 * routines which are needed by Inline(d) routines
1432 *
1433 *******************************************************************/
1434BOOLEAN _nlEqual_aNoImm_OR_bNoImm(number a, number b)
1435{
1436  assume(! (SR_HDL(a) & SR_HDL(b) & SR_INT));
1437//  long - short
1438  BOOLEAN bo;
1439  if (SR_HDL(b) & SR_INT)
1440  {
1441    if (a->s!=0) return FALSE;
1442    number n=b; b=a; a=n;
1443  }
1444//  short - long
1445  if (SR_HDL(a) & SR_INT)
1446  {
1447    if (b->s!=0)
1448      return FALSE;
1449    if (((int)a > 0) && (mpz_isNeg(&b->z)))
1450      return FALSE;
1451    if (((int)a < 0) && (!mpz_isNeg(&b->z)))
1452      return FALSE;
1453    MP_INT  bb;
1454    mpz_init_set(&bb,&b->n);
1455    if ((int)a<0)
1456    {
1457      mpz_neg(&bb,&bb);
1458      mpz_mul_ui(&bb,&bb,(long)-SR_TO_INT(a));
1459    }
1460    else
1461    {
1462      mpz_mul_ui(&bb,&bb,(long)SR_TO_INT(a));
1463    }
1464    bo=(mpz_cmp(&bb,&b->z)==0);
1465    mpz_clear(&bb);
1466    return bo;
1467  }
1468// long - long
1469  if (((a->s==1) && (b->s==3))
1470  ||  ((b->s==1) && (a->s==3)))
1471    return FALSE;
1472  if (mpz_isNeg(&a->z)&&(!mpz_isNeg(&b->z)))
1473    return FALSE;
1474  if (mpz_isNeg(&b->z)&&(!mpz_isNeg(&a->z)))
1475    return FALSE;
1476  nlGmpSimple(&a->z);
1477  nlGmpSimple(&b->z);
1478  if (a->s<2)
1479    nlGmpSimple(&a->n);
1480  if (b->s<2)
1481    nlGmpSimple(&b->n);
1482  MP_INT  aa;
1483  MP_INT  bb;
1484  mpz_init_set(&aa,&a->z);
1485  mpz_init_set(&bb,&b->z);
1486  if (a->s<2) mpz_mul(&bb,&bb,&a->n);
1487  if (b->s<2) mpz_mul(&aa,&aa,&b->n);
1488  bo=(mpz_cmp(&aa,&bb)==0);
1489  mpz_clear(&aa);
1490  mpz_clear(&bb);
1491  return bo;
1492}
1493
1494// copy not immediate number a
1495number _nlCopy_NoImm(number a)
1496{
1497  assume(!((SR_HDL(a) & SR_INT)||(a==NULL)));
1498#ifdef LDEBUG
1499  nlTest(a);
1500#endif
1501  number b=(number)omAllocBin(rnumber_bin);
1502#if defined(LDEBUG)
1503  b->debug=123456;
1504#endif
1505  switch (a->s)
1506  {
1507    case 0:
1508    case 1:
1509            nlGmpSimple(&a->n);
1510            mpz_init_set(&b->n,&a->n);
1511    case 3:
1512            nlGmpSimple(&a->z);
1513            mpz_init_set(&b->z,&a->z);
1514            break;
1515  }
1516  b->s = a->s;
1517#ifdef LDEBUG
1518  nlTest(b);
1519#endif
1520  return b;
1521}
1522
1523void _nlDelete_NoImm(number *a, const ring r)
1524{
1525  switch ((*a)->s)
1526  {
1527      case 0:
1528      case 1:
1529        mpz_clear(&(*a)->n);
1530      case 3:
1531        mpz_clear(&(*a)->z);
1532#ifdef LDEBUG
1533        (*a)->s=2;
1534#endif
1535  }
1536  omFreeBin((ADDRESS) *a, rnumber_bin);
1537}
1538
1539number _nlNeg_NoImm(number a)
1540{
1541  mpz_neg(&a->z,&a->z);
1542  if ((a->s==3) && (mpz_size1(&a->z)<=MP_SMALL))
1543  {
1544    int ui=(int)mpz_get_si(&a->z);
1545    if ((((ui<<3)>>3)==ui)
1546        && (mpz_cmp_si(&a->z,(long)ui)==0))
1547    {
1548      mpz_clear(&a->z);
1549      omFreeBin((ADDRESS)a, rnumber_bin);
1550      a=INT_TO_SR(ui);
1551    }
1552  }
1553#ifdef LDEBUG
1554  nlTest(a);
1555#endif
1556  return a;
1557}
1558
1559number _nlAdd_aNoImm_OR_bNoImm(number a, number b)
1560{
1561  number u=(number)omAllocBin(rnumber_bin);
1562#if defined(LDEBUG)
1563  u->debug=123456;
1564#endif
1565  mpz_init(&u->z);
1566  if (SR_HDL(b) & SR_INT)
1567  {
1568    number x=a;
1569    a=b;
1570    b=x;
1571  }
1572  if (SR_HDL(a) & SR_INT)
1573  {
1574    switch (b->s)
1575    {
1576      case 0:
1577      case 1:/* a:short, b:1 */
1578      {
1579        MP_INT x;
1580        mpz_init(&x);
1581        if ((int)a>0)
1582        {
1583          mpz_mul_ui(&x,&b->n,SR_TO_INT(a));
1584        }
1585        else
1586        {
1587          mpz_mul_ui(&x,&b->n,-SR_TO_INT(a));
1588          mpz_neg(&x,&x);
1589        }
1590        mpz_add(&u->z,&b->z,&x);
1591        mpz_clear(&x);
1592        nlGmpSimple(&u->z);
1593        if (mpz_cmp_ui(&u->z,(long)0)==0)
1594        {
1595          mpz_clear(&u->z);
1596          omFreeBin((ADDRESS)u, rnumber_bin);
1597          return INT_TO_SR(0);
1598        }
1599        if (mpz_cmp(&u->z,&b->n)==0)
1600        {
1601          mpz_clear(&u->z);
1602          omFreeBin((ADDRESS)u, rnumber_bin);
1603          return INT_TO_SR(1);
1604        }
1605        mpz_init_set(&u->n,&b->n);
1606        u->s = 0;
1607        break;
1608      }
1609      case 3:
1610      {
1611        if ((int)a>0)
1612          mpz_add_ui(&u->z,&b->z,SR_TO_INT(a));
1613        else
1614          mpz_sub_ui(&u->z,&b->z,-SR_TO_INT(a));
1615        nlGmpSimple(&u->z);
1616        if (mpz_cmp_ui(&u->z,(long)0)==0)
1617        {
1618          mpz_clear(&u->z);
1619          omFreeBin((ADDRESS)u, rnumber_bin);
1620          return INT_TO_SR(0);
1621        }
1622        //u->s = 3;
1623        if (mpz_size1(&u->z)<=MP_SMALL)
1624        {
1625          int ui=(int)mpz_get_si(&u->z);
1626          if ((((ui<<3)>>3)==ui)
1627          && (mpz_cmp_si(&u->z,(long)ui)==0))
1628          {
1629            mpz_clear(&u->z);
1630            omFreeBin((ADDRESS)u, rnumber_bin);
1631            return INT_TO_SR(ui);
1632          }
1633        }
1634        u->s = 3;
1635        break;
1636      }
1637    }
1638  }
1639  else
1640  {
1641    switch (a->s)
1642    {
1643      case 0:
1644      case 1:
1645      {
1646        switch(b->s)
1647        {
1648          case 0:
1649          case 1:
1650          {
1651            MP_INT x;
1652            MP_INT y;
1653            mpz_init(&x);
1654            mpz_init(&y);
1655            mpz_mul(&x,&b->z,&a->n);
1656            mpz_mul(&y,&a->z,&b->n);
1657            mpz_add(&u->z,&x,&y);
1658            nlGmpSimple(&u->z);
1659            mpz_clear(&x);
1660            mpz_clear(&y);
1661            if (mpz_cmp_ui(&u->z,(long)0)==0)
1662            {
1663              mpz_clear(&u->z);
1664              omFreeBin((ADDRESS)u, rnumber_bin);
1665              return INT_TO_SR(0);
1666            }
1667            mpz_init(&u->n);
1668            mpz_mul(&u->n,&a->n,&b->n);
1669            nlGmpSimple(&u->n);
1670            if (mpz_cmp(&u->z,&u->n)==0)
1671            {
1672               mpz_clear(&u->z);
1673               mpz_clear(&u->n);
1674               omFreeBin((ADDRESS)u, rnumber_bin);
1675               return INT_TO_SR(1);
1676            }
1677            u->s = 0;
1678            break;
1679          }
1680          case 3: /* a:1 b:3 */
1681          {
1682            MP_INT x;
1683            mpz_init(&x);
1684            mpz_mul(&x,&b->z,&a->n);
1685            mpz_add(&u->z,&a->z,&x);
1686            nlGmpSimple(&u->z);
1687            mpz_clear(&x);
1688            if (mpz_cmp_ui(&u->z,(long)0)==0)
1689            {
1690              mpz_clear(&u->z);
1691              omFreeBin((ADDRESS)u, rnumber_bin);
1692              return INT_TO_SR(0);
1693            }
1694            if (mpz_cmp(&u->z,&a->n)==0)
1695            {
1696              mpz_clear(&u->z);
1697              omFreeBin((ADDRESS)u, rnumber_bin);
1698              return INT_TO_SR(1);
1699            }
1700            mpz_init_set(&u->n,&a->n);
1701            u->s = 0;
1702            break;
1703          }
1704        } /*switch (b->s) */
1705        break;
1706      }
1707      case 3:
1708      {
1709        switch(b->s)
1710        {
1711          case 0:
1712          case 1:/* a:3, b:1 */
1713          {
1714            MP_INT x;
1715            mpz_init(&x);
1716            mpz_mul(&x,&a->z,&b->n);
1717            mpz_add(&u->z,&b->z,&x);
1718            nlGmpSimple(&u->z);
1719            mpz_clear(&x);
1720            if (mpz_cmp_ui(&u->z,(long)0)==0)
1721            {
1722              mpz_clear(&u->z);
1723              omFreeBin((ADDRESS)u, rnumber_bin);
1724              return INT_TO_SR(0);
1725            }
1726            if (mpz_cmp(&u->z,&b->n)==0)
1727            {
1728              mpz_clear(&u->z);
1729              omFreeBin((ADDRESS)u, rnumber_bin);
1730              return INT_TO_SR(1);
1731            }
1732            mpz_init_set(&u->n,&b->n);
1733            u->s = 0;
1734            break;
1735          }
1736          case 3:
1737          {
1738            mpz_add(&u->z,&a->z,&b->z);
1739            nlGmpSimple(&u->z);
1740            if (mpz_cmp_ui(&u->z,(long)0)==0)
1741            {
1742              mpz_clear(&u->z);
1743              omFreeBin((ADDRESS)u, rnumber_bin);
1744              return INT_TO_SR(0);
1745            }
1746            if (mpz_size1(&u->z)<=MP_SMALL)
1747            {
1748              int ui=(int)mpz_get_si(&u->z);
1749              if ((((ui<<3)>>3)==ui)
1750              && (mpz_cmp_si(&u->z,(long)ui)==0))
1751              {
1752                mpz_clear(&u->z);
1753                omFreeBin((ADDRESS)u, rnumber_bin);
1754                return INT_TO_SR(ui);
1755              }
1756            }
1757            u->s = 3;
1758            break;
1759          }
1760        }
1761        break;
1762      }
1763    }
1764  }
1765#ifdef LDEBUG
1766  nlTest(u);
1767#endif
1768  return u;
1769}
1770
1771number _nlSub_aNoImm_OR_bNoImm(number a, number b)
1772{
1773  number u=(number)omAllocBin(rnumber_bin);
1774#if defined(LDEBUG)
1775  u->debug=123456;
1776#endif
1777  mpz_init(&u->z);
1778  if (SR_HDL(a) & SR_INT)
1779  {
1780    switch (b->s)
1781    {
1782      case 0:
1783      case 1:/* a:short, b:1 */
1784      {
1785        MP_INT x;
1786        mpz_init(&x);
1787        if ((int)a>0)
1788        {
1789          mpz_mul_ui(&x,&b->n,SR_TO_INT(a));
1790        }
1791        else
1792        {
1793          mpz_mul_ui(&x,&b->n,-SR_TO_INT(a));
1794          mpz_neg(&x,&x);
1795        }
1796        mpz_sub(&u->z,&x,&b->z);
1797        mpz_clear(&x);
1798        if (mpz_cmp_ui(&u->z,(long)0)==0)
1799        {
1800          mpz_clear(&u->z);
1801          omFreeBin((ADDRESS)u, rnumber_bin);
1802          return INT_TO_SR(0);
1803        }
1804        if (mpz_cmp(&u->z,&b->n)==0)
1805        {
1806          mpz_clear(&u->z);
1807          omFreeBin((ADDRESS)u, rnumber_bin);
1808          return INT_TO_SR(1);
1809        }
1810        mpz_init_set(&u->n,&b->n);
1811        u->s = 0;
1812        break;
1813      }
1814      case 3:
1815      {
1816        if ((int)a>0)
1817        {
1818          mpz_sub_ui(&u->z,&b->z,SR_TO_INT(a));
1819          mpz_neg(&u->z,&u->z);
1820        }
1821        else
1822        {
1823          mpz_add_ui(&u->z,&b->z,-SR_TO_INT(a));
1824          mpz_neg(&u->z,&u->z);
1825        }
1826        nlGmpSimple(&u->z);
1827        if (mpz_cmp_ui(&u->z,(long)0)==0)
1828        {
1829          mpz_clear(&u->z);
1830          omFreeBin((ADDRESS)u, rnumber_bin);
1831          return INT_TO_SR(0);
1832        }
1833        //u->s = 3;
1834        if (mpz_size1(&u->z)<=MP_SMALL)
1835        {
1836          int ui=(int)mpz_get_si(&u->z);
1837          if ((((ui<<3)>>3)==ui)
1838          && (mpz_cmp_si(&u->z,(long)ui)==0))
1839          {
1840            mpz_clear(&u->z);
1841            omFreeBin((ADDRESS)u, rnumber_bin);
1842            return INT_TO_SR(ui);
1843          }
1844        }
1845        u->s = 3;
1846        break;
1847      }
1848    }
1849  }
1850  else if (SR_HDL(b) & SR_INT)
1851  {
1852    switch (a->s)
1853    {
1854      case 0:
1855      case 1:/* b:short, a:1 */
1856      {
1857        MP_INT x;
1858        mpz_init(&x);
1859        if ((int)b>0)
1860        {
1861          mpz_mul_ui(&x,&a->n,SR_TO_INT(b));
1862        }
1863        else
1864        {
1865          mpz_mul_ui(&x,&a->n,-SR_TO_INT(b));
1866          mpz_neg(&x,&x);
1867        }
1868        mpz_sub(&u->z,&a->z,&x);
1869        mpz_clear(&x);
1870        if (mpz_cmp_ui(&u->z,(long)0)==0)
1871        {
1872          mpz_clear(&u->z);
1873          omFreeBin((ADDRESS)u, rnumber_bin);
1874          return INT_TO_SR(0);
1875        }
1876        if (mpz_cmp(&u->z,&a->n)==0)
1877        {
1878          mpz_clear(&u->z);
1879          omFreeBin((ADDRESS)u, rnumber_bin);
1880          return INT_TO_SR(1);
1881        }
1882        mpz_init_set(&u->n,&a->n);
1883        u->s = 0;
1884        break;
1885      }
1886      case 3:
1887      {
1888        if ((int)b>0)
1889        {
1890          mpz_sub_ui(&u->z,&a->z,SR_TO_INT(b));
1891        }
1892        else
1893        {
1894          mpz_add_ui(&u->z,&a->z,-SR_TO_INT(b));
1895        }
1896        if (mpz_cmp_ui(&u->z,(long)0)==0)
1897        {
1898          mpz_clear(&u->z);
1899          omFreeBin((ADDRESS)u, rnumber_bin);
1900          return INT_TO_SR(0);
1901        }
1902        //u->s = 3;
1903        nlGmpSimple(&u->z);
1904        if (mpz_size1(&u->z)<=MP_SMALL)
1905        {
1906          int ui=(int)mpz_get_si(&u->z);
1907          if ((((ui<<3)>>3)==ui)
1908          && (mpz_cmp_si(&u->z,(long)ui)==0))
1909          {
1910            mpz_clear(&u->z);
1911            omFreeBin((ADDRESS)u, rnumber_bin);
1912            return INT_TO_SR(ui);
1913          }
1914        }
1915        u->s = 3;
1916        break;
1917      }
1918    }
1919  }
1920  else
1921  {
1922    switch (a->s)
1923    {
1924      case 0:
1925      case 1:
1926      {
1927        switch(b->s)
1928        {
1929          case 0:
1930          case 1:
1931          {
1932            MP_INT x;
1933            MP_INT y;
1934            mpz_init(&x);
1935            mpz_init(&y);
1936            mpz_mul(&x,&b->z,&a->n);
1937            mpz_mul(&y,&a->z,&b->n);
1938            mpz_sub(&u->z,&y,&x);
1939            mpz_clear(&x);
1940            mpz_clear(&y);
1941            if (mpz_cmp_ui(&u->z,(long)0)==0)
1942            {
1943              mpz_clear(&u->z);
1944              omFreeBin((ADDRESS)u, rnumber_bin);
1945              return INT_TO_SR(0);
1946            }
1947            mpz_init(&u->n);
1948            mpz_mul(&u->n,&a->n,&b->n);
1949            if (mpz_cmp(&u->z,&u->n)==0)
1950            {
1951              mpz_clear(&u->z);
1952              mpz_clear(&u->n);
1953              omFreeBin((ADDRESS)u, rnumber_bin);
1954              return INT_TO_SR(1);
1955            }
1956            u->s = 0;
1957            break;
1958          }
1959          case 3: /* a:1, b:3 */
1960          {
1961            MP_INT x;
1962            mpz_init(&x);
1963            mpz_mul(&x,&b->z,&a->n);
1964            mpz_sub(&u->z,&a->z,&x);
1965            mpz_clear(&x);
1966            if (mpz_cmp_ui(&u->z,(long)0)==0)
1967            {
1968              mpz_clear(&u->z);
1969              omFreeBin((ADDRESS)u, rnumber_bin);
1970              return INT_TO_SR(0);
1971            }
1972            if (mpz_cmp(&u->z,&a->n)==0)
1973            {
1974              mpz_clear(&u->z);
1975              omFreeBin((ADDRESS)u, rnumber_bin);
1976              return INT_TO_SR(1);
1977            }
1978            mpz_init_set(&u->n,&a->n);
1979            u->s = 0;
1980            break;
1981          }
1982        }
1983        break;
1984      }
1985      case 3:
1986      {
1987        switch(b->s)
1988        {
1989          case 0:
1990          case 1: /* a:3, b:1 */
1991          {
1992            MP_INT x;
1993            mpz_init(&x);
1994            mpz_mul(&x,&a->z,&b->n);
1995            mpz_sub(&u->z,&x,&b->z);
1996            mpz_clear(&x);
1997            if (mpz_cmp_ui(&u->z,(long)0)==0)
1998            {
1999              mpz_clear(&u->z);
2000              omFreeBin((ADDRESS)u, rnumber_bin);
2001              return INT_TO_SR(0);
2002            }
2003            if (mpz_cmp(&u->z,&b->n)==0)
2004            {
2005              mpz_clear(&u->z);
2006              omFreeBin((ADDRESS)u, rnumber_bin);
2007              return INT_TO_SR(1);
2008            }
2009            mpz_init_set(&u->n,&b->n);
2010            u->s = 0;
2011            break;
2012          }
2013          case 3: /* a:3 , b:3 */
2014          {
2015            mpz_sub(&u->z,&a->z,&b->z);
2016            nlGmpSimple(&u->z);
2017            if (mpz_cmp_ui(&u->z,(long)0)==0)
2018            {
2019              mpz_clear(&u->z);
2020              omFreeBin((ADDRESS)u, rnumber_bin);
2021              return INT_TO_SR(0);
2022            }
2023            //u->s = 3;
2024            if (mpz_size1(&u->z)<=MP_SMALL)
2025            {
2026              int ui=(int)mpz_get_si(&u->z);
2027              if ((((ui<<3)>>3)==ui)
2028              && (mpz_cmp_si(&u->z,(long)ui)==0))
2029              {
2030                mpz_clear(&u->z);
2031                omFreeBin((ADDRESS)u, rnumber_bin);
2032                return INT_TO_SR(ui);
2033              }
2034            }
2035            u->s = 3;
2036            break;
2037          }
2038        }
2039        break;
2040      }
2041    }
2042  }
2043#ifdef LDEBUG
2044  nlTest(u);
2045#endif
2046  return u;
2047}
2048
2049// a and b are intermediate, but a*b not
2050number _nlMult_aImm_bImm_rNoImm(number a, number b)
2051{
2052  number u=(number)omAllocBin(rnumber_bin);
2053#if defined(LDEBUG)
2054  u->debug=123456;
2055#endif
2056  u->s=3;
2057  if ((int)b>0)
2058  {
2059    mpz_init_set_si(&u->z,(long)SR_TO_INT(a));
2060    mpz_mul_ui(&u->z,&u->z,(unsigned long)SR_TO_INT(b));
2061  }
2062  else
2063  {
2064    mpz_init_set_si(&u->z,(long)(-SR_TO_INT(a)));
2065    mpz_mul_ui(&u->z,&u->z,(long)(-SR_TO_INT(b)));
2066  }
2067#ifdef LDEBUG
2068  nlTest(u);
2069#endif
2070  return u;
2071}
2072
2073// a or b are not immediate
2074number _nlMult_aNoImm_OR_bNoImm(number a, number b)
2075{
2076  assume(! (SR_HDL(a) & SR_HDL(b) & SR_INT));
2077  number u=(number)omAllocBin(rnumber_bin);
2078#if defined(LDEBUG)
2079  u->debug=123456;
2080#endif
2081  mpz_init(&u->z);
2082  if (SR_HDL(b) & SR_INT)
2083  {
2084    number x=a;
2085    a=b;
2086    b=x;
2087  }
2088  if (SR_HDL(a) & SR_INT)
2089  {
2090    u->s=b->s;
2091    if (u->s==1) u->s=0;
2092    if ((int)a>0)
2093    {
2094      mpz_mul_ui(&u->z,&b->z,(unsigned long)SR_TO_INT(a));
2095    }
2096    else
2097    {
2098      if (a==INT_TO_SR(-1))
2099      {
2100        mpz_set(&u->z,&b->z);
2101        mpz_neg(&u->z,&u->z);
2102        u->s=b->s;
2103      }
2104      else
2105      {
2106        mpz_mul_ui(&u->z,&b->z,(unsigned long)-SR_TO_INT(a));
2107        mpz_neg(&u->z,&u->z);
2108      }
2109    }
2110    nlGmpSimple(&u->z);
2111    if (u->s<2)
2112    {
2113      if (mpz_cmp(&u->z,&b->n)==0)
2114      {
2115        mpz_clear(&u->z);
2116        omFreeBin((ADDRESS)u, rnumber_bin);
2117        return INT_TO_SR(1);
2118      }
2119      mpz_init_set(&u->n,&b->n);
2120    }
2121    else //u->s==3
2122    {
2123      if (mpz_size1(&u->z)<=MP_SMALL)
2124      {
2125        int ui=(int)mpz_get_si(&u->z);
2126        if ((((ui<<3)>>3)==ui)
2127            && (mpz_cmp_si(&u->z,(long)ui)==0))
2128        {
2129          mpz_clear(&u->z);
2130          omFreeBin((ADDRESS)u, rnumber_bin);
2131          return INT_TO_SR(ui);
2132        }
2133      }
2134    }
2135  }
2136  else
2137  {
2138    mpz_mul(&u->z,&a->z,&b->z);
2139    u->s = 0;
2140    if(a->s==3)
2141    {
2142      if(b->s==3)
2143      {
2144        u->s = 3;
2145      }
2146      else
2147      {
2148        if (mpz_cmp(&u->z,&b->n)==0)
2149        {
2150          mpz_clear(&u->z);
2151          omFreeBin((ADDRESS)u, rnumber_bin);
2152          return INT_TO_SR(1);
2153        }
2154        mpz_init_set(&u->n,&b->n);
2155      }
2156    }
2157    else
2158    {
2159      if(b->s==3)
2160      {
2161        if (mpz_cmp(&u->z,&a->n)==0)
2162        {
2163          mpz_clear(&u->z);
2164          omFreeBin((ADDRESS)u, rnumber_bin);
2165          return INT_TO_SR(1);
2166        }
2167        mpz_init_set(&u->n,&a->n);
2168      }
2169      else
2170      {
2171        mpz_init(&u->n);
2172        mpz_mul(&u->n,&a->n,&b->n);
2173        if (mpz_cmp(&u->z,&u->n)==0)
2174        {
2175          mpz_clear(&u->z);
2176          mpz_clear(&u->n);
2177          omFreeBin((ADDRESS)u, rnumber_bin);
2178          return INT_TO_SR(1);
2179        }
2180      }
2181    }
2182  }
2183#ifdef LDEBUG
2184  nlTest(u);
2185#endif
2186  return u;
2187}
2188
2189/*2
2190* z := i
2191*/
2192number nlRInit (int i)
2193{
2194  number z=(number)omAllocBin(rnumber_bin);
2195#if defined(LDEBUG)
2196  z->debug=123456;
2197#endif
2198  mpz_init_set_si(&z->z,(long)i);
2199  z->s = 3;
2200  return z;
2201}
2202
2203/*2
2204* z := i/j
2205*/
2206number nlInit2 (int i, int j)
2207{
2208  number z=(number)omAllocBin(rnumber_bin);
2209#if defined(LDEBUG)
2210  z->debug=123456;
2211#endif
2212  mpz_init_set_si(&z->z,(long)i);
2213  mpz_init_set_si(&z->n,(long)j);
2214  z->s = 0;
2215  nlNormalize(z);
2216  return z;
2217}
2218
2219#else // DO_LINLINE
2220
2221// declare immedate routines
2222number nlRInit (int i);
2223BOOLEAN _nlEqual_aNoImm_OR_bNoImm(number a, number b);
2224number  _nlCopy_NoImm(number a);
2225void    _nlDelete_NoImm(number *a, const ring r);
2226number  _nlNeg_NoImm(number a);
2227number  _nlAdd_aNoImm_OR_bNoImm(number a, number b);
2228number  _nlSub_aNoImm_OR_bNoImm(number a, number b);
2229number  _nlMult_aNoImm_OR_bNoImm(number a, number b);
2230number  _nlMult_aImm_bImm_rNoImm(number a, number b);
2231
2232#endif
2233
2234
2235/***************************************************************
2236 *
2237 * Routines which might be inlined by p_Numbers.h
2238 *
2239 *******************************************************************/
2240#if defined(DO_LINLINE) || !defined(P_NUMBERS_H)
2241
2242// routines which are always inlined/static
2243
2244/*2
2245* a = b ?
2246*/
2247LINLINE BOOLEAN nlEqual (number a, number b)
2248{
2249#ifdef LDEBUG
2250  nlTest(a);
2251  nlTest(b);
2252#endif
2253// short - short
2254  if (SR_HDL(a) & SR_HDL(b) & SR_INT) return a==b;
2255  return _nlEqual_aNoImm_OR_bNoImm(a, b);
2256}
2257
2258
2259LINLINE number nlInit (int i)
2260{
2261  number n;
2262  if ( ((i << 3) >> 3) == i ) n=INT_TO_SR(i);
2263  else                        n=nlRInit(i);
2264#ifdef LDEBUG
2265  nlTest(n);
2266#endif
2267  return n;
2268}
2269
2270
2271/*2
2272* a == 1 ?
2273*/
2274LINLINE BOOLEAN nlIsOne (number a)
2275{
2276#ifdef LDEBUG
2277  if (a==NULL) return FALSE;
2278  nlTest(a);
2279#endif
2280  if (SR_HDL(a) & SR_INT) return (a==INT_TO_SR(1));
2281  return FALSE;
2282}
2283
2284LINLINE BOOLEAN nlIsZero (number a)
2285{
2286  return (a==INT_TO_SR(0));
2287}
2288
2289/*2
2290* copy a to b
2291*/
2292LINLINE number nlCopy(number a)
2293{
2294  if ((SR_HDL(a) & SR_INT)||(a==NULL))
2295  {
2296    return a;
2297  }
2298  return _nlCopy_NoImm(a);
2299}
2300
2301
2302LINLINE void nlNew (number * r)
2303{
2304  *r=NULL;
2305}
2306
2307/*2
2308* delete a
2309*/
2310LINLINE void nlDelete (number * a, const ring r)
2311{
2312  if (*a!=NULL)
2313  {
2314#ifdef LDEBUG
2315    nlTest(*a);
2316#endif
2317    if ((SR_HDL(*a) & SR_INT)==0)
2318      _nlDelete_NoImm(a,r);
2319    *a=NULL;
2320  }
2321}
2322
2323/*2
2324* za:= - za
2325*/
2326LINLINE number nlNeg (number a)
2327{
2328#ifdef LDEBUG
2329  nlTest(a);
2330#endif
2331  if(SR_HDL(a) &SR_INT)
2332  {
2333    int r=SR_TO_INT(a);
2334    if (r==(-(1<<28))) a=nlRInit(1<<28);
2335    else               a=INT_TO_SR(-r);
2336    return a;
2337  }
2338  return _nlNeg_NoImm(a);
2339}
2340
2341/*2
2342* u:= a + b
2343*/
2344LINLINE number nlAdd (number a, number b)
2345{
2346  number u;
2347  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2348  {
2349    int r=SR_HDL(a)+SR_HDL(b)-1;
2350    if ( ((r << 1) >> 1) == r )
2351      return (number)r;
2352    else
2353      return nlRInit(SR_TO_INT(r));
2354  }
2355  return _nlAdd_aNoImm_OR_bNoImm(a, b);
2356}
2357
2358LINLINE number nlMult (number a, number b)
2359{
2360#ifdef LDEBUG
2361  nlTest(a);
2362  nlTest(b);
2363#endif
2364  if (a==INT_TO_SR(0)) return INT_TO_SR(0);
2365  if (b==INT_TO_SR(0)) return INT_TO_SR(0);
2366  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2367  {
2368    int r=(SR_HDL(a)-1)*(SR_HDL(b)>>1);
2369    if ((r/(SR_HDL(b)>>1))==(SR_HDL(a)-1))
2370    {
2371      number u=((number) ((r>>1)+SR_INT));
2372      if (((SR_HDL(u)<<1)>>1)==SR_HDL(u)) return (u);
2373      return nlRInit(SR_HDL(u)>>2);
2374    }
2375    return _nlMult_aImm_bImm_rNoImm(a, b);
2376  }
2377  return _nlMult_aNoImm_OR_bNoImm(a, b);
2378}
2379
2380
2381/*2
2382* u:= a - b
2383*/
2384LINLINE number nlSub (number a, number b)
2385{
2386  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2387  {
2388    int r=SR_HDL(a)-SR_HDL(b)+1;
2389    if ( ((r << 1) >> 1) == r )
2390    {
2391      return (number)r;
2392    }
2393    else
2394      return nlRInit(SR_TO_INT(r));
2395  }
2396  return _nlSub_aNoImm_OR_bNoImm(a, b);
2397}
2398
2399
2400
2401#endif // DO_LINLINE
2402
2403#endif // LONGRAT_CC
Note: See TracBrowser for help on using the repository browser.