source: git/Singular/longrat.cc @ 5de8c8

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