source: git/kernel/longrat.cc @ 585bbcb

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