source: git/Singular/longrat.cc @ f4f6b4

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