source: git/libpolys/coeffs/longrat.cc @ 12777c

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