source: git/libpolys/coeffs/longrat.cc @ 7737b5

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