source: git/kernel/longrat.cc @ 6c15ec

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