source: git/libpolys/coeffs/longrat.cc @ 7326063

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