source: git/kernel/longrat.cc @ 11fa81

spielwiese
Last change on this file since 11fa81 was 11fa81, checked in by Hans Schönemann <hannes@…>, 17 years ago
*hannes: nlNormalize simplified git-svn-id: file:///usr/local/Singular/svn/trunk@9974 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.15 2007-04-12 16:33:52 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      if (mpz_cmp_si(&x->n,(long)1)==0)
1181      {
1182        mpz_clear(&x->n);
1183        if (mpz_size1(&x->z)<=MP_SMALL)
1184        {
1185          int ui=(int)mpz_get_si(&x->z);
1186          if ((((ui<<3)>>3)==ui)
1187          && (mpz_cmp_si(&x->z,(long)ui)==0))
1188          {
1189            mpz_clear(&x->z);
1190#if defined(LDEBUG)
1191            x->debug=654324;
1192#endif
1193            omFreeBin((ADDRESS)x, rnumber_bin);
1194            x=INT_TO_SR(ui);
1195            return;
1196          }
1197        }
1198        x->s=3;
1199      }
1200    }
1201    mpz_clear(&gcd);
1202#if 0
1203    else if (divided)
1204    {
1205#define mpz_alloc1(A) ((A)->_mp_alloc)
1206      int l;
1207      if ((mpz_alloc1(&x->n)>>1) >= (l=mpz_size1(&x->n)))
1208      {
1209        _mpz_realloc(&x->n,l /* mpz_size1(&x->n)*/);
1210      }
1211    }
1212    if (divided)
1213    {
1214      int l;
1215      if ((mpz_alloc1(&x->z)>>1) >= (l=mpz_size1(&x->z)))
1216      {
1217        _mpz_realloc(&x->z,l /*mpz_size1(&x->z)*/);
1218      }
1219    }
1220#endif
1221  }
1222#ifdef LDEBUG
1223  nlTest(x);
1224#endif
1225}
1226
1227/*2
1228* returns in result->z the lcm(a->z,b->n)
1229*/
1230number nlLcm(number a, number b, const ring r)
1231{
1232  number result;
1233#ifdef LDEBUG
1234  nlTest(a);
1235  nlTest(b);
1236#endif
1237  if ((SR_HDL(b) & SR_INT)
1238  || (b->s==3))
1239  {
1240    // b is 1/(b->n) => b->n is 1 => result is a
1241    return nlCopy(a);
1242  }
1243  result=(number)omAllocBin(rnumber_bin);
1244#if defined(LDEBUG)
1245  result->debug=123456;
1246#endif
1247  result->s=3;
1248  MP_INT gcd;
1249  mpz_init(&gcd);
1250  mpz_init(&result->z);
1251  if (SR_HDL(a) & SR_INT)
1252    mpz_gcd_ui(&gcd,&b->n,ABS(SR_TO_INT(a)));
1253  else
1254    mpz_gcd(&gcd,&a->z,&b->n);
1255  if (mpz_cmp_si(&gcd,(long)1)!=0)
1256  {
1257    MP_INT bt;
1258    mpz_init_set(&bt,&b->n);
1259    MPZ_EXACTDIV(&bt,&bt,&gcd);
1260    if (SR_HDL(a) & SR_INT)
1261      mpz_mul_si(&result->z,&bt,SR_TO_INT(a));
1262    else
1263      mpz_mul(&result->z,&bt,&a->z);
1264    mpz_clear(&bt);
1265  }
1266  else
1267    if (SR_HDL(a) & SR_INT)
1268      mpz_mul_si(&result->z,&b->n,SR_TO_INT(a));
1269    else
1270      mpz_mul(&result->z,&b->n,&a->z);
1271  mpz_clear(&gcd);
1272  if (mpz_size1(&result->z)<=MP_SMALL)
1273  {
1274    int ui=(int)mpz_get_si(&result->z);
1275    if ((((ui<<3)>>3)==ui)
1276    && (mpz_cmp_si(&result->z,(long)ui)==0))
1277    {
1278      mpz_clear(&result->z);
1279      omFreeBin((ADDRESS)result, rnumber_bin);
1280      return INT_TO_SR(ui);
1281    }
1282  }
1283#ifdef LDEBUG
1284  nlTest(result);
1285#endif
1286  return result;
1287}
1288
1289int nlModP(number n, int p)
1290{
1291  if (SR_HDL(n) & SR_INT)
1292  {
1293    int i=SR_TO_INT(n);
1294    if (i<0) return (p-((-i)%p));
1295    return i%p;
1296  }
1297  int iz=(int)mpz_mmod_ui(NULL,&n->z,(unsigned long)p);
1298  if (n->s!=3)
1299  {
1300    int in=mpz_mmod_ui(NULL,&n->n,(unsigned long)p);
1301    #ifdef NV_OPS
1302    if (npPrimeM>NV_MAX_PRIME)
1303    return (int)((long)nvDiv((number)iz,(number)in));
1304    #endif
1305    return (int)((long)npDiv((number)iz,(number)in));
1306  }
1307  return iz;
1308}
1309
1310/*2
1311* acces to denominator, other 1 for integers
1312*/
1313number   nlGetDenom(number &n, const ring r)
1314{
1315  if (!(SR_HDL(n) & SR_INT))
1316  {
1317    if (n->s==0)
1318    {
1319      nlNormalize(n);
1320    }
1321    if (!(SR_HDL(n) & SR_INT))
1322    {
1323      if (n->s!=3)
1324      {
1325        number u=(number)omAllocBin(rnumber_bin);
1326        u->s=3;
1327#if defined(LDEBUG)
1328        u->debug=123456;
1329#endif
1330        mpz_init_set(&u->z,&n->n);
1331        {
1332          int ui=(int)mpz_get_si(&u->z);
1333          if ((((ui<<3)>>3)==ui)
1334          && (mpz_cmp_si(&u->z,(long)ui)==0))
1335          {
1336            mpz_clear(&u->z);
1337            omFreeBin((ADDRESS)u, rnumber_bin);
1338            return INT_TO_SR(ui);
1339          }
1340        }
1341        return u;
1342      }
1343    }
1344  }
1345  return INT_TO_SR(1);
1346}
1347
1348/*2
1349* acces to Nominator, nlCopy(n) for integers
1350*/
1351number   nlGetNom(number &n, const ring r)
1352{
1353  if (!(SR_HDL(n) & SR_INT))
1354  {
1355    if (n->s==0)
1356    {
1357      nlNormalize(n);
1358    }
1359    if (!(SR_HDL(n) & SR_INT))
1360    {
1361      number u=(number)omAllocBin(rnumber_bin);
1362#if defined(LDEBUG)
1363      u->debug=123456;
1364#endif
1365      u->s=3;
1366      mpz_init_set(&u->z,&n->z);
1367      if (n->s!=3)
1368      {
1369        int ui=(int)mpz_get_si(&u->z);
1370        if ((((ui<<3)>>3)==ui)
1371        && (mpz_cmp_si(&u->z,(long)ui)==0))
1372        {
1373          mpz_clear(&u->z);
1374          omFreeBin((ADDRESS)u, rnumber_bin);
1375          return INT_TO_SR(ui);
1376        }
1377      }
1378      return u;
1379    }
1380  }
1381  return n; // imm. int
1382}
1383
1384/***************************************************************
1385 *
1386 * routines which are needed by Inline(d) routines
1387 *
1388 *******************************************************************/
1389BOOLEAN _nlEqual_aNoImm_OR_bNoImm(number a, number b)
1390{
1391  assume(! (SR_HDL(a) & SR_HDL(b) & SR_INT));
1392//  long - short
1393  BOOLEAN bo;
1394  if (SR_HDL(b) & SR_INT)
1395  {
1396    if (a->s!=0) return FALSE;
1397    number n=b; b=a; a=n;
1398  }
1399//  short - long
1400  if (SR_HDL(a) & SR_INT)
1401  {
1402    if (b->s!=0)
1403      return FALSE;
1404    if (((long)a > 0L) && (mpz_isNeg(&b->z)))
1405      return FALSE;
1406    if (((long)a < 0L) && (!mpz_isNeg(&b->z)))
1407      return FALSE;
1408    MP_INT  bb;
1409    mpz_init_set(&bb,&b->n);
1410    mpz_mul_si(&bb,&bb,(long)SR_TO_INT(a));
1411    bo=(mpz_cmp(&bb,&b->z)==0);
1412    mpz_clear(&bb);
1413    return bo;
1414  }
1415// long - long
1416  if (((a->s==1) && (b->s==3))
1417  ||  ((b->s==1) && (a->s==3)))
1418    return FALSE;
1419  if (mpz_isNeg(&a->z)&&(!mpz_isNeg(&b->z)))
1420    return FALSE;
1421  if (mpz_isNeg(&b->z)&&(!mpz_isNeg(&a->z)))
1422    return FALSE;
1423  MP_INT  aa;
1424  MP_INT  bb;
1425  mpz_init_set(&aa,&a->z);
1426  mpz_init_set(&bb,&b->z);
1427  if (a->s<2) mpz_mul(&bb,&bb,&a->n);
1428  if (b->s<2) mpz_mul(&aa,&aa,&b->n);
1429  bo=(mpz_cmp(&aa,&bb)==0);
1430  mpz_clear(&aa);
1431  mpz_clear(&bb);
1432  return bo;
1433}
1434
1435// copy not immediate number a
1436number _nlCopy_NoImm(number a)
1437{
1438  assume(!((SR_HDL(a) & SR_INT)||(a==NULL)));
1439#ifdef LDEBUG
1440  nlTest(a);
1441#endif
1442  number b=(number)omAllocBin(rnumber_bin);
1443#if defined(LDEBUG)
1444  b->debug=123456;
1445#endif
1446  switch (a->s)
1447  {
1448    case 0:
1449    case 1:
1450            mpz_init_set(&b->n,&a->n);
1451    case 3:
1452            mpz_init_set(&b->z,&a->z);
1453            break;
1454  }
1455  b->s = a->s;
1456#ifdef LDEBUG
1457  nlTest(b);
1458#endif
1459  return b;
1460}
1461
1462void _nlDelete_NoImm(number *a, const ring r)
1463{
1464  {
1465    switch ((*a)->s)
1466    {
1467      case 0:
1468      case 1:
1469        mpz_clear(&(*a)->n);
1470      case 3:
1471        mpz_clear(&(*a)->z);
1472#ifdef LDEBUG
1473        (*a)->s=2;
1474#endif
1475    }
1476    omFreeBin((ADDRESS) *a, rnumber_bin);
1477  }
1478}
1479
1480number _nlNeg_NoImm(number a)
1481{
1482  {
1483    mpz_neg(&a->z,&a->z);
1484    if ((a->s==3) && (mpz_size1(&a->z)<=MP_SMALL))
1485    {
1486      int ui=(int)mpz_get_si(&a->z);
1487      if ((((ui<<3)>>3)==ui)
1488        && (mpz_cmp_si(&a->z,(long)ui)==0))
1489      {
1490        mpz_clear(&a->z);
1491        omFreeBin((ADDRESS)a, rnumber_bin);
1492        a=INT_TO_SR(ui);
1493      }
1494    }
1495  }
1496#ifdef LDEBUG
1497  nlTest(a);
1498#endif
1499  return a;
1500}
1501
1502number _nlAdd_aNoImm_OR_bNoImm(number a, number b)
1503{
1504  number u=(number)omAllocBin(rnumber_bin);
1505#if defined(LDEBUG)
1506  u->debug=123456;
1507#endif
1508  mpz_init(&u->z);
1509  if (SR_HDL(b) & SR_INT)
1510  {
1511    number x=a;
1512    a=b;
1513    b=x;
1514  }
1515  if (SR_HDL(a) & SR_INT)
1516  {
1517    switch (b->s)
1518    {
1519      case 0:
1520      case 1:/* a:short, b:1 */
1521      {
1522        MP_INT x;
1523        mpz_init(&x);
1524        mpz_mul_si(&x,&b->n,SR_TO_INT(a));
1525        mpz_add(&u->z,&b->z,&x);
1526        mpz_clear(&x);
1527        if (mpz_cmp_ui(&u->z,(long)0)==0)
1528        {
1529          mpz_clear(&u->z);
1530          omFreeBin((ADDRESS)u, rnumber_bin);
1531          return INT_TO_SR(0);
1532        }
1533        if (mpz_cmp(&u->z,&b->n)==0)
1534        {
1535          mpz_clear(&u->z);
1536          omFreeBin((ADDRESS)u, rnumber_bin);
1537          return INT_TO_SR(1);
1538        }
1539        mpz_init_set(&u->n,&b->n);
1540        u->s = 0;
1541        break;
1542      }
1543      case 3:
1544      {
1545        if ((long)a>0L)
1546          mpz_add_ui(&u->z,&b->z,SR_TO_INT(a));
1547        else
1548          mpz_sub_ui(&u->z,&b->z,-SR_TO_INT(a));
1549        if (mpz_cmp_ui(&u->z,(long)0)==0)
1550        {
1551          mpz_clear(&u->z);
1552          omFreeBin((ADDRESS)u, rnumber_bin);
1553          return INT_TO_SR(0);
1554        }
1555        //u->s = 3;
1556        if (mpz_size1(&u->z)<=MP_SMALL)
1557        {
1558          int ui=(int)mpz_get_si(&u->z);
1559          if ((((ui<<3)>>3)==ui)
1560          && (mpz_cmp_si(&u->z,(long)ui)==0))
1561          {
1562            mpz_clear(&u->z);
1563            omFreeBin((ADDRESS)u, rnumber_bin);
1564            return INT_TO_SR(ui);
1565          }
1566        }
1567        u->s = 3;
1568        break;
1569      }
1570    }
1571  }
1572  else
1573  {
1574    switch (a->s)
1575    {
1576      case 0:
1577      case 1:
1578      {
1579        switch(b->s)
1580        {
1581          case 0:
1582          case 1:
1583          {
1584            MP_INT x;
1585            MP_INT y;
1586            mpz_init(&x);
1587            mpz_init(&y);
1588            mpz_mul(&x,&b->z,&a->n);
1589            mpz_mul(&y,&a->z,&b->n);
1590            mpz_add(&u->z,&x,&y);
1591            mpz_clear(&x);
1592            mpz_clear(&y);
1593            if (mpz_cmp_ui(&u->z,(long)0)==0)
1594            {
1595              mpz_clear(&u->z);
1596              omFreeBin((ADDRESS)u, rnumber_bin);
1597              return INT_TO_SR(0);
1598            }
1599            mpz_init(&u->n);
1600            mpz_mul(&u->n,&a->n,&b->n);
1601            if (mpz_cmp(&u->z,&u->n)==0)
1602            {
1603               mpz_clear(&u->z);
1604               mpz_clear(&u->n);
1605               omFreeBin((ADDRESS)u, rnumber_bin);
1606               return INT_TO_SR(1);
1607            }
1608            u->s = 0;
1609            break;
1610          }
1611          case 3: /* a:1 b:3 */
1612          {
1613            MP_INT x;
1614            mpz_init(&x);
1615            mpz_mul(&x,&b->z,&a->n);
1616            mpz_add(&u->z,&a->z,&x);
1617            mpz_clear(&x);
1618            if (mpz_cmp_ui(&u->z,(long)0)==0)
1619            {
1620              mpz_clear(&u->z);
1621              omFreeBin((ADDRESS)u, rnumber_bin);
1622              return INT_TO_SR(0);
1623            }
1624            if (mpz_cmp(&u->z,&a->n)==0)
1625            {
1626              mpz_clear(&u->z);
1627              omFreeBin((ADDRESS)u, rnumber_bin);
1628              return INT_TO_SR(1);
1629            }
1630            mpz_init_set(&u->n,&a->n);
1631            u->s = 0;
1632            break;
1633          }
1634        } /*switch (b->s) */
1635        break;
1636      }
1637      case 3:
1638      {
1639        switch(b->s)
1640        {
1641          case 0:
1642          case 1:/* a:3, b:1 */
1643          {
1644            MP_INT x;
1645            mpz_init(&x);
1646            mpz_mul(&x,&a->z,&b->n);
1647            mpz_add(&u->z,&b->z,&x);
1648            mpz_clear(&x);
1649            if (mpz_cmp_ui(&u->z,(long)0)==0)
1650            {
1651              mpz_clear(&u->z);
1652              omFreeBin((ADDRESS)u, rnumber_bin);
1653              return INT_TO_SR(0);
1654            }
1655            if (mpz_cmp(&u->z,&b->n)==0)
1656            {
1657              mpz_clear(&u->z);
1658              omFreeBin((ADDRESS)u, rnumber_bin);
1659              return INT_TO_SR(1);
1660            }
1661            mpz_init_set(&u->n,&b->n);
1662            u->s = 0;
1663            break;
1664          }
1665          case 3:
1666          {
1667            mpz_add(&u->z,&a->z,&b->z);
1668            if (mpz_cmp_ui(&u->z,(long)0)==0)
1669            {
1670              mpz_clear(&u->z);
1671              omFreeBin((ADDRESS)u, rnumber_bin);
1672              return INT_TO_SR(0);
1673            }
1674            if (mpz_size1(&u->z)<=MP_SMALL)
1675            {
1676              int ui=(int)mpz_get_si(&u->z);
1677              if ((((ui<<3)>>3)==ui)
1678              && (mpz_cmp_si(&u->z,(long)ui)==0))
1679              {
1680                mpz_clear(&u->z);
1681                omFreeBin((ADDRESS)u, rnumber_bin);
1682                return INT_TO_SR(ui);
1683              }
1684            }
1685            u->s = 3;
1686            break;
1687          }
1688        }
1689        break;
1690      }
1691    }
1692  }
1693#ifdef LDEBUG
1694  nlTest(u);
1695#endif
1696  return u;
1697}
1698
1699number _nlSub_aNoImm_OR_bNoImm(number a, number b)
1700{
1701  number u=(number)omAllocBin(rnumber_bin);
1702#if defined(LDEBUG)
1703  u->debug=123456;
1704#endif
1705  mpz_init(&u->z);
1706  if (SR_HDL(a) & SR_INT)
1707  {
1708    switch (b->s)
1709    {
1710      case 0:
1711      case 1:/* a:short, b:1 */
1712      {
1713        MP_INT x;
1714        mpz_init(&x);
1715        mpz_mul_si(&x,&b->n,SR_TO_INT(a));
1716        mpz_sub(&u->z,&x,&b->z);
1717        mpz_clear(&x);
1718        if (mpz_cmp_ui(&u->z,(long)0)==0)
1719        {
1720          mpz_clear(&u->z);
1721          omFreeBin((ADDRESS)u, rnumber_bin);
1722          return INT_TO_SR(0);
1723        }
1724        if (mpz_cmp(&u->z,&b->n)==0)
1725        {
1726          mpz_clear(&u->z);
1727          omFreeBin((ADDRESS)u, rnumber_bin);
1728          return INT_TO_SR(1);
1729        }
1730        mpz_init_set(&u->n,&b->n);
1731        u->s = 0;
1732        break;
1733      }
1734      case 3:
1735      {
1736        if ((long)a>0L)
1737        {
1738          mpz_sub_ui(&u->z,&b->z,SR_TO_INT(a));
1739          mpz_neg(&u->z,&u->z);
1740        }
1741        else
1742        {
1743          mpz_add_ui(&u->z,&b->z,-SR_TO_INT(a));
1744          mpz_neg(&u->z,&u->z);
1745        }
1746        if (mpz_cmp_ui(&u->z,(long)0)==0)
1747        {
1748          mpz_clear(&u->z);
1749          omFreeBin((ADDRESS)u, rnumber_bin);
1750          return INT_TO_SR(0);
1751        }
1752        if (mpz_size1(&u->z)<=MP_SMALL)
1753        {
1754          int ui=(int)mpz_get_si(&u->z);
1755          if ((((ui<<3)>>3)==ui)
1756          && (mpz_cmp_si(&u->z,(long)ui)==0))
1757          {
1758            mpz_clear(&u->z);
1759            omFreeBin((ADDRESS)u, rnumber_bin);
1760            return INT_TO_SR(ui);
1761          }
1762        }
1763        u->s = 3;
1764        break;
1765      }
1766    }
1767  }
1768  else if (SR_HDL(b) & SR_INT)
1769  {
1770    switch (a->s)
1771    {
1772      case 0:
1773      case 1:/* b:short, a:1 */
1774      {
1775        MP_INT x;
1776        mpz_init(&x);
1777        mpz_mul_si(&x,&a->n,SR_TO_INT(b));
1778        mpz_sub(&u->z,&a->z,&x);
1779        mpz_clear(&x);
1780        if (mpz_cmp_ui(&u->z,(long)0)==0)
1781        {
1782          mpz_clear(&u->z);
1783          omFreeBin((ADDRESS)u, rnumber_bin);
1784          return INT_TO_SR(0);
1785        }
1786        if (mpz_cmp(&u->z,&a->n)==0)
1787        {
1788          mpz_clear(&u->z);
1789          omFreeBin((ADDRESS)u, rnumber_bin);
1790          return INT_TO_SR(1);
1791        }
1792        mpz_init_set(&u->n,&a->n);
1793        u->s = 0;
1794        break;
1795      }
1796      case 3:
1797      {
1798        if ((long)b>0L)
1799        {
1800          mpz_sub_ui(&u->z,&a->z,SR_TO_INT(b));
1801        }
1802        else
1803        {
1804          mpz_add_ui(&u->z,&a->z,-SR_TO_INT(b));
1805        }
1806        if (mpz_cmp_ui(&u->z,(long)0)==0)
1807        {
1808          mpz_clear(&u->z);
1809          omFreeBin((ADDRESS)u, rnumber_bin);
1810          return INT_TO_SR(0);
1811        }
1812        //u->s = 3;
1813        if (mpz_size1(&u->z)<=MP_SMALL)
1814        {
1815          int ui=(int)mpz_get_si(&u->z);
1816          if ((((ui<<3)>>3)==ui)
1817          && (mpz_cmp_si(&u->z,(long)ui)==0))
1818          {
1819            mpz_clear(&u->z);
1820            omFreeBin((ADDRESS)u, rnumber_bin);
1821            return INT_TO_SR(ui);
1822          }
1823        }
1824        u->s = 3;
1825        break;
1826      }
1827    }
1828  }
1829  else
1830  {
1831    switch (a->s)
1832    {
1833      case 0:
1834      case 1:
1835      {
1836        switch(b->s)
1837        {
1838          case 0:
1839          case 1:
1840          {
1841            MP_INT x;
1842            MP_INT y;
1843            mpz_init(&x);
1844            mpz_init(&y);
1845            mpz_mul(&x,&b->z,&a->n);
1846            mpz_mul(&y,&a->z,&b->n);
1847            mpz_sub(&u->z,&y,&x);
1848            mpz_clear(&x);
1849            mpz_clear(&y);
1850            if (mpz_cmp_ui(&u->z,(long)0)==0)
1851            {
1852              mpz_clear(&u->z);
1853              omFreeBin((ADDRESS)u, rnumber_bin);
1854              return INT_TO_SR(0);
1855            }
1856            mpz_init(&u->n);
1857            mpz_mul(&u->n,&a->n,&b->n);
1858            if (mpz_cmp(&u->z,&u->n)==0)
1859            {
1860              mpz_clear(&u->z);
1861              mpz_clear(&u->n);
1862              omFreeBin((ADDRESS)u, rnumber_bin);
1863              return INT_TO_SR(1);
1864            }
1865            u->s = 0;
1866            break;
1867          }
1868          case 3: /* a:1, b:3 */
1869          {
1870            MP_INT x;
1871            mpz_init(&x);
1872            mpz_mul(&x,&b->z,&a->n);
1873            mpz_sub(&u->z,&a->z,&x);
1874            mpz_clear(&x);
1875            if (mpz_cmp_ui(&u->z,(long)0)==0)
1876            {
1877              mpz_clear(&u->z);
1878              omFreeBin((ADDRESS)u, rnumber_bin);
1879              return INT_TO_SR(0);
1880            }
1881            if (mpz_cmp(&u->z,&a->n)==0)
1882            {
1883              mpz_clear(&u->z);
1884              omFreeBin((ADDRESS)u, rnumber_bin);
1885              return INT_TO_SR(1);
1886            }
1887            mpz_init_set(&u->n,&a->n);
1888            u->s = 0;
1889            break;
1890          }
1891        }
1892        break;
1893      }
1894      case 3:
1895      {
1896        switch(b->s)
1897        {
1898          case 0:
1899          case 1: /* a:3, b:1 */
1900          {
1901            MP_INT x;
1902            mpz_init(&x);
1903            mpz_mul(&x,&a->z,&b->n);
1904            mpz_sub(&u->z,&x,&b->z);
1905            mpz_clear(&x);
1906            if (mpz_cmp_ui(&u->z,(long)0)==0)
1907            {
1908              mpz_clear(&u->z);
1909              omFreeBin((ADDRESS)u, rnumber_bin);
1910              return INT_TO_SR(0);
1911            }
1912            if (mpz_cmp(&u->z,&b->n)==0)
1913            {
1914              mpz_clear(&u->z);
1915              omFreeBin((ADDRESS)u, rnumber_bin);
1916              return INT_TO_SR(1);
1917            }
1918            mpz_init_set(&u->n,&b->n);
1919            u->s = 0;
1920            break;
1921          }
1922          case 3: /* a:3 , b:3 */
1923          {
1924            mpz_sub(&u->z,&a->z,&b->z);
1925            if (mpz_cmp_ui(&u->z,(long)0)==0)
1926            {
1927              mpz_clear(&u->z);
1928              omFreeBin((ADDRESS)u, rnumber_bin);
1929              return INT_TO_SR(0);
1930            }
1931            //u->s = 3;
1932            if (mpz_size1(&u->z)<=MP_SMALL)
1933            {
1934              int ui=(int)mpz_get_si(&u->z);
1935              if ((((ui<<3)>>3)==ui)
1936              && (mpz_cmp_si(&u->z,(long)ui)==0))
1937              {
1938                mpz_clear(&u->z);
1939                omFreeBin((ADDRESS)u, rnumber_bin);
1940                return INT_TO_SR(ui);
1941              }
1942            }
1943            u->s = 3;
1944            break;
1945          }
1946        }
1947        break;
1948      }
1949    }
1950  }
1951#ifdef LDEBUG
1952  nlTest(u);
1953#endif
1954  return u;
1955}
1956
1957// a and b are intermediate, but a*b not
1958number _nlMult_aImm_bImm_rNoImm(number a, number b)
1959{
1960  number u=(number)omAllocBin(rnumber_bin);
1961#if defined(LDEBUG)
1962  u->debug=123456;
1963#endif
1964  u->s=3;
1965  mpz_init_set_si(&u->z,(long)SR_TO_INT(a));
1966  mpz_mul_si(&u->z,&u->z,(long)SR_TO_INT(b));
1967#ifdef LDEBUG
1968  nlTest(u);
1969#endif
1970  return u;
1971}
1972
1973// a or b are not immediate
1974number _nlMult_aNoImm_OR_bNoImm(number a, number b)
1975{
1976  assume(! (SR_HDL(a) & SR_HDL(b) & SR_INT));
1977  number u=(number)omAllocBin(rnumber_bin);
1978#if defined(LDEBUG)
1979  u->debug=123456;
1980#endif
1981  mpz_init(&u->z);
1982  if (SR_HDL(b) & SR_INT)
1983  {
1984    number x=a;
1985    a=b;
1986    b=x;
1987  }
1988  if (SR_HDL(a) & SR_INT)
1989  {
1990    u->s=b->s;
1991    if (u->s==1) u->s=0;
1992    if ((long)a>0L)
1993    {
1994      mpz_mul_ui(&u->z,&b->z,(unsigned long)SR_TO_INT(a));
1995    }
1996    else
1997    {
1998      if (a==INT_TO_SR(-1))
1999      {
2000        mpz_set(&u->z,&b->z);
2001        mpz_neg(&u->z,&u->z);
2002        u->s=b->s;
2003      }
2004      else
2005      {
2006        mpz_mul_ui(&u->z,&b->z,(unsigned long)-SR_TO_INT(a));
2007        mpz_neg(&u->z,&u->z);
2008      }
2009    }
2010    if (u->s<2)
2011    {
2012      if (mpz_cmp(&u->z,&b->n)==0)
2013      {
2014        mpz_clear(&u->z);
2015        omFreeBin((ADDRESS)u, rnumber_bin);
2016        return INT_TO_SR(1);
2017      }
2018      mpz_init_set(&u->n,&b->n);
2019    }
2020    else //u->s==3
2021    {
2022      if (mpz_size1(&u->z)<=MP_SMALL)
2023      {
2024        int ui=(int)mpz_get_si(&u->z);
2025        if ((((ui<<3)>>3)==ui)
2026            && (mpz_cmp_si(&u->z,(long)ui)==0))
2027        {
2028          mpz_clear(&u->z);
2029          omFreeBin((ADDRESS)u, rnumber_bin);
2030          return INT_TO_SR(ui);
2031        }
2032      }
2033    }
2034  }
2035  else
2036  {
2037    mpz_mul(&u->z,&a->z,&b->z);
2038    u->s = 0;
2039    if(a->s==3)
2040    {
2041      if(b->s==3)
2042      {
2043        u->s = 3;
2044      }
2045      else
2046      {
2047        if (mpz_cmp(&u->z,&b->n)==0)
2048        {
2049          mpz_clear(&u->z);
2050          omFreeBin((ADDRESS)u, rnumber_bin);
2051          return INT_TO_SR(1);
2052        }
2053        mpz_init_set(&u->n,&b->n);
2054      }
2055    }
2056    else
2057    {
2058      if(b->s==3)
2059      {
2060        if (mpz_cmp(&u->z,&a->n)==0)
2061        {
2062          mpz_clear(&u->z);
2063          omFreeBin((ADDRESS)u, rnumber_bin);
2064          return INT_TO_SR(1);
2065        }
2066        mpz_init_set(&u->n,&a->n);
2067      }
2068      else
2069      {
2070        mpz_init(&u->n);
2071        mpz_mul(&u->n,&a->n,&b->n);
2072        if (mpz_cmp(&u->z,&u->n)==0)
2073        {
2074          mpz_clear(&u->z);
2075          mpz_clear(&u->n);
2076          omFreeBin((ADDRESS)u, rnumber_bin);
2077          return INT_TO_SR(1);
2078        }
2079      }
2080    }
2081  }
2082#ifdef LDEBUG
2083  nlTest(u);
2084#endif
2085  return u;
2086}
2087
2088/*2
2089* z := i
2090*/
2091number nlRInit (int i)
2092{
2093  number z=(number)omAllocBin(rnumber_bin);
2094#if defined(LDEBUG)
2095  z->debug=123456;
2096#endif
2097  mpz_init_set_si(&z->z,(long)i);
2098  z->s = 3;
2099  return z;
2100}
2101
2102/*2
2103* z := i/j
2104*/
2105number nlInit2 (int i, int j)
2106{
2107  number z=(number)omAllocBin(rnumber_bin);
2108#if defined(LDEBUG)
2109  z->debug=123456;
2110#endif
2111  mpz_init_set_si(&z->z,(long)i);
2112  mpz_init_set_si(&z->n,(long)j);
2113  z->s = 0;
2114  nlNormalize(z);
2115  return z;
2116}
2117
2118#else // DO_LINLINE
2119
2120// declare immedate routines
2121number nlRInit (int i);
2122BOOLEAN _nlEqual_aNoImm_OR_bNoImm(number a, number b);
2123number  _nlCopy_NoImm(number a);
2124void    _nlDelete_NoImm(number *a, const ring r);
2125number  _nlNeg_NoImm(number a);
2126number  _nlAdd_aNoImm_OR_bNoImm(number a, number b);
2127number  _nlSub_aNoImm_OR_bNoImm(number a, number b);
2128number  _nlMult_aNoImm_OR_bNoImm(number a, number b);
2129number  _nlMult_aImm_bImm_rNoImm(number a, number b);
2130
2131#endif
2132
2133
2134/***************************************************************
2135 *
2136 * Routines which might be inlined by p_Numbers.h
2137 *
2138 *******************************************************************/
2139#if defined(DO_LINLINE) || !defined(P_NUMBERS_H)
2140
2141// routines which are always inlined/static
2142
2143/*2
2144* a = b ?
2145*/
2146LINLINE BOOLEAN nlEqual (number a, number b)
2147{
2148#ifdef LDEBUG
2149  nlTest(a);
2150  nlTest(b);
2151#endif
2152// short - short
2153  if (SR_HDL(a) & SR_HDL(b) & SR_INT) return a==b;
2154  return _nlEqual_aNoImm_OR_bNoImm(a, b);
2155}
2156
2157
2158LINLINE number nlInit (int i)
2159{
2160  number n;
2161  if ( ((i << 3) >> 3) == i ) n=INT_TO_SR(i);
2162  else                        n=nlRInit(i);
2163#ifdef LDEBUG
2164  nlTest(n);
2165#endif
2166  return n;
2167}
2168
2169
2170/*2
2171* a == 1 ?
2172*/
2173LINLINE BOOLEAN nlIsOne (number a)
2174{
2175#ifdef LDEBUG
2176  if (a==NULL) return FALSE;
2177  nlTest(a);
2178#endif
2179  if (SR_HDL(a) & SR_INT) return (a==INT_TO_SR(1));
2180  return FALSE;
2181}
2182
2183LINLINE BOOLEAN nlIsZero (number a)
2184{
2185  return (a==INT_TO_SR(0));
2186}
2187
2188/*2
2189* copy a to b
2190*/
2191LINLINE number nlCopy(number a)
2192{
2193  if ((SR_HDL(a) & SR_INT)||(a==NULL))
2194  {
2195    return a;
2196  }
2197  return _nlCopy_NoImm(a);
2198}
2199
2200
2201LINLINE void nlNew (number * r)
2202{
2203  *r=NULL;
2204}
2205
2206/*2
2207* delete a
2208*/
2209LINLINE void nlDelete (number * a, const ring r)
2210{
2211  if (*a!=NULL)
2212  {
2213#ifdef LDEBUG
2214    nlTest(*a);
2215#endif
2216    if ((SR_HDL(*a) & SR_INT)==0)
2217    {
2218      _nlDelete_NoImm(a,r);
2219    }
2220    *a=NULL;
2221  }
2222}
2223
2224/*2
2225* za:= - za
2226*/
2227LINLINE number nlNeg (number a)
2228{
2229#ifdef LDEBUG
2230  nlTest(a);
2231#endif
2232  if(SR_HDL(a) &SR_INT)
2233  {
2234    int r=SR_TO_INT(a);
2235    if (r==(-(1<<28))) a=nlRInit(1<<28);
2236    else               a=INT_TO_SR(-r);
2237    return a;
2238  }
2239  return _nlNeg_NoImm(a);
2240}
2241
2242/*2
2243* u:= a + b
2244*/
2245LINLINE number nlAdd (number a, number b)
2246{
2247  number u;
2248  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2249  {
2250    int r=SR_HDL(a)+SR_HDL(b)-1;
2251    if ( ((r << 1) >> 1) == r )
2252      return (number)r;
2253    else
2254      return nlRInit(SR_TO_INT(r));
2255  }
2256  return _nlAdd_aNoImm_OR_bNoImm(a, b);
2257}
2258
2259LINLINE number nlMult (number a, number b)
2260{
2261#ifdef LDEBUG
2262  nlTest(a);
2263  nlTest(b);
2264#endif
2265  if (a==INT_TO_SR(0)) return INT_TO_SR(0);
2266  if (b==INT_TO_SR(0)) return INT_TO_SR(0);
2267  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2268  {
2269    int r=(SR_HDL(a)-1)*(SR_HDL(b)>>1);
2270    if ((r/(SR_HDL(b)>>1))==(SR_HDL(a)-1))
2271    {
2272      number u=((number) ((r>>1)+SR_INT));
2273      if (((SR_HDL(u)<<1)>>1)==SR_HDL(u)) return (u);
2274      return nlRInit(SR_HDL(u)>>2);
2275    }
2276    return _nlMult_aImm_bImm_rNoImm(a, b);
2277  }
2278  return _nlMult_aNoImm_OR_bNoImm(a, b);
2279}
2280
2281
2282/*2
2283* u:= a - b
2284*/
2285LINLINE number nlSub (number a, number b)
2286{
2287  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2288  {
2289    int r=SR_HDL(a)-SR_HDL(b)+1;
2290    if ( ((r << 1) >> 1) == r )
2291    {
2292      return (number)r;
2293    }
2294    else
2295      return nlRInit(SR_TO_INT(r));
2296  }
2297  return _nlSub_aNoImm_OR_bNoImm(a, b);
2298}
2299
2300#endif // DO_LINLINE
2301
2302#ifndef P_NUMBERS_H
2303
2304void nlInpGcd(number &a, number b, ring r)
2305{
2306  if ((SR_HDL(b)|SR_HDL(a))&SR_INT)
2307  {
2308    number n=nlGcd(a,b,r);
2309    nlDelete(&a,r);
2310    a=n;
2311  }
2312  else
2313  {
2314    mpz_gcd(&a->z,&a->z,&b->z);
2315    if (mpz_size1(&a->z)<=MP_SMALL)
2316    {
2317      int ui=(int)mpz_get_si(&a->z);
2318      if ((((ui<<3)>>3)==ui)
2319      && (mpz_cmp_si(&a->z,(long)ui)==0))
2320      {
2321        mpz_clear(&a->z);
2322        omFreeBin((ADDRESS)a, rnumber_bin);
2323        a=INT_TO_SR(ui);
2324      }
2325    }
2326  }
2327}
2328void nlInpIntDiv(number &a, number b, ring r)
2329{
2330  if ((SR_HDL(b)|SR_HDL(a))&SR_INT)
2331  {
2332    number n=nlIntDiv(a,b);
2333    nlDelete(&a,r);
2334    a=n;
2335  }
2336  else
2337  {
2338    if (mpz_isNeg(&a->z))
2339    {
2340      if (mpz_isNeg(&b->z))
2341      {
2342        mpz_add(&a->z,&a->z,&b->z);
2343      }
2344      else
2345      {
2346        mpz_sub(&a->z,&a->z,&b->z);
2347      }
2348      mpz_add_ui(&a->z,&a->z,1);
2349    }
2350    else
2351    {
2352      if (mpz_isNeg(&b->z))
2353      {
2354        mpz_sub(&a->z,&a->z,&b->z);
2355      }
2356      else
2357      {
2358        mpz_add(&a->z,&a->z,&b->z);
2359      }
2360      mpz_sub_ui(&a->z,&a->z,1);
2361    }
2362    MPZ_DIV(&a->z,&a->z,&b->z);
2363    if (mpz_size1(&a->z)<=MP_SMALL)
2364    {
2365      int ui=(int)mpz_get_si(&a->z);
2366      if ((((ui<<3)>>3)==ui)
2367      && (mpz_cmp_si(&a->z,(long)ui)==0))
2368      {
2369        mpz_clear(&a->z);
2370        omFreeBin((ADDRESS)a, rnumber_bin);
2371        a=INT_TO_SR(ui);
2372      }
2373    }
2374  }
2375}
2376void nlInpAdd(number &a, number b, ring r)
2377{
2378  // TODO
2379  if ((SR_HDL(b)|SR_HDL(a))&SR_INT)
2380  {
2381    number n=nlGcd(a,b,r);
2382    nlDelete(&a,r);
2383    a=n;
2384  }
2385  else
2386  {
2387    mpz_gcd(&a->z,&a->z,&b->z);
2388    if (mpz_size1(&a->z)<=MP_SMALL)
2389    {
2390      int ui=(int)mpz_get_si(&a->z);
2391      if ((((ui<<3)>>3)==ui)
2392      && (mpz_cmp_si(&a->z,(long)ui)==0))
2393      {
2394        mpz_clear(&a->z);
2395        omFreeBin((ADDRESS)a, rnumber_bin);
2396        a=INT_TO_SR(ui);
2397      }
2398    }
2399  }
2400}
2401void nlInpMult(number &a, number b, ring r)
2402{
2403  if (((SR_HDL(b)|SR_HDL(a))&SR_INT)
2404  )
2405  {
2406    number n=nlMult(a,b);
2407    nlDelete(&a,r);
2408    a=n;
2409  }
2410  else
2411  {
2412    mpz_mul(&a->z,&a->z,&b->z);
2413    if (a->s==3)
2414    {
2415      if(b->s!=3)
2416      {
2417        mpz_init_set(&a->n,&b->n);
2418        a->s=0;
2419      }
2420    }
2421    else
2422    {
2423      if(b->s!=3)
2424      {
2425        mpz_mul(&a->n,&a->n,&b->n);
2426      }
2427      a->s=0;
2428    }
2429  }
2430}
2431
2432#if 0
2433number nlMod(number a, number b)
2434{
2435  if (((SR_HDL(b)&SR_HDL(a))&SR_INT)
2436  {
2437    int bi=SR_TO_INT(b);
2438    int ai=SR_TO_INT(a);
2439    int bb=ABS(bi);
2440    int c=ai%bb;
2441    if (c<0)  c+=bb;
2442    return (INT_TO_SR(c));
2443  }
2444  number al;
2445  number bl;
2446  if (SR_HDL(a))&SR_INT)
2447    al=nlRInit(SR_TO_INT(a));
2448  else
2449    al=nlCopy(a);
2450  if (SR_HDL(b))&SR_INT)
2451    bl=nlRInit(SR_TO_INT(b));
2452  else
2453    bl=nlCopy(b);
2454  number r=nlRInit(0);
2455  mpz_mod(r->z,al->z,bl->z);
2456  nlDelete(&al);
2457  nlDelete(&bl);
2458  if (mpz_size1(&r->z)<=MP_SMALL)
2459  {
2460    int ui=(int)mpz_get_si(&r->z);
2461    if ((((ui<<3)>>3)==ui)
2462    && (mpz_cmp_si(&x->z,(long)ui)==0))
2463    {
2464      mpz_clear(&r->z);
2465      omFreeBin((ADDRESS)r, rnumber_bin);
2466      r=INT_TO_SR(ui);
2467    }
2468  }
2469  return r;
2470}
2471#endif
2472#endif // not P_NUMBERS_H
2473#endif // LONGRAT_CC
Note: See TracBrowser for help on using the repository browser.