source: git/kernel/longrat.cc @ 246d15

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