source: git/Singular/longrat.cc @ 980f81

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