source: git/kernel/longrat.cc @ 64cce0

spielwiese
Last change on this file since 64cce0 was 64cce0, checked in by Hans Schoenemann <hannes@…>, 13 years ago
nlFarey was missing debug hints git-svn-id: file:///usr/local/Singular/svn/trunk@13921 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 48.5 KB
RevLine 
[35aab3]1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
[341696]4/* $Id$ */
[35aab3]5/*
6* ABSTRACT: computation with long rational numbers (Hubert Grassmann)
7*/
8
[246d15]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
[35aab3]42#ifndef LONGRAT_CC
43#define LONGRAT_CC
44
45#include <string.h>
46#include <float.h>
[b1dfaf]47#include <omalloc/omalloc.h>
[599326]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>
[35aab3]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))
[46f6af6]96/*#define SR_INT    1L*/
[35aab3]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
[106406]108void    _nlDelete_NoImm(number *a);
[35aab3]109
110/***************************************************************
111 *
112 * Routines which are never inlined by p_Numbers.h
113 *
114 *******************************************************************/
115#ifndef P_NUMBERS_H
116
[246d15]117number nlShort3_noinline(number x) // assume x->s==3
118{
119  return nlShort3(x);
120}
121
[35aab3]122omBin rnumber_bin = omGetSpecBin(sizeof(snumber));
123
[eb059c5]124number nlOne=INT_TO_SR(1);
[35aab3]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
[cf74cd6]139static ring nlMapRing;
[35aab3]140static number nlMapP(number from)
141{
142  number to;
[8391d8]143  to = nlInit(npInt(from,nlMapRing), currRing);
[35aab3]144  return to;
145}
146
147static number nlMapLongR(number from);
148static number nlMapR(number from);
149
[894f5b1]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
[a604c3]160  mpz_init_set(z->z,(mpz_ptr) from);
[20704f]161  //mpz_init_set_ui(&z->n,1);
[894f5b1]162  z->s = 3;
[246d15]163  z=nlShort3(z);
[894f5b1]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
[a604c3]176  mpz_init_set_ui(z->z,(unsigned long) from);
[894f5b1]177  z->s = 3;
[246d15]178  z=nlShort3(z);
[894f5b1]179  return z;
180}
181#endif
182
[208e0c]183nMapFunc nlSetMap(const ring src, const ring dst)
[35aab3]184{
185  if (rField_is_Q(src))
186  {
187    return nlCopy;
188  }
[cf74cd6]189  nlMapRing=src;
[35aab3]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  }
[894f5b1]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
[35aab3]212  return NULL;
213}
214
215#ifdef LDEBUG
[85e68dd]216BOOLEAN nlDBTest(number a, const char *f,const int l)
[35aab3]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);
[7447d8]224  if ((((long)a)&3L)==3L)
[35aab3]225  {
226    Print(" !!longrat:ptr(3) in %s:%d\n",f,l);
227    return FALSE;
228  }
[7447d8]229  if ((((long)a)&3L)==1L)
[35aab3]230  {
[246d15]231    if (((((LONG)(long)a)<<1)>>1)!=((LONG)(long)a))
[35aab3]232    {
[2132395]233      Print(" !!longrat:arith:%lx in %s:%d\n",(long)a, f,l);
[35aab3]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  }
[a604c3]250  omCheckAddrSize(a->z[0]._mp_d,a->z[0]._mp_alloc*BYTES_PER_MP_LIMB);
251  if (a->z[0]._mp_alloc==0)
[2132395]252    Print("!!longrat:z->alloc=0 in %s:%d\n",f,l);
[35aab3]253
254  if (a->s<2)
255  {
[a604c3]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)
[2132395]258      Print("!!longrat:n->alloc=0 in %s:%d\n",f,l);
[a604c3]259    if ((mpz_size1(a->n) ==1) && (mpz_cmp_si(a->n,(long)1)==0))
[35aab3]260    {
261      Print("!!longrat:integer as rational in %s:%d\n",f,l);
[8fd3bd5]262      mpz_clear(a->n); a->s=3;
[35aab3]263      return FALSE;
264    }
[a604c3]265    else if (mpz_isNeg(a->n))
[35aab3]266    {
267      Print("!!longrat:div. by negative in %s:%d\n",f,l);
[a604c3]268      mpz_neg(a->z,a->z);
269      mpz_neg(a->n,a->n);
[35aab3]270      return FALSE;
271    }
272    return TRUE;
273  }
[9257fe]274  //if (a->s==2)
275  //{
276  //  Print("!!longrat:s=2 in %s:%d\n",f,l);
277  //  return FALSE;
278  //}
[a604c3]279  if (mpz_size1(a->z)>MP_SMALL) return TRUE;
[246d15]280  LONG ui=(int)mpz_get_si(a->z);
[35aab3]281  if ((((ui<<3)>>3)==ui)
[a604c3]282  && (mpz_cmp_si(a->z,(long)ui)==0))
[35aab3]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
[246d15]292number nlRInit (long i);
[35aab3]293
294static number nlMapR(number from)
295{
296  double f=nrFloat(from);
[eb059c5]297  if (f==0.0) return INT_TO_SR(0);
[35aab3]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);
[a604c3]314  mpz_set_d(r->z,f);
[35aab3]315  memcpy4(&(r->n),&h1,sizeof(h1));
316  r->s=0; /* not normalized */
[3ec923]317  if(f_sign==-1) r=nlNeg(r);
[35aab3]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;
[a604c3]327  mpz_ptr dest,ndest;
[35aab3]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)
[eb059c5]334    return INT_TO_SR(0);
[35aab3]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
[a604c3]355  dest = res->z;
[35aab3]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;
[a604c3]367    ndest = res->n;
[35aab3]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);
[246d15]388  else
[35aab3]389  {
390    // res is new, res->ref is 1
[246d15]391    res=nlShort3(res);
[35aab3]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//  memcpy4(&(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//    memcpy4(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//      memcpy4(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//      memcpy4(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 */
[a604c3]468  int s=a->z[0]._mp_alloc;
[790096]469//  while ((s>0) &&(a->z._mp_d[s]==0L)) s--;
[e08bce]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
[790096]474//  s++;
[35aab3]475  if (a->s<2)
476  {
[a604c3]477    int d=a->n[0]._mp_alloc;
[790096]478//    while ((d>0) && (a->n._mp_d[d]==0L)) d--;
[e08bce]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
[1da0b5]483    s+=d;
[35aab3]484  }
485  return s;
486}
487
488/*2
489* convert number to int
490*/
[cf74cd6]491int nlInt(number &i, const ring r)
[35aab3]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  {
[a604c3]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;
[35aab3]501    return ul;
502  }
[a604c3]503  mpz_t tmp;
[35aab3]504  int ul;
[a604c3]505  mpz_init(tmp);
506  MPZ_DIV(tmp,i->z,i->n);
507  if(mpz_size1(tmp)>MP_SMALL) ul=0;
[35aab3]508  else
509  {
[a604c3]510    ul=(int)mpz_get_si(tmp);
511    if (mpz_cmp_si(tmp,(long)ul)!=0) ul=0;
[35aab3]512  }
[a604c3]513  mpz_clear(tmp);
[35aab3]514  return ul;
515}
516
[7f7573]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);
[a604c3]530  MPZ_DIV(tmp->z,i->z,i->n);
[246d15]531  tmp=nlShort3(tmp);
[7f7573]532  return tmp;
533}
534
[35aab3]535/*
536* 1/a
537*/
538number nlInvers(number a)
539{
540  nlTest(a);
541  number n;
542  if (SR_HDL(a) & SR_INT)
543  {
[246d15]544    if ((a==INT_TO_SR(1L)) || (a==INT_TO_SR(-1L)))
[35aab3]545    {
546      return a;
547    }
548    if (nlIsZero(a))
549    {
[b7e838]550      WerrorS(nDivBy0);
[35aab3]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;
[7447d8]558    if ((long)a>0L)
[35aab3]559    {
[a604c3]560      mpz_init_set_si(n->z,(long)1);
561      mpz_init_set_si(n->n,(long)SR_TO_INT(a));
[35aab3]562    }
563    else
564    {
[a604c3]565      mpz_init_set_si(n->z,(long)-1);
566      mpz_init_set_si(n->n,(long)-SR_TO_INT(a));
[35aab3]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;
[a604c3]577    mpz_init_set(n->n,a->z);
[35aab3]578    switch (a->s)
579    {
580      case 0:
581      case 1:
[a604c3]582              mpz_init_set(n->z,a->n);
583              if (mpz_isNeg(n->n)) /* && n->s<2*/
[35aab3]584              {
[a604c3]585                mpz_neg(n->z,n->z);
586                mpz_neg(n->n,n->n);
[35aab3]587              }
[a604c3]588              if (mpz_cmp_si(n->n,(long)1)==0)
[35aab3]589              {
[a604c3]590                mpz_clear(n->n);
[35aab3]591                n->s=3;
[246d15]592                n=nlShort3(n);
[35aab3]593              }
594              break;
595      case 3:
596              n->s=1;
[a604c3]597              if (mpz_isNeg(n->n)) /* && n->s<2*/
[35aab3]598              {
[a604c3]599                mpz_neg(n->n,n->n);
600                mpz_init_set_si(n->z,(long)-1);
[35aab3]601              }
602              else
603              {
[a604c3]604                mpz_init_set_si(n->z,(long)1);
[35aab3]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  {
[b7e838]621    WerrorS(nDivBy0);
[35aab3]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)   */
[246d15]630    if ((a==INT_TO_SR(-(POW_2_28)))&&(b==INT_TO_SR(-1L)))
[35aab3]631    {
[246d15]632      return nlRInit(POW_2_28);
[35aab3]633    }
[246d15]634    long aa=SR_TO_INT(a);
635    long bb=SR_TO_INT(b);
[35aab3]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
[a604c3]648  mpz_init(u->z);
[35aab3]649  /* u=a/b */
650  u->s = 3;
[a604c3]651  MPZ_EXACTDIV(u->z,a->z,b->z);
[35aab3]652  if (bb!=NULL)
653  {
[a604c3]654    mpz_clear(bb->z);
[35aab3]655#if defined(LDEBUG)
656    bb->debug=654324;
657#endif
658    omFreeBin((ADDRESS)bb, rnumber_bin);
659  }
[246d15]660  u=nlShort3(u);
[35aab3]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  {
[b7e838]672    WerrorS(nDivBy0);
[35aab3]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)   */
[246d15]681    if ((a==INT_TO_SR(-(POW_2_28)))&&(b==INT_TO_SR(-1L)))
[35aab3]682    {
[246d15]683      return nlRInit(POW_2_28);
[35aab3]684    }
[246d15]685    long aa=SR_TO_INT(a);
686    long bb=SR_TO_INT(b);
[bb9a5a]687    return INT_TO_SR(aa/bb);
[35aab3]688  }
689  if (SR_HDL(a) & SR_INT)
690  {
691    /* the small int -(1<<28) divided by 2^28 is 1   */
[246d15]692    if (a==INT_TO_SR(-(POW_2_28)))
[35aab3]693    {
[246d15]694      if(mpz_cmp_si(b->z,(POW_2_28))==0)
[35aab3]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
[98bda9]712  assume(a->s==3);
713  assume(b->s==3);
[a604c3]714  mpz_init_set(u->z,a->z);
[35aab3]715  /* u=u/b */
716  u->s = 3;
[a604c3]717  MPZ_DIV(u->z,u->z,b->z);
[35aab3]718  if (bb!=NULL)
719  {
[a604c3]720    mpz_clear(bb->z);
[35aab3]721#if defined(LDEBUG)
722    bb->debug=654324;
723#endif
724    omFreeBin((ADDRESS)bb, rnumber_bin);
725  }
[246d15]726  u=nlShort3(u);
[35aab3]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  {
[b7e838]738    WerrorS(nDivBy0);
[35aab3]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  {
[7447d8]746    if ((long)a>0L)
[35aab3]747    {
[7447d8]748      if ((long)b>0L)
[35aab3]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    {
[7447d8]755      if ((long)b>0L)
[35aab3]756      {
[246d15]757        long i=(-SR_TO_INT(a))%SR_TO_INT(b);
758        if ( i != 0L ) i = (SR_TO_INT(b))-i;
[35aab3]759        return INT_TO_SR(i);
760      }
761      else
762      {
[246d15]763        long i=(-SR_TO_INT(a))%(-SR_TO_INT(b));
764        if ( i != 0L ) i = (-SR_TO_INT(b))-i;
[35aab3]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) */
[7447d8]772    if ((long)a<0L)
[35aab3]773    {
[a604c3]774      if (mpz_isNeg(b->z))
[35aab3]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
[a604c3]792  mpz_init(u->z);
[35aab3]793  u->s = 3;
[a604c3]794  mpz_mod(u->z,a->z,b->z);
[35aab3]795  if (bb!=NULL)
796  {
[a604c3]797    mpz_clear(bb->z);
[35aab3]798#if defined(LDEBUG)
799    bb->debug=654324;
800#endif
801    omFreeBin((ADDRESS)bb, rnumber_bin);
802  }
[a604c3]803  if (mpz_isNeg(u->z))
[35aab3]804  {
[a604c3]805    if (mpz_isNeg(b->z))
806      mpz_sub(u->z,u->z,b->z);
[35aab3]807    else
[a604c3]808      mpz_add(u->z,u->z,b->z);
[35aab3]809  }
[246d15]810  u=nlShort3(u);
[35aab3]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  {
[b7e838]823    WerrorS(nDivBy0);
[35aab3]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  {
[246d15]834    long i=SR_TO_INT(a);
835    long j=SR_TO_INT(b);
836    long r=i%j;
[35aab3]837    if (r==0)
838    {
839      omFreeBin((ADDRESS)u, rnumber_bin);
840      return INT_TO_SR(i/j);
841    }
[a604c3]842    mpz_init_set_si(u->z,(long)i);
843    mpz_init_set_si(u->n,(long)j);
[35aab3]844  }
845  else
846  {
[a604c3]847    mpz_init(u->z);
[35aab3]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      {
[a604c3]854        mpz_mul_si(u->z,b->n,SR_TO_INT(a));
[35aab3]855      }
856      else
857      // short a / long z -> a/z
858      {
[a604c3]859        mpz_set_si(u->z,SR_TO_INT(a));
[35aab3]860      }
[a604c3]861      if (mpz_cmp(u->z,b->z)==0)
[35aab3]862      {
[a604c3]863        mpz_clear(u->z);
[35aab3]864        omFreeBin((ADDRESS)u, rnumber_bin);
865        return INT_TO_SR(1);
866      }
[a604c3]867      mpz_init_set(u->n,b->z);
[35aab3]868    }
869// ---------- long / short ------------------------------------
870    else if (SR_HDL(b) & SR_INT)
871    {
[a604c3]872      mpz_set(u->z,a->z);
[35aab3]873      // (z/n) / b -> z/(n*b)
874      if (a->s<2)
875      {
[a604c3]876        mpz_init_set(u->n,a->n);
[7447d8]877        if ((long)b>0L)
[a604c3]878          mpz_mul_ui(u->n,u->n,SR_TO_INT(b));
[35aab3]879        else
880        {
[a604c3]881          mpz_mul_ui(u->n,u->n,-SR_TO_INT(b));
882          mpz_neg(u->z,u->z);
[35aab3]883        }
884      }
885      else
886      // long z / short b -> z/b
887      {
[a604c3]888        //mpz_set(u->z,a->z);
889        mpz_init_set_si(u->n,SR_TO_INT(b));
[35aab3]890      }
891    }
892// ---------- long / long ------------------------------------
893    else
894    {
[a604c3]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);
[35aab3]899    }
900  }
[a604c3]901  if (mpz_isNeg(u->n))
[35aab3]902  {
[a604c3]903    mpz_neg(u->z,u->z);
904    mpz_neg(u->n,u->n);
[35aab3]905  }
[a604c3]906  if (mpz_cmp_si(u->n,(long)1)==0)
[35aab3]907  {
[a604c3]908    mpz_clear(u->n);
[35aab3]909    u->s=3;
[246d15]910    u=nlShort3(u);
[35aab3]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{
[6242bb3]921  *u = INT_TO_SR(0); // 0^e, e!=0
[35aab3]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    }
[ee7dcf]931    else if (x->s==0)
932      nlNormalize(x);
[35aab3]933    *u=(number)omAllocBin(rnumber_bin);
934#if defined(LDEBUG)
935    (*u)->debug=123456;
936#endif
[a604c3]937    mpz_init((*u)->z);
938    mpz_pow_ui((*u)->z,x->z,(unsigned long)exp);
[35aab3]939    if (x->s<2)
940    {
[a604c3]941      if (mpz_cmp_si(x->n,(long)1)==0)
[35aab3]942      {
943        x->s=3;
[a604c3]944        mpz_clear(x->n);
[35aab3]945      }
946      else
947      {
[a604c3]948        mpz_init((*u)->n);
949        mpz_pow_ui((*u)->n,x->n,(unsigned long)exp);
[35aab3]950      }
951    }
952    (*u)->s = x->s;
[246d15]953    if ((*u)->s==3) *u=nlShort3(*u);
[35aab3]954    if (aa!=NULL)
955    {
[a604c3]956      mpz_clear(aa->z);
[35aab3]957      omFreeBin((ADDRESS)aa, rnumber_bin);
958    }
959  }
[6242bb3]960  else if (exp==0)
961    *u = INT_TO_SR(1); // 0^0
[35aab3]962#ifdef LDEBUG
[deca7f6]963  if (exp<0) Print("nlPower: neg. exp. %d\n",exp);
[35aab3]964  nlTest(*u);
965#endif
966}
967
968
969/*2
970* za >= 0 ?
971*/
972BOOLEAN nlGreaterZero (number a)
973{
974  nlTest(a);
[246d15]975  if (SR_HDL(a) & SR_INT) return SR_HDL(a)>1L /* represents number(0) */;
[a604c3]976  return (!mpz_isNeg(a->z));
[35aab3]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
[246d15]1003  //if (SR_HDL(a) & SR_INT) return (a==INT_TO_SR(-1L));
[5f4ae4]1004  //return FALSE;
[246d15]1005  return  (a==INT_TO_SR(-1L));
[35aab3]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);
[246d15]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);
[f553f3]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);
[35aab3]1025  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
1026  {
[246d15]1027    long i=SR_TO_INT(a);
1028    long j=SR_TO_INT(b);
1029    if((i==0L)||(j==0L))
[35aab3]1030      return INT_TO_SR(1);
[246d15]1031    long l;
[35aab3]1032    i=ABS(i);
1033    j=ABS(j);
1034    do
1035    {
1036      l=i%j;
1037      i=j;
1038      j=l;
[246d15]1039    } while (l!=0L);
[35aab3]1040    return INT_TO_SR(i);
1041  }
1042  if (((!(SR_HDL(a) & SR_INT))&&(a->s<2))
1043  ||  ((!(SR_HDL(b) & SR_INT))&&(b->s<2))) return INT_TO_SR(1);
1044  if (SR_HDL(a) & SR_INT)
1045  {
[a604c3]1046    unsigned long t=mpz_gcd_ui(NULL,b->z,ABS(SR_TO_INT(a)));
[246d15]1047    return INT_TO_SR(t);
[35aab3]1048  }
1049  else
1050  if (SR_HDL(b) & SR_INT)
1051  {
[a604c3]1052    unsigned long t=mpz_gcd_ui(NULL,a->z,ABS(SR_TO_INT(b)));
[246d15]1053    return INT_TO_SR(t);
[35aab3]1054  }
1055  else
1056  {
[ea66a97]1057    result=(number)omAllocBin(rnumber_bin);
[a604c3]1058    mpz_init(result->z);
1059    mpz_gcd(result->z,a->z,b->z);
[ea66a97]1060    result->s = 3;
1061  #ifdef LDEBUG
1062    result->debug=123456;
1063  #endif
[246d15]1064    result=nlShort3(result);
[35aab3]1065  }
[246d15]1066  nlTest(result);
[35aab3]1067  return result;
1068}
1069
[18057e]1070number nlShort1(number x) // assume x->s==0/1
[e8a0aa]1071{
[18057e]1072  assume(x->s<2);
[a604c3]1073  if (mpz_cmp_ui(x->z,(long)0)==0)
[e8a0aa]1074  {
[106406]1075    _nlDelete_NoImm(&x);
[e8a0aa]1076    return INT_TO_SR(0);
1077  }
[18057e]1078  if (x->s<2)
1079  {
[a604c3]1080    if (mpz_cmp(x->z,x->n)==0)
[18057e]1081    {
[106406]1082      _nlDelete_NoImm(&x);
[18057e]1083      return INT_TO_SR(1);
1084    }
1085  }
1086  return x;
1087}
[35aab3]1088/*2
1089* simplify x
1090*/
1091void nlNormalize (number &x)
1092{
1093  if ((SR_HDL(x) & SR_INT) ||(x==NULL))
1094    return;
1095  if (x->s==3)
1096  {
[246d15]1097    x=nlShort3_noinline(x);
[b72f2d]1098    nlTest(x);
[18057e]1099    return;
[35aab3]1100  }
[3ccafbf]1101  else if (x->s==0)
[35aab3]1102  {
[a604c3]1103    if (mpz_cmp_si(x->n,(long)1)==0)
[35aab3]1104    {
[a604c3]1105      mpz_clear(x->n);
[3ccafbf]1106      x->s=3;
[246d15]1107      x=nlShort3(x);
[eb059c5]1108    }
[3ccafbf]1109    else
[eb059c5]1110    {
[a604c3]1111      mpz_t gcd;
1112      mpz_init(gcd);
1113      mpz_gcd(gcd,x->z,x->n);
[3ccafbf]1114      x->s=1;
[a604c3]1115      if (mpz_cmp_si(gcd,(long)1)!=0)
[eb059c5]1116      {
[a604c3]1117        mpz_t r;
1118        mpz_init(r);
1119        MPZ_EXACTDIV(r,x->z,gcd);
1120        mpz_set(x->z,r);
1121        MPZ_EXACTDIV(r,x->n,gcd);
1122        mpz_set(x->n,r);
1123        mpz_clear(r);
1124        if (mpz_cmp_si(x->n,(long)1)==0)
[3ccafbf]1125        {
[a604c3]1126          mpz_clear(x->n);
[3ccafbf]1127          x->s=3;
[246d15]1128          x=nlShort3_noinline(x);
[3ccafbf]1129        }
[eb059c5]1130      }
[a604c3]1131      mpz_clear(gcd);
[35aab3]1132    }
1133  }
1134  nlTest(x);
1135}
1136
1137/*2
1138* returns in result->z the lcm(a->z,b->n)
1139*/
1140number nlLcm(number a, number b, const ring r)
1141{
1142  number result;
1143  nlTest(a);
1144  nlTest(b);
1145  if ((SR_HDL(b) & SR_INT)
1146  || (b->s==3))
1147  {
1148    // b is 1/(b->n) => b->n is 1 => result is a
1149    return nlCopy(a);
1150  }
1151  result=(number)omAllocBin(rnumber_bin);
1152#if defined(LDEBUG)
1153  result->debug=123456;
1154#endif
1155  result->s=3;
[a604c3]1156  mpz_t gcd;
1157  mpz_init(gcd);
1158  mpz_init(result->z);
[35aab3]1159  if (SR_HDL(a) & SR_INT)
[a604c3]1160    mpz_gcd_ui(gcd,b->n,ABS(SR_TO_INT(a)));
[35aab3]1161  else
[a604c3]1162    mpz_gcd(gcd,a->z,b->n);
1163  if (mpz_cmp_si(gcd,(long)1)!=0)
[35aab3]1164  {
[a604c3]1165    mpz_t bt;
1166    mpz_init_set(bt,b->n);
1167    MPZ_EXACTDIV(bt,bt,gcd);
[35aab3]1168    if (SR_HDL(a) & SR_INT)
[a604c3]1169      mpz_mul_si(result->z,bt,SR_TO_INT(a));
[35aab3]1170    else
[a604c3]1171      mpz_mul(result->z,bt,a->z);
1172    mpz_clear(bt);
[35aab3]1173  }
1174  else
1175    if (SR_HDL(a) & SR_INT)
[a604c3]1176      mpz_mul_si(result->z,b->n,SR_TO_INT(a));
[35aab3]1177    else
[a604c3]1178      mpz_mul(result->z,b->n,a->z);
1179  mpz_clear(gcd);
[246d15]1180  result=nlShort3(result);
[35aab3]1181  nlTest(result);
1182  return result;
1183}
1184
1185int nlModP(number n, int p)
1186{
1187  if (SR_HDL(n) & SR_INT)
1188  {
[246d15]1189    long i=SR_TO_INT(n);
1190    if (i<0L) return (((long)p)-((-i)%((long)p)));
1191    return i%((long)p);
[35aab3]1192  }
[a604c3]1193  int iz=(int)mpz_fdiv_ui(n->z,(unsigned long)p);
[35aab3]1194  if (n->s!=3)
1195  {
[a604c3]1196    int in=mpz_fdiv_ui(n->n,(unsigned long)p);
[6c15ec]1197    #ifdef NV_OPS
1198    if (npPrimeM>NV_MAX_PRIME)
1199    return (int)((long)nvDiv((number)iz,(number)in));
1200    #endif
[7447d8]1201    return (int)((long)npDiv((number)iz,(number)in));
[35aab3]1202  }
1203  return iz;
1204}
1205
[894f5b1]1206#ifdef HAVE_RINGS
1207/*2
[1919112]1208* convert number i (from Q) to GMP and warn if denom != 1
[894f5b1]1209*/
[0959dc]1210void nlGMP(number &i, number n)
[894f5b1]1211{
1212  // Hier brauche ich einfach die GMP Zahl
1213  nlTest(i);
1214  nlNormalize(i);
1215  if (SR_HDL(i) & SR_INT)
1216  {
[246d15]1217    mpz_set_si((mpz_ptr) n, SR_TO_INT(i));
[0959dc]1218    return;
[894f5b1]1219  }
1220  if (i->s!=3)
1221  {
1222     WarnS("Omitted denominator during coefficient mapping !");
1223  }
[a604c3]1224  mpz_set((mpz_ptr) n, i->z);
[894f5b1]1225}
1226#endif
1227
[35aab3]1228/*2
1229* acces to denominator, other 1 for integers
1230*/
1231number   nlGetDenom(number &n, const ring r)
1232{
1233  if (!(SR_HDL(n) & SR_INT))
1234  {
1235    if (n->s==0)
1236    {
1237      nlNormalize(n);
1238    }
1239    if (!(SR_HDL(n) & SR_INT))
1240    {
1241      if (n->s!=3)
1242      {
1243        number u=(number)omAllocBin(rnumber_bin);
1244        u->s=3;
1245#if defined(LDEBUG)
1246        u->debug=123456;
1247#endif
[a604c3]1248        mpz_init_set(u->z,n->n);
[246d15]1249        u=nlShort3_noinline(u);
[35aab3]1250        return u;
1251      }
1252    }
1253  }
1254  return INT_TO_SR(1);
1255}
1256
1257/*2
1258* acces to Nominator, nlCopy(n) for integers
1259*/
[e803ec]1260number   nlGetNumerator(number &n, const ring r)
[35aab3]1261{
1262  if (!(SR_HDL(n) & SR_INT))
1263  {
1264    if (n->s==0)
1265    {
1266      nlNormalize(n);
1267    }
1268    if (!(SR_HDL(n) & SR_INT))
1269    {
1270      number u=(number)omAllocBin(rnumber_bin);
1271#if defined(LDEBUG)
1272      u->debug=123456;
1273#endif
1274      u->s=3;
[a604c3]1275      mpz_init_set(u->z,n->z);
[35aab3]1276      if (n->s!=3)
1277      {
[246d15]1278        u=nlShort3_noinline(u);
[35aab3]1279      }
1280      return u;
1281    }
1282  }
1283  return n; // imm. int
1284}
1285
1286/***************************************************************
1287 *
1288 * routines which are needed by Inline(d) routines
1289 *
1290 *******************************************************************/
1291BOOLEAN _nlEqual_aNoImm_OR_bNoImm(number a, number b)
1292{
1293  assume(! (SR_HDL(a) & SR_HDL(b) & SR_INT));
1294//  long - short
1295  BOOLEAN bo;
1296  if (SR_HDL(b) & SR_INT)
1297  {
1298    if (a->s!=0) return FALSE;
1299    number n=b; b=a; a=n;
1300  }
1301//  short - long
1302  if (SR_HDL(a) & SR_INT)
1303  {
1304    if (b->s!=0)
1305      return FALSE;
[a604c3]1306    if (((long)a > 0L) && (mpz_isNeg(b->z)))
[35aab3]1307      return FALSE;
[a604c3]1308    if (((long)a < 0L) && (!mpz_isNeg(b->z)))
[35aab3]1309      return FALSE;
[a604c3]1310    mpz_t  bb;
1311    mpz_init_set(bb,b->n);
1312    mpz_mul_si(bb,bb,(long)SR_TO_INT(a));
1313    bo=(mpz_cmp(bb,b->z)==0);
1314    mpz_clear(bb);
[35aab3]1315    return bo;
1316  }
1317// long - long
1318  if (((a->s==1) && (b->s==3))
1319  ||  ((b->s==1) && (a->s==3)))
1320    return FALSE;
[a604c3]1321  if (mpz_isNeg(a->z)&&(!mpz_isNeg(b->z)))
[35aab3]1322    return FALSE;
[a604c3]1323  if (mpz_isNeg(b->z)&&(!mpz_isNeg(a->z)))
[35aab3]1324    return FALSE;
[a604c3]1325  mpz_t  aa;
1326  mpz_t  bb;
1327  mpz_init_set(aa,a->z);
1328  mpz_init_set(bb,b->z);
1329  if (a->s<2) mpz_mul(bb,bb,a->n);
1330  if (b->s<2) mpz_mul(aa,aa,b->n);
1331  bo=(mpz_cmp(aa,bb)==0);
1332  mpz_clear(aa);
1333  mpz_clear(bb);
[35aab3]1334  return bo;
1335}
1336
1337// copy not immediate number a
1338number _nlCopy_NoImm(number a)
1339{
1340  assume(!((SR_HDL(a) & SR_INT)||(a==NULL)));
1341  nlTest(a);
1342  number b=(number)omAllocBin(rnumber_bin);
1343#if defined(LDEBUG)
1344  b->debug=123456;
1345#endif
1346  switch (a->s)
1347  {
1348    case 0:
1349    case 1:
[a604c3]1350            mpz_init_set(b->n,a->n);
[35aab3]1351    case 3:
[a604c3]1352            mpz_init_set(b->z,a->z);
[35aab3]1353            break;
1354  }
1355  b->s = a->s;
1356  nlTest(b);
1357  return b;
1358}
1359
[fee4c2]1360void _nlDelete_NoImm(number *a)
[35aab3]1361{
1362  {
1363    switch ((*a)->s)
1364    {
1365      case 0:
1366      case 1:
[a604c3]1367        mpz_clear((*a)->n);
[35aab3]1368      case 3:
[a604c3]1369        mpz_clear((*a)->z);
[35aab3]1370#ifdef LDEBUG
1371        (*a)->s=2;
1372#endif
1373    }
1374    omFreeBin((ADDRESS) *a, rnumber_bin);
1375  }
1376}
1377
1378number _nlNeg_NoImm(number a)
1379{
1380  {
[a604c3]1381    mpz_neg(a->z,a->z);
[246d15]1382    if (a->s==3)
[35aab3]1383    {
[246d15]1384      a=nlShort3(a);
[35aab3]1385    }
1386  }
1387  nlTest(a);
1388  return a;
1389}
1390
1391number _nlAdd_aNoImm_OR_bNoImm(number a, number b)
1392{
1393  number u=(number)omAllocBin(rnumber_bin);
1394#if defined(LDEBUG)
1395  u->debug=123456;
1396#endif
[a604c3]1397  mpz_init(u->z);
[35aab3]1398  if (SR_HDL(b) & SR_INT)
1399  {
1400    number x=a;
1401    a=b;
1402    b=x;
1403  }
1404  if (SR_HDL(a) & SR_INT)
1405  {
1406    switch (b->s)
1407    {
1408      case 0:
1409      case 1:/* a:short, b:1 */
1410      {
[a604c3]1411        mpz_t x;
1412        mpz_init(x);
1413        mpz_mul_si(x,b->n,SR_TO_INT(a));
1414        mpz_add(u->z,b->z,x);
1415        mpz_clear(x);
1416        if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1417        {
[a604c3]1418          mpz_clear(u->z);
[35aab3]1419          omFreeBin((ADDRESS)u, rnumber_bin);
1420          return INT_TO_SR(0);
1421        }
[a604c3]1422        if (mpz_cmp(u->z,b->n)==0)
[35aab3]1423        {
[a604c3]1424          mpz_clear(u->z);
[35aab3]1425          omFreeBin((ADDRESS)u, rnumber_bin);
1426          return INT_TO_SR(1);
1427        }
[a604c3]1428        mpz_init_set(u->n,b->n);
[35aab3]1429        u->s = 0;
1430        break;
1431      }
1432      case 3:
1433      {
[7447d8]1434        if ((long)a>0L)
[a604c3]1435          mpz_add_ui(u->z,b->z,SR_TO_INT(a));
[35aab3]1436        else
[a604c3]1437          mpz_sub_ui(u->z,b->z,-SR_TO_INT(a));
1438        if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1439        {
[a604c3]1440          mpz_clear(u->z);
[35aab3]1441          omFreeBin((ADDRESS)u, rnumber_bin);
1442          return INT_TO_SR(0);
1443        }
1444        u->s = 3;
[246d15]1445        u=nlShort3(u);
[35aab3]1446        break;
1447      }
1448    }
1449  }
1450  else
1451  {
1452    switch (a->s)
1453    {
1454      case 0:
1455      case 1:
1456      {
1457        switch(b->s)
1458        {
1459          case 0:
1460          case 1:
1461          {
[a604c3]1462            mpz_t x;
1463            mpz_init(x);
[e8a0aa]1464
[a604c3]1465            mpz_mul(x,b->z,a->n);
1466            mpz_mul(u->z,a->z,b->n);
1467            mpz_add(u->z,u->z,x);
1468            mpz_clear(x);
[e8a0aa]1469
[a604c3]1470            if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1471            {
[a604c3]1472              mpz_clear(u->z);
[35aab3]1473              omFreeBin((ADDRESS)u, rnumber_bin);
1474              return INT_TO_SR(0);
1475            }
[a604c3]1476            mpz_init(u->n);
1477            mpz_mul(u->n,a->n,b->n);
1478            if (mpz_cmp(u->z,u->n)==0)
[35aab3]1479            {
[a604c3]1480               mpz_clear(u->z);
1481               mpz_clear(u->n);
[35aab3]1482               omFreeBin((ADDRESS)u, rnumber_bin);
1483               return INT_TO_SR(1);
1484            }
1485            u->s = 0;
1486            break;
1487          }
1488          case 3: /* a:1 b:3 */
1489          {
[a604c3]1490            mpz_mul(u->z,b->z,a->n);
1491            mpz_add(u->z,u->z,a->z);
1492            if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1493            {
[a604c3]1494              mpz_clear(u->z);
[35aab3]1495              omFreeBin((ADDRESS)u, rnumber_bin);
1496              return INT_TO_SR(0);
1497            }
[a604c3]1498            if (mpz_cmp(u->z,a->n)==0)
[35aab3]1499            {
[a604c3]1500              mpz_clear(u->z);
[35aab3]1501              omFreeBin((ADDRESS)u, rnumber_bin);
1502              return INT_TO_SR(1);
1503            }
[a604c3]1504            mpz_init_set(u->n,a->n);
[35aab3]1505            u->s = 0;
1506            break;
1507          }
1508        } /*switch (b->s) */
1509        break;
1510      }
1511      case 3:
1512      {
1513        switch(b->s)
1514        {
1515          case 0:
1516          case 1:/* a:3, b:1 */
1517          {
[a604c3]1518            mpz_mul(u->z,a->z,b->n);
1519            mpz_add(u->z,u->z,b->z);
1520            if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1521            {
[a604c3]1522              mpz_clear(u->z);
[35aab3]1523              omFreeBin((ADDRESS)u, rnumber_bin);
1524              return INT_TO_SR(0);
1525            }
[a604c3]1526            if (mpz_cmp(u->z,b->n)==0)
[35aab3]1527            {
[a604c3]1528              mpz_clear(u->z);
[35aab3]1529              omFreeBin((ADDRESS)u, rnumber_bin);
1530              return INT_TO_SR(1);
1531            }
[a604c3]1532            mpz_init_set(u->n,b->n);
[35aab3]1533            u->s = 0;
1534            break;
1535          }
1536          case 3:
1537          {
[a604c3]1538            mpz_add(u->z,a->z,b->z);
1539            if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1540            {
[a604c3]1541              mpz_clear(u->z);
[35aab3]1542              omFreeBin((ADDRESS)u, rnumber_bin);
1543              return INT_TO_SR(0);
1544            }
1545            u->s = 3;
[246d15]1546            u=nlShort3(u);
[35aab3]1547            break;
1548          }
1549        }
1550        break;
1551      }
1552    }
1553  }
1554  nlTest(u);
1555  return u;
1556}
1557
1558number _nlSub_aNoImm_OR_bNoImm(number a, number b)
1559{
1560  number u=(number)omAllocBin(rnumber_bin);
1561#if defined(LDEBUG)
1562  u->debug=123456;
1563#endif
[a604c3]1564  mpz_init(u->z);
[35aab3]1565  if (SR_HDL(a) & SR_INT)
1566  {
1567    switch (b->s)
1568    {
1569      case 0:
1570      case 1:/* a:short, b:1 */
1571      {
[a604c3]1572        mpz_t x;
1573        mpz_init(x);
1574        mpz_mul_si(x,b->n,SR_TO_INT(a));
1575        mpz_sub(u->z,x,b->z);
1576        mpz_clear(x);
1577        if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1578        {
[a604c3]1579          mpz_clear(u->z);
[35aab3]1580          omFreeBin((ADDRESS)u, rnumber_bin);
1581          return INT_TO_SR(0);
1582        }
[a604c3]1583        if (mpz_cmp(u->z,b->n)==0)
[35aab3]1584        {
[a604c3]1585          mpz_clear(u->z);
[35aab3]1586          omFreeBin((ADDRESS)u, rnumber_bin);
1587          return INT_TO_SR(1);
1588        }
[a604c3]1589        mpz_init_set(u->n,b->n);
[35aab3]1590        u->s = 0;
1591        break;
1592      }
1593      case 3:
1594      {
[7447d8]1595        if ((long)a>0L)
[35aab3]1596        {
[a604c3]1597          mpz_sub_ui(u->z,b->z,SR_TO_INT(a));
1598          mpz_neg(u->z,u->z);
[35aab3]1599        }
1600        else
1601        {
[a604c3]1602          mpz_add_ui(u->z,b->z,-SR_TO_INT(a));
1603          mpz_neg(u->z,u->z);
[35aab3]1604        }
[a604c3]1605        if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1606        {
[a604c3]1607          mpz_clear(u->z);
[35aab3]1608          omFreeBin((ADDRESS)u, rnumber_bin);
1609          return INT_TO_SR(0);
1610        }
1611        u->s = 3;
[246d15]1612        u=nlShort3(u);
[35aab3]1613        break;
1614      }
1615    }
1616  }
1617  else if (SR_HDL(b) & SR_INT)
1618  {
1619    switch (a->s)
1620    {
1621      case 0:
1622      case 1:/* b:short, a:1 */
1623      {
[a604c3]1624        mpz_t x;
1625        mpz_init(x);
1626        mpz_mul_si(x,a->n,SR_TO_INT(b));
1627        mpz_sub(u->z,a->z,x);
1628        mpz_clear(x);
1629        if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1630        {
[a604c3]1631          mpz_clear(u->z);
[35aab3]1632          omFreeBin((ADDRESS)u, rnumber_bin);
1633          return INT_TO_SR(0);
1634        }
[a604c3]1635        if (mpz_cmp(u->z,a->n)==0)
[35aab3]1636        {
[a604c3]1637          mpz_clear(u->z);
[35aab3]1638          omFreeBin((ADDRESS)u, rnumber_bin);
1639          return INT_TO_SR(1);
1640        }
[a604c3]1641        mpz_init_set(u->n,a->n);
[35aab3]1642        u->s = 0;
1643        break;
1644      }
1645      case 3:
1646      {
[7447d8]1647        if ((long)b>0L)
[35aab3]1648        {
[a604c3]1649          mpz_sub_ui(u->z,a->z,SR_TO_INT(b));
[35aab3]1650        }
1651        else
1652        {
[a604c3]1653          mpz_add_ui(u->z,a->z,-SR_TO_INT(b));
[35aab3]1654        }
[a604c3]1655        if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1656        {
[a604c3]1657          mpz_clear(u->z);
[35aab3]1658          omFreeBin((ADDRESS)u, rnumber_bin);
1659          return INT_TO_SR(0);
1660        }
1661        u->s = 3;
[246d15]1662        u=nlShort3(u);
[35aab3]1663        break;
1664      }
1665    }
1666  }
1667  else
1668  {
1669    switch (a->s)
1670    {
1671      case 0:
1672      case 1:
1673      {
1674        switch(b->s)
1675        {
1676          case 0:
1677          case 1:
1678          {
[a604c3]1679            mpz_t x;
1680            mpz_t y;
1681            mpz_init(x);
1682            mpz_init(y);
1683            mpz_mul(x,b->z,a->n);
1684            mpz_mul(y,a->z,b->n);
1685            mpz_sub(u->z,y,x);
1686            mpz_clear(x);
1687            mpz_clear(y);
1688            if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1689            {
[a604c3]1690              mpz_clear(u->z);
[35aab3]1691              omFreeBin((ADDRESS)u, rnumber_bin);
1692              return INT_TO_SR(0);
1693            }
[a604c3]1694            mpz_init(u->n);
1695            mpz_mul(u->n,a->n,b->n);
1696            if (mpz_cmp(u->z,u->n)==0)
[35aab3]1697            {
[a604c3]1698              mpz_clear(u->z);
1699              mpz_clear(u->n);
[35aab3]1700              omFreeBin((ADDRESS)u, rnumber_bin);
1701              return INT_TO_SR(1);
1702            }
1703            u->s = 0;
1704            break;
1705          }
1706          case 3: /* a:1, b:3 */
1707          {
[a604c3]1708            mpz_t x;
1709            mpz_init(x);
1710            mpz_mul(x,b->z,a->n);
1711            mpz_sub(u->z,a->z,x);
1712            mpz_clear(x);
1713            if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1714            {
[a604c3]1715              mpz_clear(u->z);
[35aab3]1716              omFreeBin((ADDRESS)u, rnumber_bin);
1717              return INT_TO_SR(0);
1718            }
[a604c3]1719            if (mpz_cmp(u->z,a->n)==0)
[35aab3]1720            {
[a604c3]1721              mpz_clear(u->z);
[35aab3]1722              omFreeBin((ADDRESS)u, rnumber_bin);
1723              return INT_TO_SR(1);
1724            }
[a604c3]1725            mpz_init_set(u->n,a->n);
[35aab3]1726            u->s = 0;
1727            break;
1728          }
1729        }
1730        break;
1731      }
1732      case 3:
1733      {
1734        switch(b->s)
1735        {
1736          case 0:
1737          case 1: /* a:3, b:1 */
1738          {
[a604c3]1739            mpz_t x;
1740            mpz_init(x);
1741            mpz_mul(x,a->z,b->n);
1742            mpz_sub(u->z,x,b->z);
1743            mpz_clear(x);
1744            if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1745            {
[a604c3]1746              mpz_clear(u->z);
[35aab3]1747              omFreeBin((ADDRESS)u, rnumber_bin);
1748              return INT_TO_SR(0);
1749            }
[a604c3]1750            if (mpz_cmp(u->z,b->n)==0)
[35aab3]1751            {
[a604c3]1752              mpz_clear(u->z);
[35aab3]1753              omFreeBin((ADDRESS)u, rnumber_bin);
1754              return INT_TO_SR(1);
1755            }
[a604c3]1756            mpz_init_set(u->n,b->n);
[35aab3]1757            u->s = 0;
1758            break;
1759          }
1760          case 3: /* a:3 , b:3 */
1761          {
[a604c3]1762            mpz_sub(u->z,a->z,b->z);
1763            if (mpz_cmp_ui(u->z,(long)0)==0)
[35aab3]1764            {
[a604c3]1765              mpz_clear(u->z);
[35aab3]1766              omFreeBin((ADDRESS)u, rnumber_bin);
1767              return INT_TO_SR(0);
1768            }
1769            u->s = 3;
[246d15]1770            u=nlShort3(u);
[35aab3]1771            break;
1772          }
1773        }
1774        break;
1775      }
1776    }
1777  }
1778  nlTest(u);
1779  return u;
1780}
1781
1782// a and b are intermediate, but a*b not
1783number _nlMult_aImm_bImm_rNoImm(number a, number b)
1784{
1785  number u=(number)omAllocBin(rnumber_bin);
1786#if defined(LDEBUG)
1787  u->debug=123456;
1788#endif
1789  u->s=3;
[246d15]1790  mpz_init_set_si(u->z,SR_TO_INT(a));
1791  mpz_mul_si(u->z,u->z,SR_TO_INT(b));
[35aab3]1792  nlTest(u);
1793  return u;
1794}
1795
1796// a or b are not immediate
1797number _nlMult_aNoImm_OR_bNoImm(number a, number b)
1798{
1799  assume(! (SR_HDL(a) & SR_HDL(b) & SR_INT));
1800  number u=(number)omAllocBin(rnumber_bin);
1801#if defined(LDEBUG)
1802  u->debug=123456;
1803#endif
[a604c3]1804  mpz_init(u->z);
[35aab3]1805  if (SR_HDL(b) & SR_INT)
1806  {
1807    number x=a;
1808    a=b;
1809    b=x;
1810  }
1811  if (SR_HDL(a) & SR_INT)
1812  {
1813    u->s=b->s;
1814    if (u->s==1) u->s=0;
[7447d8]1815    if ((long)a>0L)
[35aab3]1816    {
[a604c3]1817      mpz_mul_ui(u->z,b->z,(unsigned long)SR_TO_INT(a));
[35aab3]1818    }
1819    else
1820    {
1821      if (a==INT_TO_SR(-1))
1822      {
[a604c3]1823        mpz_set(u->z,b->z);
1824        mpz_neg(u->z,u->z);
[35aab3]1825        u->s=b->s;
1826      }
1827      else
1828      {
[a604c3]1829        mpz_mul_ui(u->z,b->z,(unsigned long)-SR_TO_INT(a));
1830        mpz_neg(u->z,u->z);
[35aab3]1831      }
1832    }
1833    if (u->s<2)
1834    {
[a604c3]1835      if (mpz_cmp(u->z,b->n)==0)
[35aab3]1836      {
[a604c3]1837        mpz_clear(u->z);
[35aab3]1838        omFreeBin((ADDRESS)u, rnumber_bin);
1839        return INT_TO_SR(1);
1840      }
[a604c3]1841      mpz_init_set(u->n,b->n);
[35aab3]1842    }
1843    else //u->s==3
1844    {
[246d15]1845      u=nlShort3(u);
[35aab3]1846    }
1847  }
1848  else
1849  {
[a604c3]1850    mpz_mul(u->z,a->z,b->z);
[35aab3]1851    u->s = 0;
1852    if(a->s==3)
1853    {
1854      if(b->s==3)
1855      {
1856        u->s = 3;
1857      }
1858      else
1859      {
[a604c3]1860        if (mpz_cmp(u->z,b->n)==0)
[35aab3]1861        {
[a604c3]1862          mpz_clear(u->z);
[35aab3]1863          omFreeBin((ADDRESS)u, rnumber_bin);
1864          return INT_TO_SR(1);
1865        }
[a604c3]1866        mpz_init_set(u->n,b->n);
[35aab3]1867      }
1868    }
1869    else
1870    {
1871      if(b->s==3)
1872      {
[a604c3]1873        if (mpz_cmp(u->z,a->n)==0)
[35aab3]1874        {
[a604c3]1875          mpz_clear(u->z);
[35aab3]1876          omFreeBin((ADDRESS)u, rnumber_bin);
1877          return INT_TO_SR(1);
1878        }
[a604c3]1879        mpz_init_set(u->n,a->n);
[35aab3]1880      }
1881      else
1882      {
[a604c3]1883        mpz_init(u->n);
1884        mpz_mul(u->n,a->n,b->n);
1885        if (mpz_cmp(u->z,u->n)==0)
[35aab3]1886        {
[a604c3]1887          mpz_clear(u->z);
1888          mpz_clear(u->n);
[35aab3]1889          omFreeBin((ADDRESS)u, rnumber_bin);
1890          return INT_TO_SR(1);
1891        }
1892      }
1893    }
1894  }
1895  nlTest(u);
1896  return u;
1897}
1898
1899/*2
1900* z := i
1901*/
[246d15]1902number nlRInit (long i)
[35aab3]1903{
1904  number z=(number)omAllocBin(rnumber_bin);
1905#if defined(LDEBUG)
1906  z->debug=123456;
1907#endif
[246d15]1908  mpz_init_set_si(z->z,i);
[35aab3]1909  z->s = 3;
1910  return z;
1911}
1912
1913/*2
1914* z := i/j
1915*/
1916number nlInit2 (int i, int j)
1917{
1918  number z=(number)omAllocBin(rnumber_bin);
1919#if defined(LDEBUG)
1920  z->debug=123456;
1921#endif
[a604c3]1922  mpz_init_set_si(z->z,(long)i);
1923  mpz_init_set_si(z->n,(long)j);
[35aab3]1924  z->s = 0;
1925  nlNormalize(z);
1926  return z;
1927}
1928
[a1ab2a]1929number nlInit2gmp (mpz_t i, mpz_t j)
1930{
1931  number z=(number)omAllocBin(rnumber_bin);
1932#if defined(LDEBUG)
1933  z->debug=123456;
1934#endif
[a604c3]1935  mpz_init_set(z->z,i);
1936  mpz_init_set(z->n,j);
[a1ab2a]1937  z->s = 0;
1938  nlNormalize(z);
1939  return z;
1940}
1941
[35aab3]1942#else // DO_LINLINE
1943
1944// declare immedate routines
1945number nlRInit (int i);
1946BOOLEAN _nlEqual_aNoImm_OR_bNoImm(number a, number b);
1947number  _nlCopy_NoImm(number a);
1948number  _nlNeg_NoImm(number a);
1949number  _nlAdd_aNoImm_OR_bNoImm(number a, number b);
1950number  _nlSub_aNoImm_OR_bNoImm(number a, number b);
1951number  _nlMult_aNoImm_OR_bNoImm(number a, number b);
1952number  _nlMult_aImm_bImm_rNoImm(number a, number b);
1953
1954#endif
1955
1956/***************************************************************
1957 *
1958 * Routines which might be inlined by p_Numbers.h
1959 *
1960 *******************************************************************/
1961#if defined(DO_LINLINE) || !defined(P_NUMBERS_H)
1962
1963// routines which are always inlined/static
1964
1965/*2
1966* a = b ?
1967*/
1968LINLINE BOOLEAN nlEqual (number a, number b)
1969{
1970  nlTest(a);
1971  nlTest(b);
1972// short - short
1973  if (SR_HDL(a) & SR_HDL(b) & SR_INT) return a==b;
1974  return _nlEqual_aNoImm_OR_bNoImm(a, b);
1975}
1976
1977
[8391d8]1978LINLINE number nlInit (int i, const ring r)
[35aab3]1979{
1980  number n;
[246d15]1981  LONG ii=(LONG)i;
1982  if ( ((ii << 3) >> 3) == ii ) n=INT_TO_SR(ii);
1983  else                          n=nlRInit(ii);
[35aab3]1984  nlTest(n);
1985  return n;
1986}
1987
1988
1989/*2
1990* a == 1 ?
1991*/
1992LINLINE BOOLEAN nlIsOne (number a)
1993{
1994#ifdef LDEBUG
1995  if (a==NULL) return FALSE;
1996  nlTest(a);
1997#endif
[89ca47]1998  return (a==INT_TO_SR(1));
[35aab3]1999}
2000
2001LINLINE BOOLEAN nlIsZero (number a)
2002{
2003  return (a==INT_TO_SR(0));
[a604c3]2004  //return (mpz_cmp_si(a->z,(long)0)==0);
[35aab3]2005}
2006
2007/*2
2008* copy a to b
2009*/
2010LINLINE number nlCopy(number a)
2011{
2012  if ((SR_HDL(a) & SR_INT)||(a==NULL))
2013  {
2014    return a;
2015  }
2016  return _nlCopy_NoImm(a);
2017}
2018
2019
2020/*2
2021* delete a
2022*/
2023LINLINE void nlDelete (number * a, const ring r)
2024{
2025  if (*a!=NULL)
2026  {
2027    nlTest(*a);
2028    if ((SR_HDL(*a) & SR_INT)==0)
2029    {
[fee4c2]2030      _nlDelete_NoImm(a);
[35aab3]2031    }
2032    *a=NULL;
2033  }
2034}
2035
2036/*2
2037* za:= - za
2038*/
2039LINLINE number nlNeg (number a)
2040{
2041  nlTest(a);
2042  if(SR_HDL(a) &SR_INT)
2043  {
2044    int r=SR_TO_INT(a);
[246d15]2045    if (r==(-(POW_2_28))) a=nlRInit(POW_2_28);
[35aab3]2046    else               a=INT_TO_SR(-r);
2047    return a;
2048  }
2049  return _nlNeg_NoImm(a);
2050}
2051
2052/*2
2053* u:= a + b
2054*/
2055LINLINE number nlAdd (number a, number b)
2056{
2057  number u;
2058  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2059  {
[246d15]2060    LONG r=SR_HDL(a)+SR_HDL(b)-1L;
[35aab3]2061    if ( ((r << 1) >> 1) == r )
[37a003]2062      return (number)(long)r;
[35aab3]2063    else
2064      return nlRInit(SR_TO_INT(r));
2065  }
2066  return _nlAdd_aNoImm_OR_bNoImm(a, b);
2067}
2068
[18057e]2069number nlShort1(number a);
[246d15]2070number nlShort3_noinline(number x);
[e8a0aa]2071
2072LINLINE number nlInpAdd (number a, number b, const ring r)
2073{
2074  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2075  {
[246d15]2076    LONG r=SR_HDL(a)+SR_HDL(b)-1L;
[e8a0aa]2077    if ( ((r << 1) >> 1) == r )
2078      return (number)(long)r;
2079    else
2080      return nlRInit(SR_TO_INT(r));
2081  }
2082  // a=a+b
2083  if (SR_HDL(b) & SR_INT)
2084  {
2085    switch (a->s)
2086    {
2087      case 0:
2088      case 1:/* b:short, a:1 */
2089      {
[a604c3]2090        mpz_t x;
2091        mpz_init(x);
2092        mpz_mul_si(x,a->n,SR_TO_INT(b));
2093        mpz_add(a->z,a->z,x);
2094        mpz_clear(x);
[e8a0aa]2095        a->s = 0;
[18057e]2096        a=nlShort1(a);
[e8a0aa]2097        break;
2098      }
2099      case 3:
2100      {
2101        if ((long)b>0L)
[a604c3]2102          mpz_add_ui(a->z,a->z,SR_TO_INT(b));
[e8a0aa]2103        else
[a604c3]2104          mpz_sub_ui(a->z,a->z,-SR_TO_INT(b));
[e8a0aa]2105        a->s = 3;
[246d15]2106        a=nlShort3_noinline(a);
[e8a0aa]2107        break;
2108      }
2109    }
2110    return a;
2111  }
2112  if (SR_HDL(a) & SR_INT)
2113  {
2114    number u=(number)omAllocBin(rnumber_bin);
2115    #if defined(LDEBUG)
2116    u->debug=123456;
2117    #endif
[a604c3]2118    mpz_init(u->z);
[e8a0aa]2119    switch (b->s)
2120    {
2121      case 0:
2122      case 1:/* a:short, b:1 */
2123      {
[a604c3]2124        mpz_t x;
2125        mpz_init(x);
[e8a0aa]2126
[a604c3]2127        mpz_mul_si(x,b->n,SR_TO_INT(a));
2128        mpz_add(u->z,b->z,x);
2129        mpz_clear(x);
[e8a0aa]2130        // result cannot be 0, if coeffs are normalized
[a604c3]2131        mpz_init_set(u->n,b->n);
[e8a0aa]2132        u->s = 0;
[18057e]2133        u=nlShort1(u);
[e8a0aa]2134        break;
2135      }
2136      case 3:
2137      {
2138        if ((long)a>0L)
[a604c3]2139          mpz_add_ui(u->z,b->z,SR_TO_INT(a));
[e8a0aa]2140        else
[a604c3]2141          mpz_sub_ui(u->z,b->z,-SR_TO_INT(a));
[e8a0aa]2142        // result cannot be 0, if coeffs are normalized
2143        u->s = 3;
[246d15]2144        u=nlShort3_noinline(u);
[e8a0aa]2145        break;
2146      }
2147    }
2148    nlTest(u);
2149    return u;
2150  }
2151  else
2152  {
2153    switch (a->s)
2154    {
2155      case 0:
2156      case 1:
2157      {
2158        switch(b->s)
2159        {
2160          case 0:
2161          case 1: /* a:1 b:1 */
2162          {
[a604c3]2163            mpz_t x;
2164            mpz_t y;
2165            mpz_init(x);
2166            mpz_init(y);
2167            mpz_mul(x,b->z,a->n);
2168            mpz_mul(y,a->z,b->n);
2169            mpz_add(a->z,x,y);
2170            mpz_clear(x);
2171            mpz_clear(y);
2172            mpz_mul(a->n,a->n,b->n);
[e8a0aa]2173            a->s = 0;
2174            break;
2175          }
2176          case 3: /* a:1 b:3 */
2177          {
[a604c3]2178            mpz_t x;
2179            mpz_init(x);
2180            mpz_mul(x,b->z,a->n);
2181            mpz_add(a->z,a->z,x);
2182            mpz_clear(x);
[e8a0aa]2183            a->s = 0;
2184            break;
2185          }
2186        } /*switch (b->s) */
[18057e]2187        a=nlShort1(a);
[e8a0aa]2188        break;
2189      }
2190      case 3:
2191      {
2192        switch(b->s)
2193        {
2194          case 0:
2195          case 1:/* a:3, b:1 */
2196          {
[a604c3]2197            mpz_t x;
2198            mpz_init(x);
2199            mpz_mul(x,a->z,b->n);
2200            mpz_add(a->z,b->z,x);
2201            mpz_clear(x);
2202            mpz_init_set(a->n,b->n);
[e8a0aa]2203            a->s = 0;
[18057e]2204            a=nlShort1(a);
[e8a0aa]2205            break;
2206          }
2207          case 3:
2208          {
[a604c3]2209            mpz_add(a->z,a->z,b->z);
[e8a0aa]2210            a->s = 3;
[246d15]2211            a=nlShort3_noinline(a);
[e8a0aa]2212            break;
2213          }
2214        }
2215        break;
2216      }
2217    }
2218    nlTest(a);
2219    return a;
2220  }
2221}
2222
[35aab3]2223LINLINE number nlMult (number a, number b)
2224{
2225  nlTest(a);
2226  nlTest(b);
[246d15]2227
[35aab3]2228  if (a==INT_TO_SR(0)) return INT_TO_SR(0);
2229  if (b==INT_TO_SR(0)) return INT_TO_SR(0);
2230  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2231  {
[246d15]2232    LONG r=(SR_HDL(a)-1L)*(SR_HDL(b)>>1);
2233    if ((r/(SR_HDL(b)>>1))==(SR_HDL(a)-1L))
[35aab3]2234    {
2235      number u=((number) ((r>>1)+SR_INT));
[246d15]2236      if (((((LONG)SR_HDL(u))<<1)>>1)==SR_HDL(u)) return (u);
[35aab3]2237      return nlRInit(SR_HDL(u)>>2);
2238    }
2239    return _nlMult_aImm_bImm_rNoImm(a, b);
2240  }
2241  return _nlMult_aNoImm_OR_bNoImm(a, b);
2242}
2243
2244
2245/*2
2246* u:= a - b
2247*/
2248LINLINE number nlSub (number a, number b)
2249{
2250  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2251  {
[246d15]2252    LONG r=SR_HDL(a)-SR_HDL(b)+1;
[35aab3]2253    if ( ((r << 1) >> 1) == r )
2254    {
[246d15]2255      return (number)(long)r;
[35aab3]2256    }
2257    else
2258      return nlRInit(SR_TO_INT(r));
2259  }
2260  return _nlSub_aNoImm_OR_bNoImm(a, b);
2261}
2262
2263#endif // DO_LINLINE
2264
2265#ifndef P_NUMBERS_H
2266
[e8a0aa]2267void nlInpGcd(number &a, number b, const ring r)
[35aab3]2268{
2269  if ((SR_HDL(b)|SR_HDL(a))&SR_INT)
2270  {
2271    number n=nlGcd(a,b,r);
2272    nlDelete(&a,r);
2273    a=n;
2274  }
2275  else
2276  {
[a604c3]2277    mpz_gcd(a->z,a->z,b->z);
[246d15]2278    a=nlShort3_noinline(a);
[35aab3]2279  }
2280}
[e8a0aa]2281void nlInpIntDiv(number &a, number b, const ring r)
[35aab3]2282{
2283  if ((SR_HDL(b)|SR_HDL(a))&SR_INT)
2284  {
2285    number n=nlIntDiv(a,b);
2286    nlDelete(&a,r);
2287    a=n;
2288  }
2289  else
2290  {
[a604c3]2291    if (mpz_isNeg(a->z))
[35aab3]2292    {
[a604c3]2293      if (mpz_isNeg(b->z))
[35aab3]2294      {
[a604c3]2295        mpz_add(a->z,a->z,b->z);
[35aab3]2296      }
2297      else
2298      {
[a604c3]2299        mpz_sub(a->z,a->z,b->z);
[35aab3]2300      }
[a604c3]2301      mpz_add_ui(a->z,a->z,1);
[35aab3]2302    }
2303    else
2304    {
[a604c3]2305      if (mpz_isNeg(b->z))
[35aab3]2306      {
[a604c3]2307        mpz_sub(a->z,a->z,b->z);
[35aab3]2308      }
2309      else
2310      {
[a604c3]2311        mpz_add(a->z,a->z,b->z);
[35aab3]2312      }
[a604c3]2313      mpz_sub_ui(a->z,a->z,1);
[35aab3]2314    }
[a604c3]2315    MPZ_DIV(a->z,a->z,b->z);
[246d15]2316    a=nlShort3_noinline(a);
[35aab3]2317  }
2318}
[e8a0aa]2319void nlInpMult(number &a, number b, const ring r)
[35aab3]2320{
2321  if (((SR_HDL(b)|SR_HDL(a))&SR_INT)
2322  )
2323  {
2324    number n=nlMult(a,b);
2325    nlDelete(&a,r);
2326    a=n;
2327  }
2328  else
2329  {
[a604c3]2330    mpz_mul(a->z,a->z,b->z);
[35aab3]2331    if (a->s==3)
2332    {
2333      if(b->s!=3)
2334      {
[a604c3]2335        mpz_init_set(a->n,b->n);
[35aab3]2336        a->s=0;
2337      }
2338    }
2339    else
2340    {
2341      if(b->s!=3)
2342      {
[a604c3]2343        mpz_mul(a->n,a->n,b->n);
[35aab3]2344      }
2345      a->s=0;
2346    }
2347  }
2348}
2349
[4fec74]2350number nlFarey(number nN, number nP)
[3149a5]2351{
[a604c3]2352  mpz_t tmp; mpz_init(tmp);
2353  mpz_t A,B,C,D,E,N,P;
2354  if (SR_HDL(nN) & SR_INT) mpz_init_set_si(N,SR_TO_INT(nN));
2355  else                     mpz_init_set(N,nN->z);
2356  if (SR_HDL(nP) & SR_INT) mpz_init_set_si(P,SR_TO_INT(nP));
2357  else                     mpz_init_set(P,nP->z);
2358  assume(!mpz_isNeg(P));
2359  if (mpz_isNeg(N))  mpz_add(N,N,P);
2360  mpz_init_set_si(A,(long)0);
2361  mpz_init_set_ui(B,(unsigned long)1);
2362  mpz_init_set_si(C,(long)0);
2363  mpz_init(D);
2364  mpz_init_set(E,P);
[3149a5]2365  number z=INT_TO_SR(0);
[a604c3]2366  while(mpz_cmp_si(N,(long)0)!=0)
[3149a5]2367  {
[a604c3]2368    mpz_mul(tmp,N,N);
2369    mpz_add(tmp,tmp,tmp);
2370    if (mpz_cmp(tmp,P)<0)
[3149a5]2371    {
2372       // return N/B
2373       z=(number)omAllocBin(rnumber_bin);
[64cce0]2374       #ifdef LDEBUG
2375       z->debug=123456;
2376       #endif
[a604c3]2377       if (mpz_isNeg(B))
[26300d]2378       {
[a604c3]2379         mpz_neg(B,B);
2380         mpz_neg(N,N);
[26300d]2381       }
[a604c3]2382       mpz_init_set(z->z,N);
2383       mpz_init_set(z->n,B);
[3149a5]2384       z->s = 0;
2385       nlNormalize(z);
2386       break;
2387    }
[a604c3]2388    mpz_mod(D,E,N);
2389    mpz_div(tmp,E,N);
2390    mpz_mul(tmp,tmp,B);
2391    mpz_sub(C,A,tmp);
2392    mpz_set(E,N);
2393    mpz_set(N,D);
2394    mpz_set(A,B);
2395    mpz_set(B,C);
2396  }
2397  mpz_clear(tmp);
2398  mpz_clear(A);
2399  mpz_clear(B);
2400  mpz_clear(C);
2401  mpz_clear(D);
2402  mpz_clear(E);
2403  mpz_clear(N);
2404  mpz_clear(P);
[3149a5]2405  return z;
2406}
[35aab3]2407#if 0
2408number nlMod(number a, number b)
2409{
2410  if (((SR_HDL(b)&SR_HDL(a))&SR_INT)
2411  {
2412    int bi=SR_TO_INT(b);
2413    int ai=SR_TO_INT(a);
2414    int bb=ABS(bi);
2415    int c=ai%bb;
2416    if (c<0)  c+=bb;
2417    return (INT_TO_SR(c));
2418  }
2419  number al;
2420  number bl;
2421  if (SR_HDL(a))&SR_INT)
2422    al=nlRInit(SR_TO_INT(a));
2423  else
2424    al=nlCopy(a);
2425  if (SR_HDL(b))&SR_INT)
2426    bl=nlRInit(SR_TO_INT(b));
2427  else
2428    bl=nlCopy(b);
2429  number r=nlRInit(0);
2430  mpz_mod(r->z,al->z,bl->z);
2431  nlDelete(&al);
2432  nlDelete(&bl);
2433  if (mpz_size1(&r->z)<=MP_SMALL)
2434  {
[246d15]2435    LONG ui=(int)mpz_get_si(&r->z);
[35aab3]2436    if ((((ui<<3)>>3)==ui)
[a604c3]2437    && (mpz_cmp_si(x->z,(long)ui)==0))
[35aab3]2438    {
2439      mpz_clear(&r->z);
2440      omFreeBin((ADDRESS)r, rnumber_bin);
2441      r=INT_TO_SR(ui);
2442    }
2443  }
2444  return r;
2445}
2446#endif
2447#endif // not P_NUMBERS_H
2448#endif // LONGRAT_CC
Note: See TracBrowser for help on using the repository browser.