source: git/kernel/longrat.cc @ 788529d

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