source: git/libpolys/coeffs/longrat.cc @ 0afa07

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