source: git/kernel/longrat.cc @ 611871

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