source: git/kernel/longrat.cc @ 09d7782

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