source: git/libpolys/coeffs/longrat.cc @ 61e855

fieker-DuValspielwiese
Last change on this file since 61e855 was 8887b4, checked in by Hans Schoenemann <hannes@…>, 7 years ago
chg: make nlChineseRemainderSym usable for Q.Z. bigint
  • Property mode set to 100644
File size: 70.4 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 bb=NULL;
756  if (SR_HDL(b) & SR_INT)
757  {
758    bb=nlRInit(SR_TO_INT(b));
759    b=bb;
760  }
761  u=ALLOC_RNUMBER();
762#if defined(LDEBUG)
763  u->debug=123456;
764#endif
765  mpz_init(u->z);
766  /* u=a/b */
767  u->s = 3;
768  mpz_divexact(u->z,a->z,b->z);
769  if (bb!=NULL)
770  {
771    mpz_clear(bb->z);
772#if defined(LDEBUG)
773    bb->debug=654324;
774#endif
775    FREE_RNUMBER(bb); // omFreeBin((void *)bb, rnumber_bin);
776  }
777  u=nlShort3(u);
778  nlTest(u, r);
779  return u;
780}
781
782/*2
783* u := a / b in Z
784*/
785number nlIntDiv (number a, number b, const coeffs r)
786{
787  if (b==INT_TO_SR(0))
788  {
789    WerrorS(nDivBy0);
790    return INT_TO_SR(0);
791  }
792  if (a==INT_TO_SR(0))
793    return INT_TO_SR(0);
794  number u;
795  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
796  {
797    /* the small int -(1<<28) divided by -1 is the large int (1<<28)   */
798    if ((a==INT_TO_SR(-(POW_2_28)))&&(b==INT_TO_SR(-1L)))
799    {
800      return nlRInit(POW_2_28);
801    }
802    LONG aa=SR_TO_INT(a);
803    LONG bb=SR_TO_INT(b);
804    LONG rr=aa%bb;
805    if (rr<0) rr+=ABS(bb);
806    LONG cc=(aa-rr)/bb;
807    return INT_TO_SR(cc);
808  }
809  number aa=NULL;
810  if (SR_HDL(a) & SR_INT)
811  {
812    /* the small int -(1<<28) divided by 2^28 is 1   */
813    if (a==INT_TO_SR(-(POW_2_28)))
814    {
815      if(mpz_cmp_si(b->z,(POW_2_28))==0)
816      {
817        return INT_TO_SR(-1);
818      }
819    }
820    aa=nlRInit(SR_TO_INT(a));
821    a=aa;
822  }
823  number bb=NULL;
824  if (SR_HDL(b) & SR_INT)
825  {
826    bb=nlRInit(SR_TO_INT(b));
827    b=bb;
828  }
829  u=ALLOC_RNUMBER();
830#if defined(LDEBUG)
831  u->debug=123456;
832#endif
833  assume(a->s==3);
834  assume(b->s==3);
835  mpz_init_set(u->z,a->z);
836  /* u=u/b */
837  u->s = 3;
838  number rr=nlIntMod(a,b,r);
839  if (SR_HDL(rr) &  SR_INT) mpz_sub_ui(u->z,u->z,SR_TO_INT(rr));
840  else                      mpz_sub(u->z,u->z,rr->z);
841  mpz_divexact(u->z,u->z,b->z);
842  if (aa!=NULL)
843  {
844    mpz_clear(aa->z);
845#if defined(LDEBUG)
846    aa->debug=654324;
847#endif
848    FREE_RNUMBER(aa);
849  }
850  if (bb!=NULL)
851  {
852    mpz_clear(bb->z);
853#if defined(LDEBUG)
854    bb->debug=654324;
855#endif
856    FREE_RNUMBER(bb);
857  }
858  u=nlShort3(u);
859  nlTest(u,r);
860  return u;
861}
862
863/*2
864* u := a mod b in Z, u>=0
865*/
866number nlIntMod (number a, number b, const coeffs r)
867{
868  if (b==INT_TO_SR(0))
869  {
870    WerrorS(nDivBy0);
871    return INT_TO_SR(0);
872  }
873  if (a==INT_TO_SR(0))
874    return INT_TO_SR(0);
875  number u;
876  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
877  {
878    LONG aa=SR_TO_INT(a);
879    LONG bb=SR_TO_INT(b);
880    LONG c=aa % bb;
881    if (c<0) c+=ABS(bb);
882    return INT_TO_SR(c);
883  }
884  if (SR_HDL(a) & SR_INT)
885  {
886    LONG ai=SR_TO_INT(a);
887    mpz_t aa;
888    mpz_init_set_si(aa, ai);
889    u=ALLOC_RNUMBER();
890#if defined(LDEBUG)
891    u->debug=123456;
892#endif
893    u->s = 3;
894    mpz_init(u->z);
895    mpz_mod(u->z, aa, b->z);
896    mpz_clear(aa);
897    u=nlShort3(u);
898    nlTest(u,r);
899    return u;
900  }
901  number bb=NULL;
902  if (SR_HDL(b) & SR_INT)
903  {
904    bb=nlRInit(SR_TO_INT(b));
905    b=bb;
906  }
907  u=ALLOC_RNUMBER();
908#if defined(LDEBUG)
909  u->debug=123456;
910#endif
911  mpz_init(u->z);
912  u->s = 3;
913  mpz_mod(u->z, a->z, b->z);
914  if (bb!=NULL)
915  {
916    mpz_clear(bb->z);
917#if defined(LDEBUG)
918    bb->debug=654324;
919#endif
920    FREE_RNUMBER(bb);
921  }
922  u=nlShort3(u);
923  nlTest(u,r);
924  return u;
925}
926
927BOOLEAN nlDivBy (number a,number b, const coeffs)
928{
929  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
930  {
931    return ((SR_TO_INT(a) % SR_TO_INT(b))==0);
932  }
933  if (SR_HDL(b) & SR_INT)
934  {
935    return (mpz_divisible_ui_p(a->z,SR_TO_INT(b))!=0);
936  }
937  if (SR_HDL(a) & SR_INT) return FALSE;
938  return mpz_divisible_p(a->z, b->z) != 0;
939}
940
941int nlDivComp(number a, number b, const coeffs r)
942{
943  if (nlDivBy(a, b, r))
944  {
945    if (nlDivBy(b, a, r)) return 2;
946    return -1;
947  }
948  if (nlDivBy(b, a, r)) return 1;
949  return 0;
950}
951
952number  nlGetUnit (number, const coeffs)
953{
954  return INT_TO_SR(1);
955}
956
957coeffs nlQuot1(number c, const coeffs r)
958{
959  long ch = r->cfInt(c, r);
960  int p=IsPrime(ch);
961  coeffs rr=NULL;
962  if (((long)p)==ch)
963  {
964    rr = nInitChar(n_Zp,(void*)ch);
965  }
966  #ifdef HAVE_RINGS
967  else
968  {
969    mpz_ptr dummy;
970    dummy = (mpz_ptr) omAlloc(sizeof(mpz_t));
971    mpz_init_set_ui(dummy, ch);
972    ZnmInfo info;
973    info.base = dummy;
974    info.exp = (unsigned long) 1;
975    rr = nInitChar(n_Zn, (void*)&info);
976  }
977  #endif
978  return(rr);
979}
980
981
982BOOLEAN nlIsUnit (number a, const coeffs)
983{
984  return ((SR_HDL(a) & SR_INT) && (ABS(SR_TO_INT(a))==1));
985}
986
987
988/*2
989* u := a / b
990*/
991number nlDiv (number a, number b, const coeffs r)
992{
993  if (nlIsZero(b,r))
994  {
995    WerrorS(nDivBy0);
996    return INT_TO_SR(0);
997  }
998  number u;
999// ---------- short / short ------------------------------------
1000  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
1001  {
1002    LONG i=SR_TO_INT(a);
1003    LONG j=SR_TO_INT(b);
1004    if (j==1L) return a;
1005    if ((i==-POW_2_28) && (j== -1L))
1006    {
1007      return nlRInit(POW_2_28);
1008    }
1009    LONG r=i%j;
1010    if (r==0)
1011    {
1012      return INT_TO_SR(i/j);
1013    }
1014    u=ALLOC_RNUMBER();
1015    u->s=0;
1016    #if defined(LDEBUG)
1017    u->debug=123456;
1018    #endif
1019    mpz_init_set_si(u->z,(long)i);
1020    mpz_init_set_si(u->n,(long)j);
1021  }
1022  else
1023  {
1024    u=ALLOC_RNUMBER();
1025    u->s=0;
1026    #if defined(LDEBUG)
1027    u->debug=123456;
1028    #endif
1029    mpz_init(u->z);
1030// ---------- short / long ------------------------------------
1031    if (SR_HDL(a) & SR_INT)
1032    {
1033      // short a / (z/n) -> (a*n)/z
1034      if (b->s<2)
1035      {
1036        mpz_mul_si(u->z,b->n,SR_TO_INT(a));
1037      }
1038      else
1039      // short a / long z -> a/z
1040      {
1041        mpz_set_si(u->z,SR_TO_INT(a));
1042      }
1043      if (mpz_cmp(u->z,b->z)==0)
1044      {
1045        mpz_clear(u->z);
1046        FREE_RNUMBER(u);
1047        return INT_TO_SR(1);
1048      }
1049      mpz_init_set(u->n,b->z);
1050    }
1051// ---------- long / short ------------------------------------
1052    else if (SR_HDL(b) & SR_INT)
1053    {
1054      mpz_set(u->z,a->z);
1055      // (z/n) / b -> z/(n*b)
1056      if (a->s<2)
1057      {
1058        mpz_init_set(u->n,a->n);
1059        if (((long)b)>0L)
1060          mpz_mul_ui(u->n,u->n,SR_TO_INT(b));
1061        else
1062        {
1063          mpz_mul_ui(u->n,u->n,-SR_TO_INT(b));
1064          mpz_neg(u->z,u->z);
1065        }
1066      }
1067      else
1068      // long z / short b -> z/b
1069      {
1070        //mpz_set(u->z,a->z);
1071        mpz_init_set_si(u->n,SR_TO_INT(b));
1072      }
1073    }
1074// ---------- long / long ------------------------------------
1075    else
1076    {
1077      mpz_set(u->z,a->z);
1078      mpz_init_set(u->n,b->z);
1079      if (a->s<2) mpz_mul(u->n,u->n,a->n);
1080      if (b->s<2) mpz_mul(u->z,u->z,b->n);
1081    }
1082  }
1083  if (mpz_isNeg(u->n))
1084  {
1085    mpz_neg(u->z,u->z);
1086    mpz_neg(u->n,u->n);
1087  }
1088  if (mpz_cmp_si(u->n,1L)==0)
1089  {
1090    mpz_clear(u->n);
1091    u->s=3;
1092    u=nlShort3(u);
1093  }
1094  nlTest(u, r);
1095  return u;
1096}
1097
1098/*2
1099* u:= x ^ exp
1100*/
1101void nlPower (number x,int exp,number * u, const coeffs r)
1102{
1103  *u = INT_TO_SR(0); // 0^e, e!=0
1104  if (exp==0)
1105    *u= INT_TO_SR(1);
1106  else if (!nlIsZero(x,r))
1107  {
1108    nlTest(x, r);
1109    number aa=NULL;
1110    if (SR_HDL(x) & SR_INT)
1111    {
1112      aa=nlRInit(SR_TO_INT(x));
1113      x=aa;
1114    }
1115    else if (x->s==0)
1116      nlNormalize(x,r);
1117    *u=ALLOC_RNUMBER();
1118#if defined(LDEBUG)
1119    (*u)->debug=123456;
1120#endif
1121    mpz_init((*u)->z);
1122    mpz_pow_ui((*u)->z,x->z,(unsigned long)exp);
1123    if (x->s<2)
1124    {
1125      if (mpz_cmp_si(x->n,1L)==0)
1126      {
1127        x->s=3;
1128        mpz_clear(x->n);
1129      }
1130      else
1131      {
1132        mpz_init((*u)->n);
1133        mpz_pow_ui((*u)->n,x->n,(unsigned long)exp);
1134      }
1135    }
1136    (*u)->s = x->s;
1137    if ((*u)->s==3) *u=nlShort3(*u);
1138    if (aa!=NULL)
1139    {
1140      mpz_clear(aa->z);
1141      FREE_RNUMBER(aa);
1142    }
1143  }
1144#ifdef LDEBUG
1145  if (exp<0) Print("nlPower: neg. exp. %d\n",exp);
1146  nlTest(*u, r);
1147#endif
1148}
1149
1150
1151/*2
1152* za >= 0 ?
1153*/
1154BOOLEAN nlGreaterZero (number a, const coeffs r)
1155{
1156  nlTest(a, r);
1157  if (SR_HDL(a) & SR_INT) return SR_HDL(a)>1L /* represents number(0) */;
1158  return (!mpz_isNeg(a->z));
1159}
1160
1161/*2
1162* a > b ?
1163*/
1164BOOLEAN nlGreater (number a, number b, const coeffs r)
1165{
1166  nlTest(a, r);
1167  nlTest(b, r);
1168  number re;
1169  BOOLEAN rr;
1170  re=nlSub(a,b,r);
1171  rr=(!nlIsZero(re,r)) && (nlGreaterZero(re,r));
1172  nlDelete(&re,r);
1173  return rr;
1174}
1175
1176/*2
1177* a == -1 ?
1178*/
1179BOOLEAN nlIsMOne (number a, const coeffs r)
1180{
1181#ifdef LDEBUG
1182  if (a==NULL) return FALSE;
1183  nlTest(a, r);
1184#endif
1185  return  (a==INT_TO_SR(-1L));
1186}
1187
1188/*2
1189* result =gcd(a,b)
1190*/
1191number nlGcd(number a, number b, const coeffs r)
1192{
1193  number result;
1194  nlTest(a, r);
1195  nlTest(b, r);
1196  //nlNormalize(a);
1197  //nlNormalize(b);
1198  if ((a==INT_TO_SR(1L))||(a==INT_TO_SR(-1L))
1199  ||  (b==INT_TO_SR(1L))||(b==INT_TO_SR(-1L)))
1200    return INT_TO_SR(1L);
1201  if (a==INT_TO_SR(0)) /* gcd(0,b) ->b */
1202    return nlCopy(b,r);
1203  if (b==INT_TO_SR(0)) /* gcd(a,0) -> a */
1204    return nlCopy(a,r);
1205  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
1206  {
1207    long i=SR_TO_INT(a);
1208    long j=SR_TO_INT(b);
1209    if((i==0L)||(j==0L))
1210      return INT_TO_SR(1);
1211    long l;
1212    i=ABS(i);
1213    j=ABS(j);
1214    do
1215    {
1216      l=i%j;
1217      i=j;
1218      j=l;
1219    } while (l!=0L);
1220    if (i==POW_2_28)
1221      result=nlRInit(POW_2_28);
1222    else
1223     result=INT_TO_SR(i);
1224    nlTest(result,r);
1225    return result;
1226  }
1227  if (((!(SR_HDL(a) & SR_INT))&&(a->s<2))
1228  ||  ((!(SR_HDL(b) & SR_INT))&&(b->s<2))) return INT_TO_SR(1);
1229  if (SR_HDL(a) & SR_INT)
1230  {
1231    LONG aa=ABS(SR_TO_INT(a));
1232    unsigned long t=mpz_gcd_ui(NULL,b->z,(long)aa);
1233    if (t==POW_2_28)
1234      result=nlRInit(POW_2_28);
1235    else
1236     result=INT_TO_SR(t);
1237  }
1238  else
1239  if (SR_HDL(b) & SR_INT)
1240  {
1241    LONG bb=ABS(SR_TO_INT(b));
1242    unsigned long t=mpz_gcd_ui(NULL,a->z,(long)bb);
1243    if (t==POW_2_28)
1244      result=nlRInit(POW_2_28);
1245    else
1246     result=INT_TO_SR(t);
1247  }
1248  else
1249  {
1250    result=ALLOC0_RNUMBER();
1251    result->s = 3;
1252  #ifdef LDEBUG
1253    result->debug=123456;
1254  #endif
1255    mpz_init(result->z);
1256    mpz_gcd(result->z,a->z,b->z);
1257    result=nlShort3(result);
1258  }
1259  nlTest(result, r);
1260  return result;
1261}
1262static int int_extgcd(int a, int b, int * u, int* x, int * v, int* y)
1263{
1264  int q, r;
1265  if (a==0)
1266  {
1267    *u = 0;
1268    *v = 1;
1269    *x = -1;
1270    *y = 0;
1271    return b;
1272  }
1273  if (b==0)
1274  {
1275    *u = 1;
1276    *v = 0;
1277    *x = 0;
1278    *y = 1;
1279    return a;
1280  }
1281  *u=1;
1282  *v=0;
1283  *x=0;
1284  *y=1;
1285  do
1286  {
1287    q = a/b;
1288    r = a%b;
1289    assume (q*b+r == a);
1290    a = b;
1291    b = r;
1292
1293    r = -(*v)*q+(*u);
1294    (*u) =(*v);
1295    (*v) = r;
1296
1297    r = -(*y)*q+(*x);
1298    (*x) = (*y);
1299    (*y) = r;
1300  } while (b);
1301
1302  return a;
1303}
1304
1305//number nlGcd_dummy(number a, number b, const coeffs r)
1306//{
1307//  extern char my_yylinebuf[80];
1308//  Print("nlGcd in >>%s<<\n",my_yylinebuf);
1309//  return nlGcd(a,b,r);;
1310//}
1311
1312number nlShort1(number x) // assume x->s==0/1
1313{
1314  assume(x->s<2);
1315  if (mpz_cmp_ui(x->z,0L)==0)
1316  {
1317    _nlDelete_NoImm(&x);
1318    return INT_TO_SR(0);
1319  }
1320  if (x->s<2)
1321  {
1322    if (mpz_cmp(x->z,x->n)==0)
1323    {
1324      _nlDelete_NoImm(&x);
1325      return INT_TO_SR(1);
1326    }
1327  }
1328  return x;
1329}
1330/*2
1331* simplify x
1332*/
1333void nlNormalize (number &x, const coeffs r)
1334{
1335  if ((SR_HDL(x) & SR_INT) ||(x==NULL))
1336    return;
1337  if (x->s==3)
1338  {
1339    x=nlShort3_noinline(x);
1340    nlTest(x,r);
1341    return;
1342  }
1343  else if (x->s==0)
1344  {
1345    if (mpz_cmp_si(x->n,1L)==0)
1346    {
1347      mpz_clear(x->n);
1348      x->s=3;
1349      x=nlShort3(x);
1350    }
1351    else
1352    {
1353      mpz_t gcd;
1354      mpz_init(gcd);
1355      mpz_gcd(gcd,x->z,x->n);
1356      x->s=1;
1357      if (mpz_cmp_si(gcd,1L)!=0)
1358      {
1359        mpz_divexact(x->z,x->z,gcd);
1360        mpz_divexact(x->n,x->n,gcd);
1361        if (mpz_cmp_si(x->n,1L)==0)
1362        {
1363          mpz_clear(x->n);
1364          x->s=3;
1365          x=nlShort3_noinline(x);
1366        }
1367      }
1368      mpz_clear(gcd);
1369    }
1370  }
1371  nlTest(x, r);
1372}
1373
1374/*2
1375* returns in result->z the lcm(a->z,b->n)
1376*/
1377number nlNormalizeHelper(number a, number b, const coeffs r)
1378{
1379  number result;
1380  nlTest(a, r);
1381  nlTest(b, r);
1382  if ((SR_HDL(b) & SR_INT)
1383  || (b->s==3))
1384  {
1385    // b is 1/(b->n) => b->n is 1 => result is a
1386    return nlCopy(a,r);
1387  }
1388  result=ALLOC_RNUMBER();
1389#if defined(LDEBUG)
1390  result->debug=123456;
1391#endif
1392  result->s=3;
1393  mpz_t gcd;
1394  mpz_init(gcd);
1395  mpz_init(result->z);
1396  if (SR_HDL(a) & SR_INT)
1397    mpz_gcd_ui(gcd,b->n,ABS(SR_TO_INT(a)));
1398  else
1399    mpz_gcd(gcd,a->z,b->n);
1400  if (mpz_cmp_si(gcd,1L)!=0)
1401  {
1402    mpz_t bt;
1403    mpz_init_set(bt,b->n);
1404    mpz_divexact(bt,bt,gcd);
1405    if (SR_HDL(a) & SR_INT)
1406      mpz_mul_si(result->z,bt,SR_TO_INT(a));
1407    else
1408      mpz_mul(result->z,bt,a->z);
1409    mpz_clear(bt);
1410  }
1411  else
1412    if (SR_HDL(a) & SR_INT)
1413      mpz_mul_si(result->z,b->n,SR_TO_INT(a));
1414    else
1415      mpz_mul(result->z,b->n,a->z);
1416  mpz_clear(gcd);
1417  result=nlShort3(result);
1418  nlTest(result, r);
1419  return result;
1420}
1421
1422// Map q \in QQ or ZZ \to Zp or an extension of it
1423// src = Q or Z, dst = Zp (or an extension of Zp)
1424number nlModP(number q, const coeffs /*Q*/, const coeffs Zp)
1425{
1426  const int p = n_GetChar(Zp);
1427  assume( p > 0 );
1428
1429  const long P = p;
1430  assume( P > 0 );
1431
1432  // embedded long within q => only long numerator has to be converted
1433  // to int (modulo char.)
1434  if (SR_HDL(q) & SR_INT)
1435  {
1436    long i = SR_TO_INT(q);
1437    return n_Init( i, Zp );
1438  }
1439
1440  const unsigned long PP = p;
1441
1442  // numerator modulo char. should fit into int
1443  number z = n_Init( static_cast<long>(mpz_fdiv_ui(q->z, PP)), Zp );
1444
1445  // denominator != 1?
1446  if (q->s!=3)
1447  {
1448    // denominator modulo char. should fit into int
1449    number n = n_Init( static_cast<long>(mpz_fdiv_ui(q->n, PP)), Zp );
1450
1451    number res = n_Div( z, n, Zp );
1452
1453    n_Delete(&z, Zp);
1454    n_Delete(&n, Zp);
1455
1456    return res;
1457  }
1458
1459  return z;
1460}
1461
1462#ifdef HAVE_RINGS
1463/*2
1464* convert number i (from Q) to GMP and warn if denom != 1
1465*/
1466void nlGMP(number &i, number n, const coeffs r)
1467{
1468  // Hier brauche ich einfach die GMP Zahl
1469  nlTest(i, r);
1470  nlNormalize(i, r);
1471  if (SR_HDL(i) & SR_INT)
1472  {
1473    mpz_set_si((mpz_ptr) n, SR_TO_INT(i));
1474    return;
1475  }
1476  if (i->s!=3)
1477  {
1478     WarnS("Omitted denominator during coefficient mapping !");
1479  }
1480  mpz_set((mpz_ptr) n, i->z);
1481}
1482#endif
1483
1484/*2
1485* acces to denominator, other 1 for integers
1486*/
1487number   nlGetDenom(number &n, const coeffs r)
1488{
1489  if (!(SR_HDL(n) & SR_INT))
1490  {
1491    if (n->s==0)
1492    {
1493      nlNormalize(n,r);
1494    }
1495    if (!(SR_HDL(n) & SR_INT))
1496    {
1497      if (n->s!=3)
1498      {
1499        number u=ALLOC_RNUMBER();
1500        u->s=3;
1501#if defined(LDEBUG)
1502        u->debug=123456;
1503#endif
1504        mpz_init_set(u->z,n->n);
1505        u=nlShort3_noinline(u);
1506        return u;
1507      }
1508    }
1509  }
1510  return INT_TO_SR(1);
1511}
1512
1513/*2
1514* acces to Nominator, nlCopy(n) for integers
1515*/
1516number   nlGetNumerator(number &n, const coeffs r)
1517{
1518  if (!(SR_HDL(n) & SR_INT))
1519  {
1520    if (n->s==0)
1521    {
1522      nlNormalize(n,r);
1523    }
1524    if (!(SR_HDL(n) & SR_INT))
1525    {
1526      number u=ALLOC_RNUMBER();
1527#if defined(LDEBUG)
1528      u->debug=123456;
1529#endif
1530      u->s=3;
1531      mpz_init_set(u->z,n->z);
1532      if (n->s!=3)
1533      {
1534        u=nlShort3_noinline(u);
1535      }
1536      return u;
1537    }
1538  }
1539  return n; // imm. int
1540}
1541
1542/***************************************************************
1543 *
1544 * routines which are needed by Inline(d) routines
1545 *
1546 *******************************************************************/
1547BOOLEAN _nlEqual_aNoImm_OR_bNoImm(number a, number b)
1548{
1549  assume(! (SR_HDL(a) & SR_HDL(b) & SR_INT));
1550//  long - short
1551  BOOLEAN bo;
1552  if (SR_HDL(b) & SR_INT)
1553  {
1554    if (a->s!=0) return FALSE;
1555    number n=b; b=a; a=n;
1556  }
1557//  short - long
1558  if (SR_HDL(a) & SR_INT)
1559  {
1560    if (b->s!=0)
1561      return FALSE;
1562    if ((((long)a) > 0L) && (mpz_isNeg(b->z)))
1563      return FALSE;
1564    if ((((long)a) < 0L) && (!mpz_isNeg(b->z)))
1565      return FALSE;
1566    mpz_t  bb;
1567    mpz_init_set(bb,b->n);
1568    mpz_mul_si(bb,bb,(long)SR_TO_INT(a));
1569    bo=(mpz_cmp(bb,b->z)==0);
1570    mpz_clear(bb);
1571    return bo;
1572  }
1573// long - long
1574  if (((a->s==1) && (b->s==3))
1575  ||  ((b->s==1) && (a->s==3)))
1576    return FALSE;
1577  if (mpz_isNeg(a->z)&&(!mpz_isNeg(b->z)))
1578    return FALSE;
1579  if (mpz_isNeg(b->z)&&(!mpz_isNeg(a->z)))
1580    return FALSE;
1581  mpz_t  aa;
1582  mpz_t  bb;
1583  mpz_init_set(aa,a->z);
1584  mpz_init_set(bb,b->z);
1585  if (a->s<2) mpz_mul(bb,bb,a->n);
1586  if (b->s<2) mpz_mul(aa,aa,b->n);
1587  bo=(mpz_cmp(aa,bb)==0);
1588  mpz_clear(aa);
1589  mpz_clear(bb);
1590  return bo;
1591}
1592
1593// copy not immediate number a
1594number _nlCopy_NoImm(number a)
1595{
1596  assume(!((SR_HDL(a) & SR_INT)||(a==NULL)));
1597  //nlTest(a, r);
1598  number b=ALLOC_RNUMBER();
1599#if defined(LDEBUG)
1600  b->debug=123456;
1601#endif
1602  switch (a->s)
1603  {
1604    case 0:
1605    case 1:
1606            mpz_init_set(b->n,a->n);
1607    case 3:
1608            mpz_init_set(b->z,a->z);
1609            break;
1610  }
1611  b->s = a->s;
1612  return b;
1613}
1614
1615void _nlDelete_NoImm(number *a)
1616{
1617  {
1618    switch ((*a)->s)
1619    {
1620      case 0:
1621      case 1:
1622        mpz_clear((*a)->n);
1623      case 3:
1624        mpz_clear((*a)->z);
1625#ifdef LDEBUG
1626        (*a)->s=2;
1627#endif
1628    }
1629    FREE_RNUMBER(*a); // omFreeBin((void *) *a, rnumber_bin);
1630  }
1631}
1632
1633number _nlNeg_NoImm(number a)
1634{
1635  {
1636    mpz_neg(a->z,a->z);
1637    if (a->s==3)
1638    {
1639      a=nlShort3(a);
1640    }
1641  }
1642  return a;
1643}
1644
1645// conditio to use nlNormalize_Gcd in intermediate computations:
1646#define GCD_NORM_COND(OLD,NEW) (mpz_size1(NEW->z)>mpz_size1(OLD->z))
1647
1648static void nlNormalize_Gcd(number &x)
1649{
1650  mpz_t gcd;
1651  mpz_init(gcd);
1652  mpz_gcd(gcd,x->z,x->n);
1653  x->s=1;
1654  if (mpz_cmp_si(gcd,1L)!=0)
1655  {
1656    mpz_divexact(x->z,x->z,gcd);
1657    mpz_divexact(x->n,x->n,gcd);
1658    if (mpz_cmp_si(x->n,1L)==0)
1659    {
1660      mpz_clear(x->n);
1661      x->s=3;
1662      x=nlShort3_noinline(x);
1663    }
1664  }
1665  mpz_clear(gcd);
1666}
1667
1668number _nlAdd_aNoImm_OR_bNoImm(number a, number b)
1669{
1670  number u=ALLOC_RNUMBER();
1671#if defined(LDEBUG)
1672  u->debug=123456;
1673#endif
1674  mpz_init(u->z);
1675  if (SR_HDL(b) & SR_INT)
1676  {
1677    number x=a;
1678    a=b;
1679    b=x;
1680  }
1681  if (SR_HDL(a) & SR_INT)
1682  {
1683    switch (b->s)
1684    {
1685      case 0:
1686      case 1:/* a:short, b:1 */
1687      {
1688        mpz_t x;
1689        mpz_init(x);
1690        mpz_mul_si(x,b->n,SR_TO_INT(a));
1691        mpz_add(u->z,b->z,x);
1692        mpz_clear(x);
1693        if (mpz_cmp_ui(u->z,0L)==0)
1694        {
1695          mpz_clear(u->z);
1696          FREE_RNUMBER(u);
1697          return INT_TO_SR(0);
1698        }
1699        if (mpz_cmp(u->z,b->n)==0)
1700        {
1701          mpz_clear(u->z);
1702          FREE_RNUMBER(u);
1703          return INT_TO_SR(1);
1704        }
1705        mpz_init_set(u->n,b->n);
1706        u->s = 0;
1707        if (GCD_NORM_COND(b,u)) { nlNormalize_Gcd(u); }
1708        break;
1709      }
1710      case 3:
1711      {
1712        if (((long)a)>0L)
1713          mpz_add_ui(u->z,b->z,SR_TO_INT(a));
1714        else
1715          mpz_sub_ui(u->z,b->z,-SR_TO_INT(a));
1716        u->s = 3;
1717        u=nlShort3(u);
1718        break;
1719      }
1720    }
1721  }
1722  else
1723  {
1724    switch (a->s)
1725    {
1726      case 0:
1727      case 1:
1728      {
1729        switch(b->s)
1730        {
1731          case 0:
1732          case 1:
1733          {
1734            mpz_t x;
1735            mpz_init(x);
1736
1737            mpz_mul(x,b->z,a->n);
1738            mpz_mul(u->z,a->z,b->n);
1739            mpz_add(u->z,u->z,x);
1740            mpz_clear(x);
1741
1742            if (mpz_cmp_ui(u->z,0L)==0)
1743            {
1744              mpz_clear(u->z);
1745              FREE_RNUMBER(u);
1746              return INT_TO_SR(0);
1747            }
1748            mpz_init(u->n);
1749            mpz_mul(u->n,a->n,b->n);
1750            if (mpz_cmp(u->z,u->n)==0)
1751            {
1752               mpz_clear(u->z);
1753               mpz_clear(u->n);
1754               FREE_RNUMBER(u);
1755               return INT_TO_SR(1);
1756            }
1757            u->s = 0;
1758            if (GCD_NORM_COND(b,u)) { nlNormalize_Gcd(u); }
1759            break;
1760          }
1761          case 3: /* a:1 b:3 */
1762          {
1763            mpz_mul(u->z,b->z,a->n);
1764            mpz_add(u->z,u->z,a->z);
1765            if (mpz_cmp_ui(u->z,0L)==0)
1766            {
1767              mpz_clear(u->z);
1768              FREE_RNUMBER(u);
1769              return INT_TO_SR(0);
1770            }
1771            if (mpz_cmp(u->z,a->n)==0)
1772            {
1773              mpz_clear(u->z);
1774              FREE_RNUMBER(u);
1775              return INT_TO_SR(1);
1776            }
1777            mpz_init_set(u->n,a->n);
1778            u->s = 0;
1779            if (GCD_NORM_COND(a,u)) { nlNormalize_Gcd(u); }
1780            break;
1781          }
1782        } /*switch (b->s) */
1783        break;
1784      }
1785      case 3:
1786      {
1787        switch(b->s)
1788        {
1789          case 0:
1790          case 1:/* a:3, b:1 */
1791          {
1792            mpz_mul(u->z,a->z,b->n);
1793            mpz_add(u->z,u->z,b->z);
1794            if (mpz_cmp_ui(u->z,0L)==0)
1795            {
1796              mpz_clear(u->z);
1797              FREE_RNUMBER(u);
1798              return INT_TO_SR(0);
1799            }
1800            if (mpz_cmp(u->z,b->n)==0)
1801            {
1802              mpz_clear(u->z);
1803              FREE_RNUMBER(u);
1804              return INT_TO_SR(1);
1805            }
1806            mpz_init_set(u->n,b->n);
1807            u->s = 0;
1808            if (GCD_NORM_COND(b,u)) { nlNormalize_Gcd(u); }
1809            break;
1810          }
1811          case 3:
1812          {
1813            mpz_add(u->z,a->z,b->z);
1814            u->s = 3;
1815            u=nlShort3(u);
1816            break;
1817          }
1818        }
1819        break;
1820      }
1821    }
1822  }
1823  return u;
1824}
1825
1826void _nlInpAdd_aNoImm_OR_bNoImm(number &a, number b)
1827{
1828  if (SR_HDL(b) & SR_INT)
1829  {
1830    switch (a->s)
1831    {
1832      case 0:
1833      case 1:/* b:short, a:1 */
1834      {
1835        mpz_t x;
1836        mpz_init(x);
1837        mpz_mul_si(x,a->n,SR_TO_INT(b));
1838        mpz_add(a->z,a->z,x);
1839        mpz_clear(x);
1840        nlNormalize_Gcd(a);
1841        break;
1842      }
1843      case 3:
1844      {
1845        if (((long)b)>0L)
1846          mpz_add_ui(a->z,a->z,SR_TO_INT(b));
1847        else
1848          mpz_sub_ui(a->z,a->z,-SR_TO_INT(b));
1849        a->s = 3;
1850        a=nlShort3_noinline(a);
1851        break;
1852      }
1853    }
1854    return;
1855  }
1856  else if (SR_HDL(a) & SR_INT)
1857  {
1858    number u=ALLOC_RNUMBER();
1859    #if defined(LDEBUG)
1860    u->debug=123456;
1861    #endif
1862    mpz_init(u->z);
1863    switch (b->s)
1864    {
1865      case 0:
1866      case 1:/* a:short, b:1 */
1867      {
1868        mpz_t x;
1869        mpz_init(x);
1870
1871        mpz_mul_si(x,b->n,SR_TO_INT(a));
1872        mpz_add(u->z,b->z,x);
1873        mpz_clear(x);
1874        // result cannot be 0, if coeffs are normalized
1875        mpz_init_set(u->n,b->n);
1876        u->s=0;
1877        if (GCD_NORM_COND(b,u)) { nlNormalize_Gcd(u); }
1878        else { u=nlShort1(u); }
1879        break;
1880      }
1881      case 3:
1882      {
1883        if (((long)a)>0L)
1884          mpz_add_ui(u->z,b->z,SR_TO_INT(a));
1885        else
1886          mpz_sub_ui(u->z,b->z,-SR_TO_INT(a));
1887        // result cannot be 0, if coeffs are normalized
1888        u->s = 3;
1889        u=nlShort3_noinline(u);
1890        break;
1891      }
1892    }
1893    a=u;
1894  }
1895  else
1896  {
1897    switch (a->s)
1898    {
1899      case 0:
1900      case 1:
1901      {
1902        switch(b->s)
1903        {
1904          case 0:
1905          case 1: /* a:1 b:1 */
1906          {
1907            mpz_t x;
1908            mpz_t y;
1909            mpz_init(x);
1910            mpz_init(y);
1911            mpz_mul(x,b->z,a->n);
1912            mpz_mul(y,a->z,b->n);
1913            mpz_add(a->z,x,y);
1914            mpz_clear(x);
1915            mpz_clear(y);
1916            mpz_mul(a->n,a->n,b->n);
1917            a->s=0;
1918            if (GCD_NORM_COND(b,a)) { nlNormalize_Gcd(a); }
1919            else { a=nlShort1(a);}
1920            break;
1921          }
1922          case 3: /* a:1 b:3 */
1923          {
1924            mpz_t x;
1925            mpz_init(x);
1926            mpz_mul(x,b->z,a->n);
1927            mpz_add(a->z,a->z,x);
1928            mpz_clear(x);
1929            a->s=0;
1930            if (GCD_NORM_COND(b,a)) { nlNormalize_Gcd(a); }
1931            else { a=nlShort1(a);}
1932            break;
1933          }
1934        } /*switch (b->s) */
1935        break;
1936      }
1937      case 3:
1938      {
1939        switch(b->s)
1940        {
1941          case 0:
1942          case 1:/* a:3, b:1 */
1943          {
1944            mpz_t x;
1945            mpz_init(x);
1946            mpz_mul(x,a->z,b->n);
1947            mpz_add(a->z,b->z,x);
1948            mpz_clear(x);
1949            mpz_init_set(a->n,b->n);
1950            a->s=0;
1951            if (GCD_NORM_COND(b,a)) { nlNormalize_Gcd(a); }
1952            else { a=nlShort1(a);}
1953            break;
1954          }
1955          case 3:
1956          {
1957            mpz_add(a->z,a->z,b->z);
1958            a->s = 3;
1959            a=nlShort3_noinline(a);
1960            break;
1961          }
1962        }
1963        break;
1964      }
1965    }
1966  }
1967}
1968
1969number _nlSub_aNoImm_OR_bNoImm(number a, number b)
1970{
1971  number u=ALLOC_RNUMBER();
1972#if defined(LDEBUG)
1973  u->debug=123456;
1974#endif
1975  mpz_init(u->z);
1976  if (SR_HDL(a) & SR_INT)
1977  {
1978    switch (b->s)
1979    {
1980      case 0:
1981      case 1:/* a:short, b:1 */
1982      {
1983        mpz_t x;
1984        mpz_init(x);
1985        mpz_mul_si(x,b->n,SR_TO_INT(a));
1986        mpz_sub(u->z,x,b->z);
1987        mpz_clear(x);
1988        if (mpz_cmp_ui(u->z,0L)==0)
1989        {
1990          mpz_clear(u->z);
1991          FREE_RNUMBER(u);
1992          return INT_TO_SR(0);
1993        }
1994        if (mpz_cmp(u->z,b->n)==0)
1995        {
1996          mpz_clear(u->z);
1997          FREE_RNUMBER(u);
1998          return INT_TO_SR(1);
1999        }
2000        mpz_init_set(u->n,b->n);
2001        u->s=0;
2002        if (GCD_NORM_COND(b,u)) { nlNormalize_Gcd(u); }
2003        break;
2004      }
2005      case 3:
2006      {
2007        if (((long)a)>0L)
2008        {
2009          mpz_sub_ui(u->z,b->z,SR_TO_INT(a));
2010          mpz_neg(u->z,u->z);
2011        }
2012        else
2013        {
2014          mpz_add_ui(u->z,b->z,-SR_TO_INT(a));
2015          mpz_neg(u->z,u->z);
2016        }
2017        u->s = 3;
2018        u=nlShort3(u);
2019        break;
2020      }
2021    }
2022  }
2023  else if (SR_HDL(b) & SR_INT)
2024  {
2025    switch (a->s)
2026    {
2027      case 0:
2028      case 1:/* b:short, a:1 */
2029      {
2030        mpz_t x;
2031        mpz_init(x);
2032        mpz_mul_si(x,a->n,SR_TO_INT(b));
2033        mpz_sub(u->z,a->z,x);
2034        mpz_clear(x);
2035        if (mpz_cmp_ui(u->z,0L)==0)
2036        {
2037          mpz_clear(u->z);
2038          FREE_RNUMBER(u);
2039          return INT_TO_SR(0);
2040        }
2041        if (mpz_cmp(u->z,a->n)==0)
2042        {
2043          mpz_clear(u->z);
2044          FREE_RNUMBER(u);
2045          return INT_TO_SR(1);
2046        }
2047        mpz_init_set(u->n,a->n);
2048        u->s=0;
2049        if (GCD_NORM_COND(a,u)) { nlNormalize_Gcd(u); }
2050        break;
2051      }
2052      case 3:
2053      {
2054        if (((long)b)>0L)
2055        {
2056          mpz_sub_ui(u->z,a->z,SR_TO_INT(b));
2057        }
2058        else
2059        {
2060          mpz_add_ui(u->z,a->z,-SR_TO_INT(b));
2061        }
2062        u->s = 3;
2063        u=nlShort3(u);
2064        break;
2065      }
2066    }
2067  }
2068  else
2069  {
2070    switch (a->s)
2071    {
2072      case 0:
2073      case 1:
2074      {
2075        switch(b->s)
2076        {
2077          case 0:
2078          case 1:
2079          {
2080            mpz_t x;
2081            mpz_t y;
2082            mpz_init(x);
2083            mpz_init(y);
2084            mpz_mul(x,b->z,a->n);
2085            mpz_mul(y,a->z,b->n);
2086            mpz_sub(u->z,y,x);
2087            mpz_clear(x);
2088            mpz_clear(y);
2089            if (mpz_cmp_ui(u->z,0L)==0)
2090            {
2091              mpz_clear(u->z);
2092              FREE_RNUMBER(u);
2093              return INT_TO_SR(0);
2094            }
2095            mpz_init(u->n);
2096            mpz_mul(u->n,a->n,b->n);
2097            if (mpz_cmp(u->z,u->n)==0)
2098            {
2099              mpz_clear(u->z);
2100              mpz_clear(u->n);
2101              FREE_RNUMBER(u);
2102              return INT_TO_SR(1);
2103            }
2104            u->s=0;
2105            if (GCD_NORM_COND(a,u)) { nlNormalize_Gcd(u); }
2106            break;
2107          }
2108          case 3: /* a:1, b:3 */
2109          {
2110            mpz_t x;
2111            mpz_init(x);
2112            mpz_mul(x,b->z,a->n);
2113            mpz_sub(u->z,a->z,x);
2114            mpz_clear(x);
2115            if (mpz_cmp_ui(u->z,0L)==0)
2116            {
2117              mpz_clear(u->z);
2118              FREE_RNUMBER(u);
2119              return INT_TO_SR(0);
2120            }
2121            if (mpz_cmp(u->z,a->n)==0)
2122            {
2123              mpz_clear(u->z);
2124              FREE_RNUMBER(u);
2125              return INT_TO_SR(1);
2126            }
2127            mpz_init_set(u->n,a->n);
2128            u->s=0;
2129            if (GCD_NORM_COND(a,u)) { nlNormalize_Gcd(u); }
2130            break;
2131          }
2132        }
2133        break;
2134      }
2135      case 3:
2136      {
2137        switch(b->s)
2138        {
2139          case 0:
2140          case 1: /* a:3, b:1 */
2141          {
2142            mpz_t x;
2143            mpz_init(x);
2144            mpz_mul(x,a->z,b->n);
2145            mpz_sub(u->z,x,b->z);
2146            mpz_clear(x);
2147            if (mpz_cmp_ui(u->z,0L)==0)
2148            {
2149              mpz_clear(u->z);
2150              FREE_RNUMBER(u);
2151              return INT_TO_SR(0);
2152            }
2153            if (mpz_cmp(u->z,b->n)==0)
2154            {
2155              mpz_clear(u->z);
2156              FREE_RNUMBER(u);
2157              return INT_TO_SR(1);
2158            }
2159            mpz_init_set(u->n,b->n);
2160            u->s=0;
2161            if (GCD_NORM_COND(b,u)) { nlNormalize_Gcd(u); }
2162            break;
2163          }
2164          case 3: /* a:3 , b:3 */
2165          {
2166            mpz_sub(u->z,a->z,b->z);
2167            u->s = 3;
2168            u=nlShort3(u);
2169            break;
2170          }
2171        }
2172        break;
2173      }
2174    }
2175  }
2176  return u;
2177}
2178
2179// a and b are intermediate, but a*b not
2180number _nlMult_aImm_bImm_rNoImm(number a, number b)
2181{
2182  number u=ALLOC_RNUMBER();
2183#if defined(LDEBUG)
2184  u->debug=123456;
2185#endif
2186  u->s=3;
2187  mpz_init_set_si(u->z,SR_TO_INT(a));
2188  mpz_mul_si(u->z,u->z,SR_TO_INT(b));
2189  return u;
2190}
2191
2192// a or b are not immediate
2193number _nlMult_aNoImm_OR_bNoImm(number a, number b)
2194{
2195  assume(! (SR_HDL(a) & SR_HDL(b) & SR_INT));
2196  number u=ALLOC_RNUMBER();
2197#if defined(LDEBUG)
2198  u->debug=123456;
2199#endif
2200  mpz_init(u->z);
2201  if (SR_HDL(b) & SR_INT)
2202  {
2203    number x=a;
2204    a=b;
2205    b=x;
2206  }
2207  if (SR_HDL(a) & SR_INT)
2208  {
2209    u->s=b->s;
2210    if (u->s==1) u->s=0;
2211    if (((long)a)>0L)
2212    {
2213      mpz_mul_ui(u->z,b->z,(unsigned long)SR_TO_INT(a));
2214    }
2215    else
2216    {
2217      if (a==INT_TO_SR(-1))
2218      {
2219        mpz_set(u->z,b->z);
2220        mpz_neg(u->z,u->z);
2221        u->s=b->s;
2222      }
2223      else
2224      {
2225        mpz_mul_ui(u->z,b->z,(unsigned long)-SR_TO_INT(a));
2226        mpz_neg(u->z,u->z);
2227      }
2228    }
2229    if (u->s<2)
2230    {
2231      if (mpz_cmp(u->z,b->n)==0)
2232      {
2233        mpz_clear(u->z);
2234        FREE_RNUMBER(u);
2235        return INT_TO_SR(1);
2236      }
2237      mpz_init_set(u->n,b->n);
2238      if (GCD_NORM_COND(b,u)) { nlNormalize_Gcd(u); }
2239    }
2240    else //u->s==3
2241    {
2242      u=nlShort3(u);
2243    }
2244  }
2245  else
2246  {
2247    mpz_mul(u->z,a->z,b->z);
2248    u->s = 0;
2249    if(a->s==3)
2250    {
2251      if(b->s==3)
2252      {
2253        u->s = 3;
2254      }
2255      else
2256      {
2257        if (mpz_cmp(u->z,b->n)==0)
2258        {
2259          mpz_clear(u->z);
2260          FREE_RNUMBER(u);
2261          return INT_TO_SR(1);
2262        }
2263        mpz_init_set(u->n,b->n);
2264        if (GCD_NORM_COND(b,u)) { nlNormalize_Gcd(u); }
2265      }
2266    }
2267    else
2268    {
2269      if(b->s==3)
2270      {
2271        if (mpz_cmp(u->z,a->n)==0)
2272        {
2273          mpz_clear(u->z);
2274          FREE_RNUMBER(u);
2275          return INT_TO_SR(1);
2276        }
2277        mpz_init_set(u->n,a->n);
2278        if (GCD_NORM_COND(a,u)) { nlNormalize_Gcd(u); }
2279      }
2280      else
2281      {
2282        mpz_init(u->n);
2283        mpz_mul(u->n,a->n,b->n);
2284        if (mpz_cmp(u->z,u->n)==0)
2285        {
2286          mpz_clear(u->z);
2287          mpz_clear(u->n);
2288          FREE_RNUMBER(u);
2289          return INT_TO_SR(1);
2290        }
2291        if (GCD_NORM_COND(a,u)) { nlNormalize_Gcd(u); }
2292      }
2293    }
2294  }
2295  return u;
2296}
2297
2298/*2
2299* copy a to b for mapping
2300*/
2301number nlCopyMap(number a, const coeffs /*src*/, const coeffs /*dst*/)
2302{
2303  if ((SR_HDL(a) & SR_INT)||(a==NULL))
2304  {
2305    return a;
2306  }
2307  return _nlCopy_NoImm(a);
2308}
2309
2310nMapFunc nlSetMap(const coeffs src, const coeffs /*dst*/)
2311{
2312  if (src->rep==n_rep_gap_rat)  /*Q, coeffs_BIGINT */
2313  {
2314    return ndCopyMap;
2315  }
2316  if ((src->rep==n_rep_int) && nCoeff_is_Zp(src))
2317  {
2318    return nlMapP;
2319  }
2320  if ((src->rep==n_rep_float) && nCoeff_is_R(src))
2321  {
2322    return nlMapR;
2323  }
2324  if ((src->rep==n_rep_gmp_float) && nCoeff_is_long_R(src))
2325  {
2326    return nlMapLongR; /* long R -> Q */
2327  }
2328#ifdef HAVE_RINGS
2329  if (src->rep==n_rep_gmp) // nCoeff_is_Ring_Z(src) || nCoeff_is_Ring_PtoM(src) || nCoeff_is_Ring_ModN(src))
2330  {
2331    return nlMapGMP;
2332  }
2333  if (src->rep==n_rep_gap_gmp)
2334  {
2335    return nlMapZ;
2336  }
2337  if ((src->rep==n_rep_int) && nCoeff_is_Ring_2toM(src))
2338  {
2339    return nlMapMachineInt;
2340  }
2341#endif
2342  return NULL;
2343}
2344/*2
2345* z := i
2346*/
2347number nlRInit (long i)
2348{
2349  number z=ALLOC_RNUMBER();
2350#if defined(LDEBUG)
2351  z->debug=123456;
2352#endif
2353  mpz_init_set_si(z->z,i);
2354  z->s = 3;
2355  return z;
2356}
2357
2358/*2
2359* z := i/j
2360*/
2361number nlInit2 (int i, int j, const coeffs r)
2362{
2363  number z=ALLOC_RNUMBER();
2364#if defined(LDEBUG)
2365  z->debug=123456;
2366#endif
2367  mpz_init_set_si(z->z,(long)i);
2368  mpz_init_set_si(z->n,(long)j);
2369  z->s = 0;
2370  nlNormalize(z,r);
2371  return z;
2372}
2373
2374number nlInit2gmp (mpz_t i, mpz_t j, const coeffs r)
2375{
2376  number z=ALLOC_RNUMBER();
2377#if defined(LDEBUG)
2378  z->debug=123456;
2379#endif
2380  mpz_init_set(z->z,i);
2381  mpz_init_set(z->n,j);
2382  z->s = 0;
2383  nlNormalize(z,r);
2384  return z;
2385}
2386
2387#else // DO_LINLINE
2388
2389// declare immedate routines
2390number nlRInit (long i);
2391BOOLEAN _nlEqual_aNoImm_OR_bNoImm(number a, number b);
2392number  _nlCopy_NoImm(number a);
2393number  _nlNeg_NoImm(number a);
2394number  _nlAdd_aNoImm_OR_bNoImm(number a, number b);
2395void    _nlInpAdd_aNoImm_OR_bNoImm(number &a, number b);
2396number  _nlSub_aNoImm_OR_bNoImm(number a, number b);
2397number  _nlMult_aNoImm_OR_bNoImm(number a, number b);
2398number  _nlMult_aImm_bImm_rNoImm(number a, number b);
2399
2400#endif
2401
2402/***************************************************************
2403 *
2404 * Routines which might be inlined by p_Numbers.h
2405 *
2406 *******************************************************************/
2407#if defined(DO_LINLINE) || !defined(P_NUMBERS_H)
2408
2409// routines which are always inlined/static
2410
2411/*2
2412* a = b ?
2413*/
2414LINLINE BOOLEAN nlEqual (number a, number b, const coeffs r)
2415{
2416  nlTest(a, r);
2417  nlTest(b, r);
2418// short - short
2419  if (SR_HDL(a) & SR_HDL(b) & SR_INT) return a==b;
2420  return _nlEqual_aNoImm_OR_bNoImm(a, b);
2421}
2422
2423LINLINE number nlInit (long i, const coeffs r)
2424{
2425  number n;
2426  #if MAX_NUM_SIZE == 60
2427  if (((i << 3) >> 3) == i) n=INT_TO_SR(i);
2428  else                      n=nlRInit(i);
2429  #else
2430  LONG ii=(LONG)i;
2431  if ( ((((long)ii)==i) && ((ii << 3) >> 3) == ii )) n=INT_TO_SR(ii);
2432  else                                             n=nlRInit(i);
2433  #endif
2434  nlTest(n, r);
2435  return n;
2436}
2437
2438/*2
2439* a == 1 ?
2440*/
2441LINLINE BOOLEAN nlIsOne (number a, const coeffs r)
2442{
2443#ifdef LDEBUG
2444  if (a==NULL) return FALSE;
2445  nlTest(a, r);
2446#endif
2447  return (a==INT_TO_SR(1));
2448}
2449
2450LINLINE BOOLEAN nlIsZero (number a, const coeffs)
2451{
2452  #if 0
2453  if (a==INT_TO_SR(0)) return TRUE;
2454  if ((SR_HDL(a) & SR_INT)||(a==NULL)) return FALSE;
2455  if (mpz_cmp_si(a->z,0L)==0)
2456  {
2457    printf("gmp-0 in nlIsZero\n");
2458    dErrorBreak();
2459    return TRUE;
2460  }
2461  return FALSE;
2462  #else
2463  return (a==INT_TO_SR(0));
2464  #endif
2465}
2466
2467/*2
2468* copy a to b
2469*/
2470LINLINE number nlCopy(number a, const coeffs)
2471{
2472  if ((SR_HDL(a) & SR_INT)||(a==NULL))
2473  {
2474    return a;
2475  }
2476  return _nlCopy_NoImm(a);
2477}
2478
2479
2480/*2
2481* delete a
2482*/
2483LINLINE void nlDelete (number * a, const coeffs r)
2484{
2485  if (*a!=NULL)
2486  {
2487    nlTest(*a, r);
2488    if ((SR_HDL(*a) & SR_INT)==0)
2489    {
2490      _nlDelete_NoImm(a);
2491    }
2492    *a=NULL;
2493  }
2494}
2495
2496/*2
2497* za:= - za
2498*/
2499LINLINE number nlNeg (number a, const coeffs R)
2500{
2501  nlTest(a, R);
2502  if(SR_HDL(a) &SR_INT)
2503  {
2504    LONG r=SR_TO_INT(a);
2505    if (r==(-(POW_2_28))) a=nlRInit(POW_2_28);
2506    else               a=INT_TO_SR(-r);
2507    return a;
2508  }
2509  a = _nlNeg_NoImm(a);
2510  nlTest(a, R);
2511  return a;
2512
2513}
2514
2515/*2
2516* u:= a + b
2517*/
2518LINLINE number nlAdd (number a, number b, const coeffs R)
2519{
2520  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2521  {
2522    LONG r=SR_HDL(a)+SR_HDL(b)-1L;
2523    if ( ((r << 1) >> 1) == r )
2524      return (number)(long)r;
2525    else
2526      return nlRInit(SR_TO_INT(r));
2527  }
2528  number u =  _nlAdd_aNoImm_OR_bNoImm(a, b);
2529  nlTest(u, R);
2530  return u;
2531}
2532
2533number nlShort1(number a);
2534number nlShort3_noinline(number x);
2535
2536LINLINE void nlInpAdd(number &a, number b, const coeffs r)
2537{
2538  // a=a+b
2539  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2540  {
2541    LONG r=SR_HDL(a)+SR_HDL(b)-1L;
2542    if ( ((r << 1) >> 1) == r )
2543      a=(number)(long)r;
2544    else
2545      a=nlRInit(SR_TO_INT(r));
2546  }
2547  else
2548  {
2549    _nlInpAdd_aNoImm_OR_bNoImm(a,b);
2550    nlTest(a,r);
2551  }
2552}
2553
2554LINLINE number nlMult (number a, number b, const coeffs R)
2555{
2556  nlTest(a, R);
2557  nlTest(b, R);
2558  if (a==INT_TO_SR(0)) return INT_TO_SR(0);
2559  if (b==INT_TO_SR(0)) return INT_TO_SR(0);
2560  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2561  {
2562    LONG r=(LONG)((unsigned LONG)(SR_HDL(a)-1L))*((unsigned LONG)(SR_HDL(b)>>1));
2563    if ((r/(SR_HDL(b)>>1))==(SR_HDL(a)-1L))
2564    {
2565      number u=((number) ((r>>1)+SR_INT));
2566      if (((((LONG)SR_HDL(u))<<1)>>1)==SR_HDL(u)) return (u);
2567      return nlRInit(SR_HDL(u)>>2);
2568    }
2569    number u = _nlMult_aImm_bImm_rNoImm(a, b);
2570    nlTest(u, R);
2571    return u;
2572
2573  }
2574  number u = _nlMult_aNoImm_OR_bNoImm(a, b);
2575  nlTest(u, R);
2576  return u;
2577
2578}
2579
2580
2581/*2
2582* u:= a - b
2583*/
2584LINLINE number nlSub (number a, number b, const coeffs r)
2585{
2586  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2587  {
2588    LONG r=SR_HDL(a)-SR_HDL(b)+1;
2589    if ( ((r << 1) >> 1) == r )
2590    {
2591      return (number)(long)r;
2592    }
2593    else
2594      return nlRInit(SR_TO_INT(r));
2595  }
2596  number u = _nlSub_aNoImm_OR_bNoImm(a, b);
2597  nlTest(u, r);
2598  return u;
2599
2600}
2601
2602LINLINE void nlInpMult(number &a, number b, const coeffs r)
2603{
2604  number aa=a;
2605  if (((SR_HDL(b)|SR_HDL(aa))&SR_INT))
2606  {
2607    number n=nlMult(aa,b,r);
2608    nlDelete(&a,r);
2609    a=n;
2610  }
2611  else
2612  {
2613    mpz_mul(aa->z,a->z,b->z);
2614    if (aa->s==3)
2615    {
2616      if(b->s!=3)
2617      {
2618        mpz_init_set(a->n,b->n);
2619        a->s=0;
2620      }
2621    }
2622    else
2623    {
2624      if(b->s!=3)
2625      {
2626        mpz_mul(a->n,a->n,b->n);
2627      }
2628      a->s=0;
2629    }
2630  }
2631}
2632#endif // DO_LINLINE
2633
2634#ifndef P_NUMBERS_H
2635
2636static void nlMPZ(mpz_t m, number &n, const coeffs r)
2637{
2638  nlTest(n, r);
2639  nlNormalize(n, r);
2640  if (SR_HDL(n) & SR_INT) mpz_init_set_si(m, SR_TO_INT(n));     /* n fits in an int */
2641  else             mpz_init_set(m, (mpz_ptr)n->z);
2642}
2643
2644
2645static number nlInitMPZ(mpz_t m, const coeffs)
2646{
2647  number z = ALLOC_RNUMBER();
2648  z->s = 3;
2649  #ifdef LDEBUG
2650  z->debug=123456;
2651  #endif
2652  mpz_init_set(z->z, m);
2653  z=nlShort3(z);
2654  return z;
2655}
2656
2657number  nlXExtGcd (number a, number b, number *s, number *t, number *u, number *v, const coeffs r)
2658{
2659  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2660  {
2661    int uu, vv, x, y;
2662    int g = int_extgcd(SR_TO_INT(a), SR_TO_INT(b), &uu, &vv, &x, &y);
2663    *s = INT_TO_SR(uu);
2664    *t = INT_TO_SR(vv);
2665    *u = INT_TO_SR(x);
2666    *v = INT_TO_SR(y);
2667    return INT_TO_SR(g);
2668  }
2669  else
2670  {
2671    mpz_t aa, bb;
2672    if (SR_HDL(a) & SR_INT)
2673    {
2674      mpz_init_set_si(aa, SR_TO_INT(a));
2675    }
2676    else
2677    {
2678      mpz_init_set(aa, a->z);
2679    }
2680    if (SR_HDL(b) & SR_INT)
2681    {
2682      mpz_init_set_si(bb, SR_TO_INT(b));
2683    }
2684    else
2685    {
2686      mpz_init_set(bb, b->z);
2687    }
2688    mpz_t erg; mpz_t bs; mpz_t bt;
2689    mpz_init(erg);
2690    mpz_init(bs);
2691    mpz_init(bt);
2692
2693    mpz_gcdext(erg, bs, bt, aa, bb);
2694
2695    mpz_div(aa, aa, erg);
2696    *u=nlInitMPZ(bb,r);
2697    *u=nlNeg(*u,r);
2698    *v=nlInitMPZ(aa,r);
2699
2700    mpz_clear(aa);
2701    mpz_clear(bb);
2702
2703    *s = nlInitMPZ(bs,r);
2704    *t = nlInitMPZ(bt,r);
2705    return nlInitMPZ(erg,r);
2706  }
2707}
2708
2709number nlQuotRem (number a, number b, number * r, const coeffs R)
2710{
2711  assume(SR_TO_INT(b)!=0);
2712  if (SR_HDL(a) & SR_HDL(b) & SR_INT)
2713  {
2714    if (r!=NULL)
2715      *r = INT_TO_SR(SR_TO_INT(a) % SR_TO_INT(b));
2716    return INT_TO_SR(SR_TO_INT(a)/SR_TO_INT(b));
2717  }
2718  else if (SR_HDL(a) & SR_INT)
2719  {
2720    // -2^xx / 2^xx
2721    if ((a==INT_TO_SR(-(POW_2_28)))&&(b==INT_TO_SR(-1L)))
2722    {
2723      if (r!=NULL) *r=INT_TO_SR(0);
2724      return nlRInit(POW_2_28);
2725    }
2726    //a is small, b is not, so q=0, r=a
2727    if (r!=NULL)
2728      *r = a;
2729    return INT_TO_SR(0);
2730  }
2731  else if (SR_HDL(b) & SR_INT)
2732  {
2733    unsigned long rr;
2734    mpz_t qq;
2735    mpz_init(qq);
2736    mpz_t rrr;
2737    mpz_init(rrr);
2738    rr = mpz_divmod_ui(qq, rrr, a->z, (unsigned long)ABS(SR_TO_INT(b)));
2739    mpz_clear(rrr);
2740
2741    if (r!=NULL)
2742      *r = INT_TO_SR(rr);
2743    if (SR_TO_INT(b)<0)
2744    {
2745      mpz_mul_si(qq, qq, -1);
2746    }
2747    return nlInitMPZ(qq,R);
2748  }
2749  mpz_t qq,rr;
2750  mpz_init(qq);
2751  mpz_init(rr);
2752  mpz_divmod(qq, rr, a->z, b->z);
2753  if (r!=NULL)
2754    *r = nlInitMPZ(rr,R);
2755  else
2756  {
2757    mpz_clear(rr);
2758  }
2759  return nlInitMPZ(qq,R);
2760}
2761
2762void nlInpGcd(number &a, number b, const coeffs r)
2763{
2764  if ((SR_HDL(b)|SR_HDL(a))&SR_INT)
2765  {
2766    number n=nlGcd(a,b,r);
2767    nlDelete(&a,r);
2768    a=n;
2769  }
2770  else
2771  {
2772    mpz_gcd(a->z,a->z,b->z);
2773    a=nlShort3_noinline(a);
2774  }
2775}
2776
2777void nlInpIntDiv(number &a, number b, const coeffs r)
2778{
2779  if ((SR_HDL(b)|SR_HDL(a))&SR_INT)
2780  {
2781    number n=nlIntDiv(a,b, r);
2782    nlDelete(&a,r);
2783    a=n;
2784  }
2785  else
2786  {
2787    number rr=nlIntMod(a,b,r);
2788    if (SR_HDL(rr) &  SR_INT) mpz_sub_ui(a->z,a->z,SR_TO_INT(rr));
2789    else                      mpz_sub(a->z,a->z,rr->z);
2790    mpz_divexact(a->z,a->z,b->z);
2791    a=nlShort3_noinline(a);
2792  }
2793}
2794
2795number nlFarey(number nN, number nP, const coeffs r)
2796{
2797  mpz_t tmp; mpz_init(tmp);
2798  mpz_t A,B,C,D,E,N,P;
2799  if (SR_HDL(nN) & SR_INT) mpz_init_set_si(N,SR_TO_INT(nN));
2800  else                     mpz_init_set(N,nN->z);
2801  if (SR_HDL(nP) & SR_INT) mpz_init_set_si(P,SR_TO_INT(nP));
2802  else                     mpz_init_set(P,nP->z);
2803  assume(!mpz_isNeg(P));
2804  if (mpz_isNeg(N))  mpz_add(N,N,P);
2805  mpz_init_set_si(A,0L);
2806  mpz_init_set_ui(B,(unsigned long)1);
2807  mpz_init_set_si(C,0L);
2808  mpz_init(D);
2809  mpz_init_set(E,P);
2810  number z=INT_TO_SR(0);
2811  while(mpz_cmp_si(N,0L)!=0)
2812  {
2813    mpz_mul(tmp,N,N);
2814    mpz_add(tmp,tmp,tmp);
2815    if (mpz_cmp(tmp,P)<0)
2816    {
2817       if (mpz_isNeg(B))
2818       {
2819         mpz_neg(B,B);
2820         mpz_neg(N,N);
2821       }
2822       // check for gcd(N,B)==1
2823       mpz_gcd(tmp,N,B);
2824       if (mpz_cmp_ui(tmp,1)==0)
2825       {
2826         // return N/B
2827         z=ALLOC_RNUMBER();
2828         #ifdef LDEBUG
2829         z->debug=123456;
2830         #endif
2831         mpz_init_set(z->z,N);
2832         mpz_init_set(z->n,B);
2833         z->s = 0;
2834         nlNormalize(z,r);
2835       }
2836       else
2837       {
2838         // return nN (the input) instead of "fail"
2839         z=nlCopy(nN,r);
2840       }
2841       break;
2842    }
2843    //mpz_mod(D,E,N);
2844    //mpz_div(tmp,E,N);
2845    mpz_divmod(tmp,D,E,N);
2846    mpz_mul(tmp,tmp,B);
2847    mpz_sub(C,A,tmp);
2848    mpz_set(E,N);
2849    mpz_set(N,D);
2850    mpz_set(A,B);
2851    mpz_set(B,C);
2852  }
2853  mpz_clear(tmp);
2854  mpz_clear(A);
2855  mpz_clear(B);
2856  mpz_clear(C);
2857  mpz_clear(D);
2858  mpz_clear(E);
2859  mpz_clear(N);
2860  mpz_clear(P);
2861  return z;
2862}
2863
2864number nlExtGcd(number a, number b, number *s, number *t, const coeffs)
2865{
2866  mpz_ptr aa,bb;
2867  *s=ALLOC_RNUMBER();
2868  mpz_init((*s)->z); (*s)->s=3;
2869  (*t)=ALLOC_RNUMBER();
2870  mpz_init((*t)->z); (*t)->s=3;
2871  number g=ALLOC_RNUMBER();
2872  mpz_init(g->z); g->s=3;
2873  #ifdef LDEBUG
2874  g->debug=123456;
2875  (*s)->debug=123456;
2876  (*t)->debug=123456;
2877  #endif
2878  if (SR_HDL(a) & SR_INT)
2879  {
2880    aa=(mpz_ptr)omAlloc(sizeof(mpz_t));
2881    mpz_init_set_si(aa,SR_TO_INT(a));
2882  }
2883  else
2884  {
2885    aa=a->z;
2886  }
2887  if (SR_HDL(b) & SR_INT)
2888  {
2889    bb=(mpz_ptr)omAlloc(sizeof(mpz_t));
2890    mpz_init_set_si(bb,SR_TO_INT(b));
2891  }
2892  else
2893  {
2894    bb=b->z;
2895  }
2896  mpz_gcdext(g->z,(*s)->z,(*t)->z,aa,bb);
2897  g=nlShort3(g);
2898  (*s)=nlShort3((*s));
2899  (*t)=nlShort3((*t));
2900  if (SR_HDL(a) & SR_INT)
2901  {
2902    mpz_clear(aa);
2903    omFreeSize(aa, sizeof(mpz_t));
2904  }
2905  if (SR_HDL(b) & SR_INT)
2906  {
2907    mpz_clear(bb);
2908    omFreeSize(bb, sizeof(mpz_t));
2909  }
2910  return g;
2911}
2912
2913void    nlCoeffWrite  (const coeffs r, BOOLEAN /*details*/)
2914{
2915  if (r->is_field)
2916  PrintS("//   characteristic : 0\n");
2917  else
2918  PrintS("//   coeff. ring is : Integers\n");
2919}
2920
2921int n_SwitchChinRem=0;
2922number   nlChineseRemainderSym(number *x, number *q,int rl, BOOLEAN sym, CFArray &inv_cache,const coeffs CF)
2923// elemenst in the array are x[0..(rl-1)], q[0..(rl-1)]
2924{
2925  setCharacteristic( 0 ); // only in char 0
2926  Off(SW_RATIONAL);
2927  CFArray X(rl), Q(rl);
2928  int i;
2929  for(i=rl-1;i>=0;i--)
2930  {
2931    X[i]=CF->convSingNFactoryN(x[i],FALSE,CF); // may be larger MAX_INT
2932    Q[i]=CF->convSingNFactoryN(q[i],FALSE,CF); // may be larger MAX_INT
2933  }
2934  CanonicalForm xnew,qnew;
2935  if (n_SwitchChinRem)
2936    chineseRemainder(X,Q,xnew,qnew);
2937  else
2938    chineseRemainderCached(X,Q,xnew,qnew,inv_cache);
2939  number n=CF->convFactoryNSingN(xnew,CF);
2940  if (sym)
2941  {
2942    number p=CF->convFactoryNSingN(qnew,CF);
2943    number p2;
2944    if (getCoeffType(CF) == n_Q) p2=nlIntDiv(p,nlInit(2, CF),CF);
2945    else                         p2=CF->cfDiv(p,CF->cfInit(2, CF),CF);
2946    if (CF->cfGreater(n,p2,CF))
2947    {
2948       number n2=CF->cfSub(n,p,CF);
2949       CF->cfDelete(&n,CF);
2950       n=n2;
2951    }
2952    CF->cfDelete(&p2,CF);
2953    CF->cfDelete(&p,CF);
2954  }
2955  CF->cfNormalize(n,CF);
2956  return n;
2957}
2958#if 0
2959number nlChineseRemainder(number *x, number *q,int rl, const coeffs C)
2960{
2961  CFArray inv(rl);
2962  return nlChineseRemainderSym(x,q,rl,TRUE,inv,C);
2963}
2964#endif
2965
2966static void nlClearContent(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs cf)
2967{
2968  assume(cf != NULL);
2969
2970  numberCollectionEnumerator.Reset();
2971
2972  if( !numberCollectionEnumerator.MoveNext() ) // empty zero polynomial?
2973  {
2974    c = nlInit(1, cf);
2975    return;
2976  }
2977
2978  // all coeffs are given by integers!!!
2979
2980  // part 1, find a small candidate for gcd
2981  number cand1,cand;
2982  int s1,s;
2983  s=2147483647; // max. int
2984
2985  const BOOLEAN lc_is_pos=nlGreaterZero(numberCollectionEnumerator.Current(),cf);
2986
2987  int normalcount = 0;
2988  do
2989  {
2990    number& n = numberCollectionEnumerator.Current();
2991    nlNormalize(n, cf); ++normalcount;
2992    cand1 = n;
2993
2994    if (SR_HDL(cand1)&SR_INT) { cand=cand1; break; }
2995    assume(cand1->s==3); // all coeffs should be integers // ==0?!! after printing
2996    s1=mpz_size1(cand1->z);
2997    if (s>s1)
2998    {
2999      cand=cand1;
3000      s=s1;
3001    }
3002  } while (numberCollectionEnumerator.MoveNext() );
3003
3004//  assume( nlGreaterZero(cand,cf) ); // cand may be a negative integer!
3005
3006  cand=nlCopy(cand,cf);
3007  // part 2: compute gcd(cand,all coeffs)
3008
3009  numberCollectionEnumerator.Reset();
3010
3011  while (numberCollectionEnumerator.MoveNext() )
3012  {
3013    number& n = numberCollectionEnumerator.Current();
3014
3015    if( (--normalcount) <= 0)
3016      nlNormalize(n, cf);
3017
3018    nlInpGcd(cand, n, cf);
3019    assume( nlGreaterZero(cand,cf) );
3020
3021    if(nlIsOne(cand,cf))
3022    {
3023      c = cand;
3024
3025      if(!lc_is_pos)
3026      {
3027        // make the leading coeff positive
3028        c = nlNeg(c, cf);
3029        numberCollectionEnumerator.Reset();
3030
3031        while (numberCollectionEnumerator.MoveNext() )
3032        {
3033          number& nn = numberCollectionEnumerator.Current();
3034          nn = nlNeg(nn, cf);
3035        }
3036      }
3037      return;
3038    }
3039  }
3040
3041  // part3: all coeffs = all coeffs / cand
3042  if (!lc_is_pos)
3043    cand = nlNeg(cand,cf);
3044
3045  c = cand;
3046  numberCollectionEnumerator.Reset();
3047
3048  while (numberCollectionEnumerator.MoveNext() )
3049  {
3050    number& n = numberCollectionEnumerator.Current();
3051    number t=nlIntDiv(n, cand, cf); // simple integer exact division, no ratios to remain
3052    nlDelete(&n, cf);
3053    n = t;
3054  }
3055}
3056
3057static void nlClearDenominators(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs cf)
3058{
3059  assume(cf != NULL);
3060
3061  numberCollectionEnumerator.Reset();
3062
3063  if( !numberCollectionEnumerator.MoveNext() ) // empty zero polynomial?
3064  {
3065    c = nlInit(1, cf);
3066//    assume( n_GreaterZero(c, cf) );
3067    return;
3068  }
3069
3070  // all coeffs are given by integers after returning from this routine
3071
3072  // part 1, collect product of all denominators /gcds
3073  number cand;
3074  cand=ALLOC_RNUMBER();
3075#if defined(LDEBUG)
3076  cand->debug=123456;
3077#endif
3078  cand->s=3;
3079
3080  int s=0;
3081
3082  const BOOLEAN lc_is_pos=nlGreaterZero(numberCollectionEnumerator.Current(),cf);
3083
3084  do
3085  {
3086    number& cand1 = numberCollectionEnumerator.Current();
3087
3088    if (!(SR_HDL(cand1)&SR_INT))
3089    {
3090      nlNormalize(cand1, cf);
3091      if ((!(SR_HDL(cand1)&SR_INT)) // not a short int
3092      && (cand1->s==1))             // and is a normalised rational
3093      {
3094        if (s==0) // first denom, we meet
3095        {
3096          mpz_init_set(cand->z, cand1->n); // cand->z = cand1->n
3097          s=1;
3098        }
3099        else // we have already something
3100        {
3101          mpz_lcm(cand->z, cand->z, cand1->n);
3102        }
3103      }
3104    }
3105  }
3106  while (numberCollectionEnumerator.MoveNext() );
3107
3108
3109  if (s==0) // nothing to do, all coeffs are already integers
3110  {
3111//    mpz_clear(tmp);
3112    FREE_RNUMBER(cand);
3113    if (lc_is_pos)
3114      c=nlInit(1,cf);
3115    else
3116    {
3117      // make the leading coeff positive
3118      c=nlInit(-1,cf);
3119
3120      // TODO: incorporate the following into the loop below?
3121      numberCollectionEnumerator.Reset();
3122      while (numberCollectionEnumerator.MoveNext() )
3123      {
3124        number& n = numberCollectionEnumerator.Current();
3125        n = nlNeg(n, cf);
3126      }
3127    }
3128//    assume( n_GreaterZero(c, cf) );
3129    return;
3130  }
3131
3132  cand = nlShort3(cand);
3133
3134  // part2: all coeffs = all coeffs * cand
3135  // make the lead coeff positive
3136  numberCollectionEnumerator.Reset();
3137
3138  if (!lc_is_pos)
3139    cand = nlNeg(cand, cf);
3140
3141  c = cand;
3142
3143  while (numberCollectionEnumerator.MoveNext() )
3144  {
3145    number &n = numberCollectionEnumerator.Current();
3146    nlInpMult(n, cand, cf);
3147  }
3148
3149}
3150
3151char * nlCoeffName(const coeffs r)
3152{
3153  if (r->cfDiv==nlDiv) return (char*)"QQ";
3154  else                 return (char*)"ZZ";
3155}
3156
3157static char* nlCoeffString(const coeffs r)
3158{
3159  //return omStrDup(nlCoeffName(r));
3160  if (r->cfDiv==nlDiv) return omStrDup("QQ");
3161  else                 return omStrDup("ZZ");
3162}
3163
3164static void nlWriteFd(number n,FILE* f, const coeffs)
3165{
3166  if(SR_HDL(n) & SR_INT)
3167  {
3168    #if SIZEOF_LONG == 4
3169    fprintf(f,"4 %ld ",SR_TO_INT(n));
3170    #else
3171    long nn=SR_TO_INT(n);
3172    if ((nn<POW_2_28_32)&&(nn>= -POW_2_28_32))
3173    {
3174      int nnn=(int)nn;
3175      fprintf(f,"4 %d ",nnn);
3176    }
3177    else
3178    {
3179      mpz_t tmp;
3180      mpz_init_set_si(tmp,nn);
3181      fputs("8 ",f);
3182      mpz_out_str (f,SSI_BASE, tmp);
3183      fputc(' ',f);
3184      mpz_clear(tmp);
3185    }
3186    #endif
3187  }
3188  else if (n->s<2)
3189  {
3190    //gmp_fprintf(f,"%d %Zd %Zd ",n->s,n->z,n->n);
3191    fprintf(f,"%d ",n->s+5);
3192    mpz_out_str (f,SSI_BASE, n->z);
3193    fputc(' ',f);
3194    mpz_out_str (f,SSI_BASE, n->n);
3195    fputc(' ',f);
3196
3197    //if (d->f_debug!=NULL) gmp_fprintf(d->f_debug,"number: s=%d gmp/gmp \"%Zd %Zd\" ",n->s,n->z,n->n);
3198  }
3199  else /*n->s==3*/
3200  {
3201    //gmp_fprintf(d->f_write,"3 %Zd ",n->z);
3202    fputs("8 ",f);
3203    mpz_out_str (f,SSI_BASE, n->z);
3204    fputc(' ',f);
3205
3206    //if (d->f_debug!=NULL) gmp_fprintf(d->f_debug,"number: gmp \"%Zd\" ",n->z);
3207  }
3208}
3209
3210static number nlReadFd(s_buff f, const coeffs)
3211{
3212  int sub_type=-1;
3213  sub_type=s_readint(f);
3214  switch(sub_type)
3215  {
3216     case 0:
3217     case 1:
3218       {// read mpz_t, mpz_t
3219         number n=nlRInit(0);
3220         mpz_init(n->n);
3221         s_readmpz(f,n->z);
3222         s_readmpz(f,n->n);
3223         n->s=sub_type;
3224         return n;
3225       }
3226
3227     case 3:
3228       {// read mpz_t
3229         number n=nlRInit(0);
3230         s_readmpz(f,n->z);
3231         n->s=3; /*sub_type*/
3232         #if SIZEOF_LONG == 8
3233         n=nlShort3(n);
3234         #endif
3235         return n;
3236       }
3237     case 4:
3238       {
3239         LONG dd=s_readlong(f);
3240         //#if SIZEOF_LONG == 8
3241         return INT_TO_SR(dd);
3242         //#else
3243         //return nlInit(dd,NULL);
3244         //#endif
3245       }
3246     case 5:
3247     case 6:
3248       {// read raw mpz_t, mpz_t
3249         number n=nlRInit(0);
3250         mpz_init(n->n);
3251         s_readmpz_base (f,n->z, SSI_BASE);
3252         s_readmpz_base (f,n->n, SSI_BASE);
3253         n->s=sub_type-5;
3254         return n;
3255       }
3256     case 8:
3257       {// read raw mpz_t
3258         number n=nlRInit(0);
3259         s_readmpz_base (f,n->z, SSI_BASE);
3260         n->s=sub_type=3; /*subtype-5*/
3261         #if SIZEOF_LONG == 8
3262         n=nlShort3(n);
3263         #endif
3264         return n;
3265       }
3266
3267     default: Werror("error in reading number: invalid subtype %d",sub_type);
3268              return NULL;
3269  }
3270  return NULL;
3271}
3272BOOLEAN nlCoeffIsEqual(const coeffs r, n_coeffType n, void *p)
3273{
3274  /* test, if r is an instance of nInitCoeffs(n,parameter) */
3275  /* if parameter is not needed */
3276  if (n==r->type)
3277  {
3278    if ((p==NULL)&&(r->cfDiv==nlDiv)) return TRUE;
3279    if ((p!=NULL)&&(r->cfDiv!=nlDiv)) return TRUE;
3280  }
3281  return FALSE;
3282}
3283
3284static number nlLcm(number a,number b,const coeffs r)
3285{
3286  number g=nlGcd(a,b,r);
3287  number n1=nlMult(a,b,r);
3288  number n2=nlIntDiv(n1,g,r);
3289  nlDelete(&g,r);
3290  nlDelete(&n1,r);
3291  return n2;
3292}
3293
3294static number nlRandom(siRandProc p, number v2, number, const coeffs cf)
3295{
3296  number a=nlInit(p(),cf);
3297  if (v2!=NULL)
3298  {
3299    number b=nlInit(p(),cf);
3300    number c=nlDiv(a,b,cf);
3301    nlDelete(&b,cf);
3302    nlDelete(&a,cf);
3303    a=c;
3304  }
3305  return a;
3306}
3307
3308BOOLEAN nlInitChar(coeffs r, void*p)
3309{
3310  r->is_domain=TRUE;
3311  r->rep=n_rep_gap_rat;
3312
3313  //const int ch = (int)(long)(p);
3314
3315  r->nCoeffIsEqual=nlCoeffIsEqual;
3316  //r->cfKillChar = ndKillChar; /* dummy */
3317  r->cfCoeffString=nlCoeffString;
3318  r->cfCoeffName=nlCoeffName;
3319
3320  r->cfInitMPZ = nlInitMPZ;
3321  r->cfMPZ  = nlMPZ;
3322
3323  r->cfMult  = nlMult;
3324  r->cfSub   = nlSub;
3325  r->cfAdd   = nlAdd;
3326  if (p==NULL) /* Q */
3327  {
3328    r->is_field=TRUE;
3329    r->cfDiv   = nlDiv;
3330    //r->cfGcd  = ndGcd_dummy;
3331    r->cfSubringGcd  = nlGcd;
3332  }
3333  else /* Z: coeffs_BIGINT */
3334  {
3335    r->is_field=FALSE;
3336    r->cfDiv   = nlIntDiv;
3337    r->cfIntMod= nlIntMod;
3338    r->cfGcd  = nlGcd;
3339    r->cfDivBy=nlDivBy;
3340    r->cfDivComp = nlDivComp;
3341    r->cfIsUnit = nlIsUnit;
3342    r->cfGetUnit = nlGetUnit;
3343    r->cfQuot1 = nlQuot1;
3344    r->cfLcm = nlLcm;
3345    r->cfXExtGcd=nlXExtGcd;
3346    r->cfQuotRem=nlQuotRem;
3347    r->cfExactDiv= nlExactDiv;
3348  }
3349  r->cfInit = nlInit;
3350  r->cfSize  = nlSize;
3351  r->cfInt  = nlInt;
3352
3353  r->cfChineseRemainder=nlChineseRemainderSym;
3354  r->cfFarey=nlFarey;
3355  r->cfInpNeg   = nlNeg;
3356  r->cfInvers= nlInvers;
3357  r->cfCopy  = nlCopy;
3358  r->cfRePart = nlCopy;
3359  //r->cfImPart = ndReturn0;
3360  r->cfWriteLong = nlWrite;
3361  r->cfRead = nlRead;
3362  r->cfNormalize=nlNormalize;
3363  r->cfGreater = nlGreater;
3364  r->cfEqual = nlEqual;
3365  r->cfIsZero = nlIsZero;
3366  r->cfIsOne = nlIsOne;
3367  r->cfIsMOne = nlIsMOne;
3368  r->cfGreaterZero = nlGreaterZero;
3369  r->cfPower = nlPower;
3370  r->cfGetDenom = nlGetDenom;
3371  r->cfGetNumerator = nlGetNumerator;
3372  r->cfExtGcd = nlExtGcd; // only for ring stuff and Z
3373  r->cfNormalizeHelper  = nlNormalizeHelper;
3374  r->cfDelete= nlDelete;
3375  r->cfSetMap = nlSetMap;
3376  //r->cfName = ndName;
3377  r->cfInpMult=nlInpMult;
3378  r->cfInpAdd=nlInpAdd;
3379  r->cfCoeffWrite=nlCoeffWrite;
3380
3381  r->cfClearContent = nlClearContent;
3382  r->cfClearDenominators = nlClearDenominators;
3383
3384#ifdef LDEBUG
3385  // debug stuff
3386  r->cfDBTest=nlDBTest;
3387#endif
3388  r->convSingNFactoryN=nlConvSingNFactoryN;
3389  r->convFactoryNSingN=nlConvFactoryNSingN;
3390
3391  r->cfRandom=nlRandom;
3392
3393  // io via ssi
3394  r->cfWriteFd=nlWriteFd;
3395  r->cfReadFd=nlReadFd;
3396
3397  // the variables: general stuff (required)
3398  r->nNULL = INT_TO_SR(0);
3399  //r->type = n_Q;
3400  r->ch = 0;
3401  r->has_simple_Alloc=FALSE;
3402  r->has_simple_Inverse=FALSE;
3403
3404  // variables for this type of coeffs:
3405  // (none)
3406  return FALSE;
3407}
3408#if 0
3409number nlMod(number a, number b)
3410{
3411  if (((SR_HDL(b)&SR_HDL(a))&SR_INT)
3412  {
3413    int bi=SR_TO_INT(b);
3414    int ai=SR_TO_INT(a);
3415    int bb=ABS(bi);
3416    int c=ai%bb;
3417    if (c<0)  c+=bb;
3418    return (INT_TO_SR(c));
3419  }
3420  number al;
3421  number bl;
3422  if (SR_HDL(a))&SR_INT)
3423    al=nlRInit(SR_TO_INT(a));
3424  else
3425    al=nlCopy(a);
3426  if (SR_HDL(b))&SR_INT)
3427    bl=nlRInit(SR_TO_INT(b));
3428  else
3429    bl=nlCopy(b);
3430  number r=nlRInit(0);
3431  mpz_mod(r->z,al->z,bl->z);
3432  nlDelete(&al);
3433  nlDelete(&bl);
3434  if (mpz_size1(&r->z)<=MP_SMALL)
3435  {
3436    LONG ui=(int)mpz_get_si(&r->z);
3437    if ((((ui<<3)>>3)==ui)
3438    && (mpz_cmp_si(x->z,(long)ui)==0))
3439    {
3440      mpz_clear(&r->z);
3441      FREE_RNUMBER(r); //  omFreeBin((void *)r, rnumber_bin);
3442      r=INT_TO_SR(ui);
3443    }
3444  }
3445  return r;
3446}
3447#endif
3448#endif // not P_NUMBERS_H
3449#endif // LONGRAT_CC
Note: See TracBrowser for help on using the repository browser.