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

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