source: git/libpolys/coeffs/rintegers.cc @ 30f819

spielwiese
Last change on this file since 30f819 was 30f819, checked in by Christian Eder, 6 years ago
adds new quotient with remainder over the integers: tries to compute the smalles possible remainder, even if it has negative sign
  • Property mode set to 100644
File size: 41.5 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT: numbers (integers)
6*/
7
8#include "misc/auxiliary.h"
9
10#include "factory/factory.h"
11
12#include "misc/mylimits.h"
13#include "reporter/reporter.h"
14
15#include "coeffs/coeffs.h"
16#include "coeffs/longrat.h"
17#include "coeffs/numbers.h"
18
19#include "coeffs/si_gmp.h"
20
21#include "coeffs/mpr_complex.h"
22#include "coeffs/rintegers.h"
23#include "coeffs/rmodulon.h"
24#include "coeffs/longrat.h"
25
26#include <string.h>
27
28#ifdef HAVE_RINGS
29
30omBin gmp_nrz_bin = omGetSpecBin(sizeof(mpz_t));
31
32#if SI_INTEGER_VARIANT == 2
33/*
34 * Multiply two numbers
35 */
36static number nrzMult (number a, number b, const coeffs)
37{
38  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
39  mpz_init(erg);
40  mpz_mul(erg, (mpz_ptr) a, (mpz_ptr) b);
41  return (number) erg;
42}
43
44/*
45 * Give the smallest non unit k, such that a * x = k = b * y has a solution
46 */
47static number nrzLcm (number a,number b,const coeffs)
48{
49  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
50  mpz_init(erg);
51  mpz_lcm(erg, (mpz_ptr) a, (mpz_ptr) b);
52  return (number) erg;
53}
54
55/*
56 * Give the largest non unit k, such that a = x * k, b = y * k has
57 * a solution.
58 */
59static number nrzGcd (number a,number b,const coeffs)
60{
61  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
62  mpz_init(erg);
63  mpz_gcd(erg, (mpz_ptr) a, (mpz_ptr) b);
64  return (number) erg;
65}
66
67/*
68 * Give the largest non unit k, such that a = x * k, b = y * k has
69 * a solution and r, s, s.t. k = s*a + t*b
70 */
71static number nrzExtGcd (number a, number b, number *s, number *t, const coeffs)
72{
73  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
74  mpz_ptr bs = (mpz_ptr) omAllocBin(gmp_nrz_bin);
75  mpz_ptr bt = (mpz_ptr) omAllocBin(gmp_nrz_bin);
76  mpz_init(erg);
77  mpz_init(bs);
78  mpz_init(bt);
79  mpz_gcdext(erg, bs, bt, (mpz_ptr) a, (mpz_ptr) b);
80  *s = (number) bs;
81  *t = (number) bt;
82  return (number) erg;
83}
84
85static number nrzXExtGcd (number a, number b, number *s, number *t, number *u, number *v, const coeffs )
86{
87  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
88  mpz_ptr bs = (mpz_ptr) omAllocBin(gmp_nrz_bin);
89  mpz_ptr bt = (mpz_ptr) omAllocBin(gmp_nrz_bin);
90  mpz_init(erg);
91  mpz_init(bs);
92  mpz_init(bt);
93
94  mpz_gcdext(erg, bs, bt, (mpz_ptr)a, (mpz_ptr)b);
95
96  mpz_ptr bu = (mpz_ptr) omAllocBin(gmp_nrz_bin);
97  mpz_ptr bv = (mpz_ptr) omAllocBin(gmp_nrz_bin);
98
99  mpz_init_set(bu, (mpz_ptr) b);
100  mpz_init_set(bv, (mpz_ptr) a);
101
102  assume(mpz_cmp_si(erg, 0));
103
104  mpz_div(bu, bu, erg);
105  mpz_div(bv, bv, erg);
106
107  mpz_mul_si(bu, bu, -1);
108  *u = (number) bu;
109  *v = (number) bv;
110
111  *s = (number) bs;
112  *t = (number) bt;
113  return (number) erg;
114}
115
116static void nrzPower (number a, int i, number * result, const coeffs)
117{
118  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
119  mpz_init(erg);
120  mpz_pow_ui(erg, (mpz_ptr) a, i);
121  *result = (number) erg;
122}
123
124/*
125 * create a number from int
126 */
127number nrzInit (long i, const coeffs)
128{
129  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
130  mpz_init_set_si(erg, i);
131  return (number) erg;
132}
133
134void nrzDelete(number *a, const coeffs)
135{
136  if (*a != NULL)
137  {
138    mpz_clear((mpz_ptr) *a);
139    omFreeBin((ADDRESS) *a, gmp_nrz_bin);
140    *a = NULL;
141  }
142}
143
144static number nrzCopy(number a, const coeffs)
145{
146  if (a==NULL) return NULL;
147  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
148  mpz_init_set(erg, (mpz_ptr) a);
149  return (number) erg;
150}
151
152#if 0
153number nrzCopyMap(number a, const coeffs /*src*/, const coeffs dst)
154{
155  return nrzCopy(a,dst);
156}
157#endif
158
159int nrzSize(number a, const coeffs)
160{
161  mpz_ptr p=(mpz_ptr)a;
162  int s=p->_mp_alloc;
163  if (s==1) s=(mpz_cmp_ui(p,0)!=0);
164  return s;
165
166}
167
168/*
169 * convert a number to int
170 */
171static long nrzInt(number &n, const coeffs)
172{
173  return mpz_get_si( (mpz_ptr)n);
174}
175
176static number nrzAdd (number a, number b, const coeffs)
177{
178  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
179  mpz_init(erg);
180  mpz_add(erg, (mpz_ptr) a, (mpz_ptr) b);
181  return (number) erg;
182}
183
184static number nrzSub (number a, number b, const coeffs)
185{
186  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
187  mpz_init(erg);
188  mpz_sub(erg, (mpz_ptr) a, (mpz_ptr) b);
189  return (number) erg;
190}
191
192static number nrzGetUnit (number, const coeffs r)
193{
194  return nrzInit(1, r);
195}
196
197static BOOLEAN nrzIsUnit (number a, const coeffs)
198{
199  return 0 == mpz_cmpabs_ui((mpz_ptr) a, 1);
200}
201
202static BOOLEAN nrzIsZero (number  a, const coeffs)
203{
204  return 0 == mpz_cmpabs_ui((mpz_ptr) a, 0);
205}
206
207static BOOLEAN nrzIsOne (number a, const coeffs)
208{
209  return (0 == mpz_cmp_ui((mpz_ptr) a, 1));
210}
211
212static BOOLEAN nrzIsMOne (number a, const coeffs)
213{
214  return (0 == mpz_cmp_si((mpz_ptr) a, -1));
215}
216
217static BOOLEAN nrzEqual (number a,number b, const coeffs)
218{
219  return 0 == mpz_cmp((mpz_ptr) a, (mpz_ptr) b);
220}
221
222static BOOLEAN nrzGreater (number a,number b, const coeffs)
223{
224  return 0 < mpz_cmp((mpz_ptr) a, (mpz_ptr) b);
225}
226
227static BOOLEAN nrzGreaterZero (number k, const coeffs)
228{
229  return 0 < mpz_sgn1((mpz_ptr) k);
230}
231
232static BOOLEAN nrzDivBy (number a,number b, const coeffs)
233{
234  return mpz_divisible_p((mpz_ptr) a, (mpz_ptr) b) != 0;
235}
236
237static int nrzDivComp(number a, number b, const coeffs r)
238{
239  if (nrzDivBy(a, b, r))
240  {
241    if (nrzDivBy(b, a, r)) return 2;
242    return -1;
243  }
244  if (nrzDivBy(b, a, r)) return 1;
245  return 0;
246}
247
248static number nrzDiv (number a,number b, const coeffs)
249{
250  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
251  mpz_init(erg);
252  mpz_ptr r = (mpz_ptr) omAllocBin(gmp_nrz_bin);
253  mpz_init(r);
254  mpz_tdiv_qr(erg, r, (mpz_ptr) a, (mpz_ptr) b);
255  //if (!nrzIsZero((number) r, R))
256  //{
257  //  WerrorS("Division by non divisible element.");
258  //  WerrorS("Result is without remainder.");
259  //}
260  mpz_clear(r);
261  omFreeBin(r, gmp_nrz_bin);
262  return (number) erg;
263}
264
265static number nrzExactDiv (number a,number b, const coeffs)
266{
267  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
268  mpz_init(erg);
269  mpz_tdiv_q(erg, (mpz_ptr) a, (mpz_ptr) b);
270  return (number) erg;
271}
272
273static number nrzSmallestQuotRem (number a, number b, number * r, const coeffs )
274{
275  mpz_ptr qq = (mpz_ptr) omAllocBin(gmp_nrz_bin);
276  mpz_init(qq);
277  mpz_ptr rr = (mpz_ptr) omAllocBin(gmp_nrz_bin);
278  mpz_init(rr);
279  int gsign = mpz_sgn((mpz_ptr) b);
280  mpz_t gg, ghalf;
281  mpz_init(gg);
282  mpz_init(ghalf);
283  mpz_abs(gg, (mpz_ptr) b);
284  mpz_fdiv_qr(qq, rr, (mpz_ptr) a, gg);
285  mpz_tdiv_q_2exp(ghalf, gg, 1);
286  if (mpz_cmp(rr, ghalf) > 0)  // r > ghalf
287    {
288      mpz_sub(rr, rr, gg);
289      mpz_add_ui(qq, qq, 1);
290    }
291  if (gsign < 0) mpz_neg(qq, qq);
292
293  mpz_clear(gg);
294  mpz_clear(ghalf);
295  if (r==NULL)
296  {
297    mpz_clear(rr);
298    omFreeBin(rr,gmp_nrz_bin);
299  }
300  else
301  {
302    *r=(number)rr;
303  }
304  return (number) qq;
305}
306
307static number nrzQuotRem (number a, number b, number * r, const coeffs )
308{
309  mpz_ptr qq = (mpz_ptr) omAllocBin(gmp_nrz_bin);
310  mpz_init(qq);
311  mpz_ptr rr = (mpz_ptr) omAllocBin(gmp_nrz_bin);
312  mpz_init(rr);
313  mpz_tdiv_qr(qq, rr, (mpz_ptr) a, (mpz_ptr) b);
314  if (r==NULL)
315  {
316    mpz_clear(rr);
317    omFreeBin(rr,gmp_nrz_bin);
318  }
319  else
320  {
321    *r=(number)rr;
322  }
323  return (number) qq;
324}
325
326static number nrzIntMod (number a,number b, const coeffs)
327{
328  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
329  mpz_init(erg);
330  mpz_ptr r = (mpz_ptr) omAllocBin(gmp_nrz_bin);
331  mpz_init(r);
332  mpz_tdiv_qr(erg, r, (mpz_ptr) a, (mpz_ptr) b);
333  mpz_clear(erg);
334  omFreeBin(erg, gmp_nrz_bin);
335  return (number) r;
336}
337
338static number  nrzInvers (number c, const coeffs r)
339{
340  if (!nrzIsUnit((number) c, r))
341  {
342    WerrorS("Non invertible element.");
343    return (number)NULL;
344  }
345  return nrzCopy(c,r);
346}
347
348static number nrzNeg (number c, const coeffs)
349{
350// nNeg inplace !!!
351  mpz_mul_si((mpz_ptr) c, (mpz_ptr) c, -1);
352  return c;
353}
354
355static number nrzMapMachineInt(number from, const coeffs /*src*/, const coeffs /*dst*/)
356{
357  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
358  mpz_init_set_ui(erg, (unsigned long) from);
359  return (number) erg;
360}
361
362static number nrzMapZp(number from, const coeffs /*src*/, const coeffs /*dst*/)
363{
364  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
365  mpz_init_set_si(erg, (long) from);
366  return (number) erg;
367}
368
369static number nrzMapQ(number from, const coeffs src, const coeffs /*dst*/)
370{
371  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
372  mpz_init(erg);
373  nlGMP(from, erg, src); // FIXME? TODO? // extern void   nlGMP(number &i, number n, const coeffs r); // to be replaced with n_MPZ(erg, from, src); // ?
374  return (number) erg;
375}
376
377static nMapFunc nrzSetMap(const coeffs src, const coeffs /*dst*/)
378{
379  /* dst = currRing */
380  /* dst = nrn */
381  if ((src->rep==n_rep_gmp)
382  && (nCoeff_is_Z(src) || nCoeff_is_Zn(src) || nCoeff_is_Ring_PtoM(src)))
383  {
384    return ndCopyMap; //nrzCopyMap;
385  }
386  if ((src->rep==n_rep_gap_gmp) /*&& nCoeff_is_Z(src)*/)
387  {
388    return ndCopyMap; //nrzCopyMap;
389  }
390  if (nCoeff_is_Ring_2toM(src))
391  {
392    return nrzMapMachineInt;
393  }
394  if (nCoeff_is_Zp(src))
395  {
396    return nrzMapZp;
397  }
398  if (getCoeffType(src)==n_Q /*nCoeff_is_Q(src) or coeffs_BIGINT*/)
399  {
400    return nrzMapQ;
401  }
402  return NULL;      // default
403}
404
405/*
406 * set the exponent (allocate and init tables) (TODO)
407 */
408
409void nrzSetExp(int, coeffs)
410{
411}
412
413void nrzInitExp(int, coeffs)
414{
415}
416
417#ifdef LDEBUG
418static BOOLEAN nrzDBTest (number, const char *, const int, const coeffs)
419{
420  return TRUE;//TODO
421}
422#endif
423
424void nrzWrite (number a, const coeffs)
425{
426  char *s,*z;
427  if (a==NULL)
428  {
429    StringAppendS("o");
430  }
431  else
432  {
433    int l=mpz_sizeinbase((mpz_ptr) a, 10) + 2;
434    s=(char*)omAlloc(l);
435    z=mpz_get_str(s,10,(mpz_ptr) a);
436    StringAppendS(z);
437    omFreeSize((ADDRESS)s,l);
438  }
439}
440
441/*2
442* extracts a long integer from s, returns the rest    (COPY FROM longrat0.cc)
443*/
444static const char * nlEatLongC(char *s, mpz_ptr i)
445{
446  const char * start=s;
447
448  if (*s<'0' || *s>'9')
449  {
450    mpz_set_ui(i,1);
451    return s;
452  }
453  while (*s >= '0' && *s <= '9') s++;
454  if (*s=='\0')
455  {
456    mpz_set_str(i,start,10);
457  }
458  else
459  {
460    char c=*s;
461    *s='\0';
462    mpz_set_str(i,start,10);
463    *s=c;
464  }
465  return s;
466}
467
468
469static CanonicalForm nrzConvSingNFactoryN(number n, BOOLEAN setChar, const coeffs /*r*/)
470{
471  if (setChar) setCharacteristic( 0 );
472
473  CanonicalForm term;
474  mpz_t num;
475  mpz_init_set(num, *((mpz_t*)n));
476  term = make_cf(num);
477  return term;
478}
479
480static number nrzConvFactoryNSingN(const CanonicalForm n, const coeffs r)
481{
482  if (n.isImm())
483    return nrzInit(n.intval(),r);
484  else
485  {
486    mpz_ptr m = (mpz_ptr) omAllocBin(gmp_nrz_bin);
487    gmp_numerator(n,m);
488    if (!n.den().isOne())
489    {
490      WarnS("denominator is not 1 in factory");
491    }
492    return (number) m;
493  }
494}
495
496static const char * nrzRead (const char *s, number *a, const coeffs)
497{
498  mpz_ptr z = (mpz_ptr) omAllocBin(gmp_nrz_bin);
499  {
500    mpz_init(z);
501    s = nlEatLongC((char *) s, z);
502  }
503  *a = (number) z;
504  return s;
505}
506
507static void nrzCoeffWrite  (const coeffs, BOOLEAN /*details*/)
508{
509  PrintS("ZZ");
510}
511
512static char* nrzCoeffName(const coeffs)
513{
514  return (char*)"ZZ";
515}
516
517static char* nrzCoeffString(const coeffs cf)
518{
519  return omStrDup(nrzCoeffName(cf));
520}
521
522static coeffs nrzQuot1(number c, const coeffs r)
523{
524    long ch = r->cfInt(c, r);
525    mpz_t dummy;
526    mpz_init_set_ui(dummy, ch);
527    ZnmInfo info;
528    info.base = dummy;
529    info.exp = (unsigned long) 1;
530    coeffs rr = nInitChar(n_Zn, (void*)&info);
531    mpz_clear(dummy);
532    return(rr);
533}
534
535static number nrzInitMPZ(mpz_t m, const coeffs)
536{
537  mpz_ptr z = (mpz_ptr) omAllocBin(gmp_nrz_bin);
538  mpz_init_set(z, m);
539  return (number)z;
540}
541
542static number nrzFarey(number r, number N, const coeffs R)
543{
544  number a0 = nrzCopy(N, R);
545  number b0 = nrzInit(0, R);
546  number a1 = nrzCopy(r, R);
547  number b1 = nrzInit(1, R);
548  number two = nrzInit(2, R);
549#if 0
550  PrintS("Farey start with ");
551  n_Print(r, R);
552  PrintS(" mod ");
553  n_Print(N, R);
554  PrintLn();
555#endif
556  while (1)
557  {
558    number as = nrzMult(a1, a1, R);
559    n_InpMult(as, two, R);
560    if (nrzGreater(N, as, R))
561    {
562      nrzDelete(&as, R);
563      break;
564    }
565    nrzDelete(&as, R);
566    number q = nrzDiv(a0, a1, R);
567    number t = nrzMult(a1, q, R),
568           s = nrzSub(a0, t, R);
569    nrzDelete(&a0, R);
570    a0 = a1;
571    a1 = s;
572    nrzDelete(&t, R);
573
574    t = nrzMult(b1, q, R);
575    s = nrzSub(b0, t, R);
576    nrzDelete(&b0, R);
577    b0 = b1;
578    b1 = s;
579    nrzDelete(&t, R);
580    nrzDelete(&q, R);
581  }
582  number as = nrzMult(b1, b1, R);
583  n_InpMult(as, two, R);
584  nrzDelete(&two, R);
585  if (nrzGreater(as, N, R))
586  {
587    nrzDelete(&a0, R);
588    nrzDelete(&a1, R);
589    nrzDelete(&b0, R);
590    nrzDelete(&b1, R);
591    nrzDelete(&as, R);
592    return NULL;
593  }
594  nrzDelete(&as, R);
595  nrzDelete(&a0, R);
596  nrzDelete(&b0, R);
597
598  number a, b, ab;
599  coeffs Q = nInitChar(n_Q, 0);
600  nMapFunc f = n_SetMap(R, Q);
601  a = f(a1, R, Q);
602  b = f(b1, R, Q);
603  ab = n_Div(a, b, Q);
604  n_Delete(&a, Q);
605  n_Delete(&b, Q);
606  nKillChar(Q);
607
608  nrzDelete(&a1, R);
609  nrzDelete(&b1, R);
610  return ab;
611}
612
613void nrzWriteFd(number n, const ssiInfo* d, const coeffs)
614{
615  mpz_out_str (d->f_write,SSI_BASE, (mpz_ptr)n);
616  fputc(' ',d->f_write);
617}
618
619number nrzReadFd(const ssiInfo *d, const coeffs)
620{
621  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
622  mpz_init(erg);
623  s_readmpz_base(d->f_read,erg,SSI_BASE);
624  return (number)erg;
625}
626
627BOOLEAN nrzInitChar(coeffs r,  void *)
628{
629  assume( getCoeffType(r) == n_Z );
630
631  r->is_field=FALSE;
632  r->is_domain=TRUE;
633  r->rep=n_rep_gmp;
634
635  //r->nCoeffIsEqual = ndCoeffIsEqual;
636  r->cfCoeffString = nrzCoeffString;
637  r->cfCoeffName = nrzCoeffName;
638  r->cfCoeffWrite = nrzCoeffWrite;
639  //r->cfKillChar = ndKillChar;
640  r->cfMult  = nrzMult;
641  r->cfSub   = nrzSub;
642  r->cfAdd   = nrzAdd;
643  r->cfDiv   = nrzDiv;
644  r->cfIntMod= nrzIntMod;
645  r->cfExactDiv= nrzExactDiv;
646  r->cfInit = nrzInit;
647  r->cfInitMPZ = nrzInitMPZ;
648  r->cfSize  = nrzSize;
649  r->cfInt  = nrzInt;
650  r->cfDivComp = nrzDivComp;
651  r->cfIsUnit = nrzIsUnit;
652  r->cfGetUnit = nrzGetUnit;
653  r->cfExtGcd = nrzExtGcd;
654  r->cfXExtGcd = nrzXExtGcd;
655  r->cfDivBy = nrzDivBy;
656  r->cfQuotRem = nrzSmallestQuotRem;
657  r->cfInpNeg   = nrzNeg;
658  r->cfInvers= nrzInvers;
659  r->cfCopy  = nrzCopy;
660  r->cfWriteLong = nrzWrite;
661  r->cfRead = nrzRead;
662  r->cfGreater = nrzGreater;
663  r->cfEqual = nrzEqual;
664  r->cfIsZero = nrzIsZero;
665  r->cfIsOne = nrzIsOne;
666  r->cfIsMOne = nrzIsMOne;
667  r->cfGreaterZero = nrzGreaterZero;
668  r->cfPower = nrzPower;
669  r->cfGcd  = nrzGcd;
670  r->cfLcm  = nrzLcm;
671  r->cfDelete= nrzDelete;
672  r->cfSetMap = nrzSetMap;
673  r->cfQuot1 = nrzQuot1;
674  r->convSingNFactoryN=nrzConvSingNFactoryN;
675  r->convFactoryNSingN=nrzConvFactoryNSingN;
676  r->cfChineseRemainder=nlChineseRemainderSym;
677  r->cfFarey=nrzFarey;
678  r->cfWriteFd=nrzWriteFd;
679  r->cfReadFd=nrzReadFd;
680  // debug stuff
681
682#ifdef LDEBUG
683  r->cfDBTest=nrzDBTest;
684#endif
685
686  r->ch = 0;
687  r->has_simple_Alloc=FALSE;
688  r->has_simple_Inverse=FALSE;
689  return FALSE;
690}
691
692#elif SI_INTEGER_VARIANT == 3
693
694//make sure that a small number is an immediate integer
695//bascially coped from longrat.cc nlShort3
696//TODO: is there any point in checking 0 first???
697//TODO: it is not clear that this works in 32/64 bit everywhere.
698//      too many hacks.
699#ifdef LDEBUG
700#define nrzTest(A) nrzDBTest(A,__FILE__,__LINE__,NULL)
701BOOLEAN nrzDBTest (number x, const char *f, const int l, const coeffs);
702#else
703#define nrzTest(A)
704#endif
705
706#undef CF_DEBUG
707static inline number nrz_short(number x)
708{
709#if CF_DEBUG
710  StringAppendS("short(");
711  nrzWrite(x, NULL);
712#endif
713  if (mpz_sgn1((mpz_ptr) x)==0)
714  {
715    mpz_clear((mpz_ptr)x);
716    omFreeBin(x, gmp_nrz_bin);
717#if CF_DEBUG
718    StringAppendS(")=0");
719#endif
720    return INT_TO_SR(0);
721  }
722  if (mpz_size1((mpz_ptr)x)<=MP_SMALL)
723  {
724    long ui=mpz_get_si((mpz_ptr)x);
725    if ((((ui<<3)>>3)==ui)
726    && (mpz_cmp_si((mpz_ptr)x,ui)==0))
727    {
728      mpz_clear((mpz_ptr)x);
729      omFreeBin(x, gmp_nrz_bin);
730#if CF_DEBUG
731    StringAppendS(")=imm");
732#endif
733      return INT_TO_SR(ui);
734    }
735  }
736#if CF_DEBUG
737  StringAppendS(")");
738#endif
739  return x;
740}
741
742
743static int nrzSize(number a, const coeffs)
744{
745  if (a==INT_TO_SR(0)) return 0;
746  if (n_Z_IS_SMALL(a)) return 1;
747  return ((mpz_ptr)a)->_mp_alloc;
748}
749
750
751/*
752 * Multiply two numbers
753 * check for 0, 1, -1 maybe
754 */
755#if CF_DEBUG
756number _nrzMult(number, number, const coeffs);
757number nrzMult(number a, number b, const coeffs R)
758{
759  StringSetS("Mult: ");
760  nrzWrite(a, R);
761  StringAppendS(" by ");
762  nrzWrite(b, R);
763  number c = _nrzMult(a, b, R);
764  StringAppendS(" is ");
765  nrzWrite(c, R);
766  char * s = StringEndS();
767  Print("%s\n", s);
768  omFree(s);
769  return c;
770}
771number _nrzMult (number a, number b, const coeffs R)
772#else
773number nrzMult (number a, number b, const coeffs R)
774#endif
775{
776  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
777  {
778  //from longrat.cc
779    if (SR_TO_INT(a)==0)
780      return a;
781    if (SR_TO_INT(b)==0)
782      return b;
783    long r=(long)((unsigned long)(SR_HDL(a)-1L))*((unsigned long)(SR_HDL(b)>>1));
784    if ((r/(SR_HDL(b)>>1))==(SR_HDL(a)-1L))
785    {
786      number u=((number) ((r>>1)+SR_INT));
787    //  if (((((long)SR_HDL(u))<<1)>>1)==SR_HDL(u)) return (u);
788      return nrzInit(SR_HDL(u)>>2, R);
789    }
790    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
791    mpz_init(erg);
792    mpz_set_si(erg, SR_TO_INT(a));
793    mpz_mul_si(erg, erg, SR_TO_INT(b));
794    nrzTest((number)erg);
795    return (number) erg;
796  }
797  else if (n_Z_IS_SMALL(a))
798  {
799    if (SR_TO_INT(a)==0)
800      return a;
801    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
802    mpz_init_set(erg, (mpz_ptr) b);
803    mpz_mul_si(erg, erg, SR_TO_INT(a));
804    nrzTest((number)erg);
805    return (number) erg;
806  }
807  else if (n_Z_IS_SMALL(b))
808  {
809    if (SR_TO_INT(b)==0)
810      return b;
811    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
812    mpz_init_set(erg, (mpz_ptr) a);
813    mpz_mul_si(erg, erg, SR_TO_INT(b));
814    nrzTest((number)erg);
815    return (number) erg;
816  }
817  else
818  {
819    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
820    mpz_init(erg);
821    mpz_mul(erg, (mpz_ptr) a, (mpz_ptr) b);
822    nrzTest((number)erg);
823    return (number) erg;
824  }
825}
826
827
828static long int_gcd(long a, long b)
829{
830  long r;
831  a = ABS(a);
832  b = ABS(b);
833  if (!a) return b;
834  if (!b) return a;
835  do
836  {
837    r = a % b;
838    a = b;
839    b = r;
840  } while (b);
841  return ABS(a); // % in c doeas not imply a signn
842                 // it would be unlikely to see a negative here
843                 // but who knows
844}
845
846/*
847 * Give the smallest non unit k, such that a * x = k = b * y has a solution
848 */
849static number nrzLcm (number a, number b, const coeffs R)
850{
851  #ifdef CF_DEBUG
852  PrintS("nrzLcm\n");
853  #endif
854  mpz_ptr erg;
855  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
856  {
857    long g = int_gcd(SR_TO_INT(a), SR_TO_INT(b));
858    return nrzMult(a, INT_TO_SR(SR_TO_INT(b)/g), R);
859  }
860  else
861  {
862    erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
863    if (n_Z_IS_SMALL(a))
864    {
865      mpz_init_set(erg, (mpz_ptr) b);
866      unsigned long g = mpz_gcd_ui(NULL, erg, (unsigned long) ABS(SR_TO_INT(a)));
867      mpz_mul_si(erg, erg, SR_TO_INT(a)/g);
868    }
869    else if (n_Z_IS_SMALL(b))
870    {
871      mpz_init_set(erg, (mpz_ptr) a);
872      unsigned long g = mpz_gcd_ui(NULL, erg, (unsigned long) ABS(SR_TO_INT(b)));
873      mpz_mul_si(erg, erg, SR_TO_INT(b)/g);
874    }
875    else
876    {
877      mpz_init(erg);
878      mpz_lcm(erg, (mpz_ptr) a, (mpz_ptr) b);
879    }
880  }
881  return (number) erg;
882}
883
884static number nrzCopy(number a, const coeffs)
885{
886  if (n_Z_IS_SMALL(a)) return a;
887  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
888  mpz_init_set(erg, (mpz_ptr) a);
889  return (number) erg;
890}
891
892/*
893 * Give the largest non unit k, such that a = x * k, b = y * k has
894 * a solution.
895 */
896static number nrzGcd (number a,number b,const coeffs R)
897{
898  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
899  {
900    long g = int_gcd(SR_TO_INT(a), SR_TO_INT(b));
901    return INT_TO_SR(g);
902  }
903  else if (n_Z_IS_SMALL(a))
904  {
905    if (a==INT_TO_SR(0))
906      return nrzCopy(b, R);
907    unsigned long g = mpz_gcd_ui(NULL, (mpz_ptr)b, (unsigned long) ABS(SR_TO_INT(a)));
908    return INT_TO_SR( g);
909  }
910  else if (n_Z_IS_SMALL(b))
911  {
912    if (b==INT_TO_SR(0))
913      return nrzCopy(a, R);
914    unsigned long g = mpz_gcd_ui(NULL, (mpz_ptr)a, (unsigned long) ABS(SR_TO_INT(b)));
915    return INT_TO_SR(g);
916  }
917  else
918  {
919    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
920    mpz_init(erg);
921    mpz_gcd(erg, (mpz_ptr) a, (mpz_ptr) b);
922    return (number) erg;
923  }
924}
925
926/*
927 * Give the largest non unit k, such that a = x * k, b = y * k has
928 * a solution and r, s, s.t. k = s*a + t*b
929 */
930static long int_extgcd(long a, long b, long * u, long* x, long * v, long* y)
931{
932  long q, r;
933  if (!a)
934  {
935    *u = 0;
936    *v = 1;
937    *x = -1;
938    *y = 0;
939    return b;
940  }
941  if (!b)
942  {
943    *u = 1;
944    *v = 0;
945    *x = 0;
946    *y = 1;
947    return a;
948  }
949  *u=1;
950  *v=0;
951  *x=0;
952  *y=1;
953  do
954  {
955    q = a/b;
956    r = a%b;
957    assume (q*b+r == a);
958    a = b;
959    b = r;
960
961    r = -(*v)*q+(*u);
962    (*u) =(*v);
963    (*v) = r;
964
965    r = -(*y)*q+(*x);
966    (*x) = (*y);
967    (*y) = r;
968  } while (b);
969
970  return a;
971}
972
973static number  nrzExtGcd (number a, number b, number *s, number *t, const coeffs)
974{
975  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
976  {
977    long u, v, x, y;
978    long g = int_extgcd(SR_TO_INT(a), SR_TO_INT(b), &u, &v, &x, &y);
979    *s = INT_TO_SR(u);
980    *t = INT_TO_SR(v);
981    return INT_TO_SR(g);
982  }
983  else
984  {
985    mpz_t aa, bb;
986    if (n_Z_IS_SMALL(a))
987    {
988      mpz_init_set_si(aa, SR_TO_INT(a));
989    }
990    else
991    {
992      mpz_init_set(aa, (mpz_ptr) a);
993    }
994    if (n_Z_IS_SMALL(b))
995    {
996      mpz_init_set_si(bb, SR_TO_INT(b));
997    }
998    else
999    {
1000      mpz_init_set(bb, (mpz_ptr) b);
1001    }
1002    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1003    mpz_ptr bs = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1004    mpz_ptr bt = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1005    mpz_init(erg);
1006    mpz_init(bs);
1007    mpz_init(bt);
1008    mpz_gcdext(erg, bs, bt, aa, bb);
1009    *s = nrz_short((number) bs);
1010    *t = nrz_short((number) bt);
1011    mpz_clear(aa);
1012    mpz_clear(bb);
1013    return nrz_short((number) erg);
1014  }
1015}
1016#if CF_DEBUG
1017static number _nrzXExtGcd(number, number, number *, number *, number *, number *, const coeffs);
1018static number nrzXExtGcd(number a, number b, number *x, number * y, number * u, number * v, const coeffs R)
1019{
1020  char * s;
1021  StringSetS("XExtGcd: ");
1022  nrzWrite(a, R);
1023  StringAppendS(" by ");
1024  nrzWrite(b, R);
1025  number c = _nrzXExtGcd(a, b, x, y, u, v, R);
1026  StringAppendS(" is ");
1027  nrzWrite(c, R);
1028  StringAppendS("[[");
1029  nrzWrite(*x, R);
1030  StringAppendS(", ");
1031  nrzWrite(*y, R);
1032  StringAppendS("], ");
1033  nrzWrite(*u, R);
1034  StringAppendS(", ");
1035  nrzWrite(*v, R);
1036  s=StringEndS();
1037  Print("%s]]\n", s);
1038  omFree(s);
1039  return c;
1040}
1041static number  _nrzXExtGcd (number a, number b, number *s, number *t, number *u, number *v, const coeffs )
1042#else
1043static number  nrzXExtGcd (number a, number b, number *s, number *t, number *u, number *v, const coeffs )
1044#endif
1045{
1046  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
1047  {
1048    long uu, vv, x, y;
1049    long g = int_extgcd(SR_TO_INT(a), SR_TO_INT(b), &uu, &vv, &x, &y);
1050    *s = INT_TO_SR(uu);
1051    *t = INT_TO_SR(vv);
1052    *u = INT_TO_SR(x);
1053    *v = INT_TO_SR(y);
1054    return INT_TO_SR(g);
1055  }
1056  else
1057  {
1058    mpz_t aa, bb;
1059    if (n_Z_IS_SMALL(a))
1060    {
1061      mpz_init_set_si(aa, SR_TO_INT(a));
1062    }
1063    else
1064    {
1065      mpz_init_set(aa, (mpz_ptr) a);
1066    }
1067    if (n_Z_IS_SMALL(b))
1068    {
1069      mpz_init_set_si(bb, SR_TO_INT(b));
1070    }
1071    else
1072    {
1073      mpz_init_set(bb, (mpz_ptr) b);
1074    }
1075    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1076    mpz_ptr bs = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1077    mpz_ptr bt = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1078    mpz_init(erg);
1079    mpz_init(bs);
1080    mpz_init(bt);
1081
1082    mpz_gcdext(erg, bs, bt, aa, bb);
1083
1084    mpz_ptr bu = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1085    mpz_ptr bv = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1086
1087    mpz_init_set(bu, (mpz_ptr) bb);
1088    mpz_init_set(bv, (mpz_ptr) aa);
1089
1090    mpz_clear(aa);
1091    mpz_clear(bb);
1092    assume(mpz_cmp_si(erg, 0));
1093
1094    mpz_div(bu, bu, erg);
1095    mpz_div(bv, bv, erg);
1096
1097    mpz_mul_si(bu, bu, -1);
1098    *u = nrz_short((number) bu);
1099    *v = nrz_short((number) bv);
1100
1101    *s = nrz_short((number) bs);
1102    *t = nrz_short((number) bt);
1103    return nrz_short((number) erg);
1104  }
1105}
1106#if CF_DEBUG
1107static number _nrzQuotRem(number, number, number *, const coeffs);
1108static number nrzQuotRem(number a, number b, number * r, const coeffs R)
1109{
1110  StringSetS("QuotRem: ");
1111  nrzWrite(a, R);
1112  StringAppendS(" by ");
1113  nrzWrite(b, R);
1114  number c = _nrzQuotRem(a, b, r, R);
1115  StringAppendS(" is ");
1116  nrzWrite(c, R);
1117  if (r) {
1118    StringAppendS("+R(");
1119    nrzWrite(*r, R);
1120    StringAppendS(")");
1121  }
1122  char * s = StringEndS();
1123  Print("%s\n", s);
1124  omFree(s);
1125  return c;
1126}
1127static number _nrzQuotRem (number a, number b, number * r, const coeffs )
1128#else
1129static number nrzQuotRem (number a, number b, number * r, const coeffs )
1130#endif
1131{
1132  assume(SR_TO_INT(b));
1133  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
1134  {
1135    if (r)
1136      *r = INT_TO_SR(SR_TO_INT(a) % SR_TO_INT(b));
1137    return INT_TO_SR(SR_TO_INT(a)/SR_TO_INT(b));
1138  }
1139  else if (n_Z_IS_SMALL(a))
1140  {
1141    //a is small, b is not, so q=0, r=a
1142    if (r)
1143      *r = a;
1144    return INT_TO_SR(0);
1145  }
1146  else if (n_Z_IS_SMALL(b))
1147  {
1148    unsigned long rr;
1149    mpz_ptr qq = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1150    mpz_init(qq);
1151    mpz_t rrr;
1152    mpz_init(rrr);
1153    rr = mpz_divmod_ui(qq, rrr, (mpz_ptr) a, (unsigned long)ABS(SR_TO_INT(b)));
1154    mpz_clear(rrr);
1155
1156    if (r)
1157      *r = INT_TO_SR(rr);
1158    if (SR_TO_INT(b)<0)
1159    {
1160      mpz_mul_si(qq, qq, -1);
1161    }
1162    return nrz_short((number)qq);
1163  }
1164  mpz_ptr qq = (mpz_ptr) omAllocBin(gmp_nrz_bin),
1165             rr = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1166  mpz_init(qq);
1167  mpz_init(rr);
1168  mpz_divmod(qq, rr, (mpz_ptr)a, (mpz_ptr)b);
1169  if (r)
1170    *r = (number) rr;
1171  else
1172  {
1173    mpz_clear(rr);
1174  }
1175  nrzTest((number)qq);
1176  return (number) qq;
1177}
1178
1179static void nrzPower (number a, int i, number * result, const coeffs)
1180{
1181  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1182  mpz_init(erg);
1183  mpz_t aa;
1184  if (n_Z_IS_SMALL(a))
1185    mpz_init_set_si(aa, SR_TO_INT(a));
1186  else
1187    mpz_init_set(aa, (mpz_ptr) a);
1188  mpz_pow_ui(erg, aa, i);
1189  *result = nrz_short((number) erg);
1190}
1191
1192/*
1193 * create a number from int
1194 * TODO: do not create an mpz if not necessary
1195 */
1196number nrzInit (long i, const coeffs)
1197{
1198  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1199  mpz_init_set_si(erg, i);
1200  return nrz_short((number) erg);
1201}
1202
1203static number nrzInitMPZ(mpz_t m, const coeffs)
1204{
1205  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1206  mpz_init_set(erg, m);
1207  return nrz_short((number) erg);
1208}
1209
1210
1211static void nrzDelete(number *a, const coeffs)
1212{
1213  if (*a == NULL) return;
1214  if (n_Z_IS_SMALL(*a)==0)
1215  {
1216    mpz_clear((mpz_ptr) *a);
1217    omFreeBin((ADDRESS) *a, gmp_nrz_bin);
1218  }
1219  *a = NULL;
1220}
1221
1222/*
1223 * convert a number to int
1224 */
1225static long nrzInt(number &n, const coeffs)
1226{
1227  if (n_Z_IS_SMALL(n)) return SR_TO_INT(n);
1228  return mpz_get_si( (mpz_ptr)n);
1229}
1230#if CF_DEBUG
1231static number _nrzAdd(number, number, const coeffs);
1232static number nrzAdd(number a, number b, const coeffs R)
1233{
1234  StringSetS("Add: ");
1235  nrzWrite(a, R);
1236  StringAppendS(" to ");
1237  nrzWrite(b, R);
1238  number c = _nrzAdd(a, b, R);
1239  StringAppendS(" is ");
1240  nrzWrite(c, R);
1241  char * s = StringEndS();
1242  Print("%s\n", s);
1243  omFree(s);
1244  return c;
1245}
1246static number _nrzAdd (number a, number b, const coeffs )
1247#else
1248static number nrzAdd (number a, number b, const coeffs )
1249#endif
1250{
1251  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
1252  {
1253    long c = SR_TO_INT(a) + SR_TO_INT(b);
1254    if (INT_IS_SMALL(c))
1255      return INT_TO_SR(c);
1256    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1257    mpz_init_set_si(erg, c);
1258
1259    nrzTest((number)erg);
1260    return (number) erg;
1261  }
1262  else if (n_Z_IS_SMALL(a))
1263  {
1264    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1265    mpz_init(erg);
1266    if (SR_TO_INT(a)>0)
1267      mpz_add_ui(erg, (mpz_ptr) b, (unsigned long)SR_TO_INT(a));
1268    else
1269      mpz_sub_ui(erg, (mpz_ptr) b, (unsigned long)-(SR_TO_INT(a)));
1270    return nrz_short((number) erg);
1271  }
1272  else if (n_Z_IS_SMALL(b))
1273  {
1274    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1275    mpz_init(erg);
1276    if (SR_TO_INT(b)>0)
1277      mpz_add_ui(erg, (mpz_ptr) a, (unsigned long)SR_TO_INT(b));
1278    else
1279      mpz_sub_ui(erg, (mpz_ptr) a, (unsigned long)-(SR_TO_INT(b)));
1280    return nrz_short((number) erg);
1281  }
1282  else
1283  {
1284    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1285    mpz_init(erg);
1286    mpz_add(erg, (mpz_ptr) a, (mpz_ptr) b);
1287    return nrz_short((number) erg);
1288  }
1289}
1290
1291static number nrzSub (number a, number b,  const coeffs )
1292{
1293  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
1294  {
1295    long c = SR_TO_INT(a) - SR_TO_INT(b);
1296    if (INT_IS_SMALL(c))
1297      return INT_TO_SR(c);
1298    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1299    mpz_init_set_si(erg, c);
1300    nrzTest((number)erg);
1301    return (number) erg;
1302  }
1303  else if (n_Z_IS_SMALL(a))
1304  {
1305    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1306    mpz_init(erg);
1307
1308    if (SR_TO_INT(a)>0)
1309      mpz_ui_sub(erg, (unsigned long)SR_TO_INT(a), (mpz_ptr) b);
1310    else
1311    {
1312      mpz_add_ui(erg, (mpz_ptr) b, (unsigned long)-SR_TO_INT(a));
1313      mpz_neg(erg, erg);
1314    }
1315    return nrz_short((number) erg);
1316  }
1317  else if (n_Z_IS_SMALL(b))
1318  {
1319    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1320    mpz_init(erg);
1321    if (SR_TO_INT(b)>0)
1322      mpz_sub_ui(erg, (mpz_ptr) a, (unsigned long)SR_TO_INT(b));
1323    else
1324      mpz_add_ui(erg, (mpz_ptr) a, (unsigned long)-SR_TO_INT(b));
1325    return nrz_short((number) erg);
1326  }
1327  else
1328  {
1329    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1330    mpz_init(erg);
1331    mpz_sub(erg, (mpz_ptr) a, (mpz_ptr) b);
1332    return nrz_short((number) erg);
1333  }
1334}
1335
1336static BOOLEAN nrzGreater (number a,number b, const coeffs)
1337{
1338  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
1339    return ((long)a)>((long)b);
1340  else if (n_Z_IS_SMALL(a))
1341    return 0 > mpz_cmp_si((mpz_ptr)b,SR_TO_INT(a));
1342  else if (n_Z_IS_SMALL(b))
1343    return 0 < mpz_cmp_si((mpz_ptr)a,SR_TO_INT(b));
1344  return 0 < mpz_cmp((mpz_ptr) a, (mpz_ptr) b);
1345}
1346
1347static BOOLEAN nrzGreaterZero (number k, const coeffs C)
1348{
1349  return nrzGreater(k, INT_TO_SR(0), C);
1350}
1351
1352static number  nrzGetUnit (number n, const coeffs r)
1353{
1354  if (nrzGreaterZero(n, r))
1355    return INT_TO_SR(1);
1356  /*else*/
1357    return INT_TO_SR(-1);
1358}
1359
1360static number nrzAnn(number n, const coeffs)
1361{
1362  if (SR_TO_INT(n))  // in Z: the annihilator of !=0 is 0
1363    return INT_TO_SR(0);
1364  else
1365    return INT_TO_SR(1);
1366}
1367
1368static BOOLEAN nrzIsUnit (number a, const coeffs)
1369{
1370  return ABS(SR_TO_INT(a))==1;
1371}
1372
1373static BOOLEAN nrzIsZero (number  a, const coeffs)
1374{
1375  return (a==INT_TO_SR(0));
1376}
1377
1378static BOOLEAN nrzIsOne (number a, const coeffs)
1379{
1380  return a==INT_TO_SR(1);
1381}
1382
1383static BOOLEAN nrzIsMOne (number a, const coeffs)
1384{
1385  return a==INT_TO_SR(-1);
1386}
1387
1388static BOOLEAN nrzEqual (number a,number b, const coeffs)
1389{
1390  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
1391    return a==b;
1392  else if (n_Z_IS_SMALL(a) || n_Z_IS_SMALL(b))
1393    return FALSE;
1394  else
1395    return 0 == mpz_cmp((mpz_ptr) a, (mpz_ptr) b);
1396}
1397
1398static BOOLEAN nrzDivBy (number a,number b, const coeffs)
1399{
1400  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
1401  {
1402    return SR_TO_INT(a) %SR_TO_INT(b) ==0;
1403  }
1404  else if (n_Z_IS_SMALL(a))
1405  {
1406    return a==INT_TO_SR(0);
1407  }
1408  else if (n_Z_IS_SMALL(b))
1409  {
1410    return mpz_divisible_ui_p((mpz_ptr)a, (unsigned long)ABS(SR_TO_INT(b))) != 0;
1411  }
1412  else
1413    return mpz_divisible_p((mpz_ptr) a, (mpz_ptr) b) != 0;
1414}
1415
1416static int nrzDivComp(number a, number b, const coeffs r)
1417{
1418  if (nrzDivBy(a, b, r))
1419  {
1420    if (nrzDivBy(b, a, r)) return 2;
1421    return -1;
1422  }
1423  if (nrzDivBy(b, a, r)) return 1;
1424  return 0;
1425}
1426
1427static number nrzDiv (number a,number b, const coeffs)
1428{
1429  assume(SR_TO_INT(b));
1430  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
1431  {
1432    //if (SR_TO_INT(a) % SR_TO_INT(b))
1433    //{
1434    //  WerrorS("1:Division by non divisible element.");
1435    //  WerrorS("Result is without remainder.");
1436    //}
1437    return INT_TO_SR(SR_TO_INT(a)/SR_TO_INT(b));
1438  }
1439  else if (n_Z_IS_SMALL(a))
1440  {
1441    //if (SR_TO_INT(a))
1442    //{
1443    //  WerrorS("2:Division by non divisible element.");
1444    //  WerrorS("Result is without remainder.");
1445    //}
1446    return INT_TO_SR(0);
1447  }
1448  else if (n_Z_IS_SMALL(b))
1449  {
1450    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1451    mpz_t r;
1452    mpz_init(r);
1453    mpz_init(erg);
1454    if (mpz_divmod_ui(erg, r, (mpz_ptr) a, (unsigned long)ABS(SR_TO_INT(b)))) {
1455    //  WerrorS("3:Division by non divisible element.");
1456    //  WerrorS("Result is without remainder.");
1457    }
1458    mpz_clear(r);
1459    if (SR_TO_INT(b)<0)
1460      mpz_neg(erg, erg);
1461    return nrz_short((number) erg);
1462  }
1463  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1464  mpz_init(erg);
1465  mpz_t r;
1466  mpz_init(r);
1467  mpz_tdiv_qr(erg, r, (mpz_ptr) a, (mpz_ptr) b);
1468#if CF_DEBUG
1469  StringSetS("division of");
1470  nrzWrite(a, R);
1471  StringAppendS(" by ");
1472  nrzWrite(b, R);
1473  StringAppendS(" is ");
1474  number du;
1475  nrzWrite(du = (number)erg, R);
1476  StringAppendS(" rest ");
1477  nrzWrite(du = (number)r, R);
1478  char * s = StringEndS();
1479  Print("%s\n", s);
1480  omFree(s);
1481#endif
1482
1483  if (mpz_sgn1(r)!=0)
1484  {
1485    //WerrorS("4:Division by non divisible element.");
1486    //WerrorS("Result is without remainder.");
1487  }
1488  mpz_clear(r);
1489  return nrz_short((number) erg);
1490}
1491
1492static number nrzExactDiv (number a,number b, const coeffs)
1493{
1494  assume(SR_TO_INT(b));
1495  mpz_t aa, bb;
1496  if (n_Z_IS_SMALL(a))
1497    mpz_init_set_si(aa, SR_TO_INT(a));
1498  else
1499    mpz_init_set(aa, (mpz_ptr) a);
1500  if (n_Z_IS_SMALL(b))
1501    mpz_init_set_si(bb, SR_TO_INT(b));
1502  else
1503    mpz_init_set(bb, (mpz_ptr) b);
1504  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1505  mpz_init(erg);
1506  mpz_tdiv_q(erg, (mpz_ptr) aa, (mpz_ptr) bb);
1507  mpz_clear(aa);
1508  mpz_clear(bb);
1509  nrzTest((number)erg);
1510  return (number) erg;
1511}
1512
1513static number nrzIntMod (number a,number b, const coeffs)
1514{
1515  mpz_t aa, bb;
1516  assume(SR_TO_INT(b));
1517  if (n_Z_IS_SMALL(a))
1518    mpz_init_set_si(aa, SR_TO_INT(a));
1519  else
1520    mpz_init_set(aa, (mpz_ptr) a);
1521  if (n_Z_IS_SMALL(b))
1522    mpz_init_set_si(bb, SR_TO_INT(b));
1523  else
1524    mpz_init_set(bb, (mpz_ptr) b);
1525
1526  mpz_t erg;
1527  mpz_init(erg);
1528  mpz_ptr r = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1529  mpz_init(r);
1530  mpz_tdiv_qr(erg, r, (mpz_ptr) aa, (mpz_ptr) bb);
1531  mpz_clear(erg);
1532  mpz_clear(aa);
1533  mpz_clear(bb);
1534
1535  return nrz_short((number) r);
1536}
1537
1538static number  nrzInvers (number c, const coeffs r)
1539{
1540  if (!nrzIsUnit((number) c, r))
1541  {
1542    WerrorS("Non invertible element.");
1543    return (number)NULL;
1544  }
1545  return c; // has to be 1 or -1....
1546}
1547
1548static number nrzNeg (number c, const coeffs)
1549{
1550// nNeg inplace !!!
1551  if (n_Z_IS_SMALL(c))
1552    return INT_TO_SR(-SR_TO_INT(c));
1553  mpz_mul_si((mpz_ptr) c, (mpz_ptr) c, -1);
1554  return c;
1555}
1556
1557static number nrzFarey(number r, number N, const coeffs R)
1558{
1559  number a0 = nrzCopy(N, R);
1560  number b0 = nrzInit(0, R);
1561  number a1 = nrzCopy(r, R);
1562  number b1 = nrzInit(1, R);
1563  number two = nrzInit(2, R);
1564#if 0
1565  PrintS("Farey start with ");
1566  n_Print(r, R);
1567  PrintS(" mod ");
1568  n_Print(N, R);
1569  PrintLn();
1570#endif
1571  while (1)
1572  {
1573    number as = nrzMult(a1, a1, R);
1574    n_InpMult(as, two, R);
1575    if (nrzGreater(N, as, R))
1576    {
1577      nrzDelete(&as, R);
1578      break;
1579    }
1580    nrzDelete(&as, R);
1581    number q = nrzDiv(a0, a1, R);
1582    number t = nrzMult(a1, q, R),
1583           s = nrzSub(a0, t, R);
1584    nrzDelete(&a0, R);
1585    a0 = a1;
1586    a1 = s;
1587    nrzDelete(&t, R);
1588
1589    t = nrzMult(b1, q, R);
1590    s = nrzSub(b0, t, R);
1591    nrzDelete(&b0, R);
1592    b0 = b1;
1593    b1 = s;
1594    nrzDelete(&t, R);
1595    nrzDelete(&q, R);
1596  }
1597  number as = nrzMult(b1, b1, R);
1598  n_InpMult(as, two, R);
1599  nrzDelete(&two, R);
1600  if (nrzGreater(as, N, R))
1601  {
1602    nrzDelete(&a0, R);
1603    nrzDelete(&a1, R);
1604    nrzDelete(&b0, R);
1605    nrzDelete(&b1, R);
1606    nrzDelete(&as, R);
1607    return NULL;
1608  }
1609  nrzDelete(&as, R);
1610  nrzDelete(&a0, R);
1611  nrzDelete(&b0, R);
1612
1613  number a, b, ab;
1614  coeffs Q = nInitChar(n_Q, 0);
1615  nMapFunc f = n_SetMap(R, Q);
1616  a = f(a1, R, Q);
1617  b = f(b1, R, Q);
1618  ab = n_Div(a, b, Q);
1619  n_Delete(&a, Q);
1620  n_Delete(&b, Q);
1621  nKillChar(Q);
1622
1623  nrzDelete(&a1, R);
1624  nrzDelete(&b1, R);
1625  return ab;
1626}
1627
1628static number nrzMapMachineInt(number from, const coeffs /*src*/, const coeffs /*dst*/)
1629{
1630  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1631  mpz_init_set_ui(erg, (unsigned long) from);
1632  return nrz_short((number) erg);
1633}
1634
1635static number nrzMapZp(number from, const coeffs /*src*/, const coeffs /*dst*/)
1636{
1637  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1638  mpz_init_set_si(erg, (long) from);
1639  return nrz_short((number) erg);
1640}
1641
1642static number nrzModNMap(number from, const coeffs /* src */, const coeffs /*dst*/)
1643{
1644  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1645  mpz_init_set(erg, (mpz_ptr) from);
1646  return nrz_short((number) erg);
1647}
1648
1649static number nrzMapQ(number from, const coeffs /* src */, const coeffs dst)
1650{
1651  if (SR_HDL(from) & SR_INT)
1652    return nrzInit(SR_TO_INT(from),dst);
1653  if (from->s!=3)
1654  {
1655    WerrorS("rational in map to integer");
1656    return NULL;
1657  }
1658  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1659  mpz_init_set(erg, from->z);
1660  return nrz_short((number) erg);
1661}
1662
1663static nMapFunc nrzSetMap(const coeffs src, const coeffs /*dst*/)
1664{
1665  /* dst = rintegers */
1666  if (src->rep==n_rep_gmp) //nCoeff_is_Zn(src) || nCoeff_is_Ring_PtoM(src))
1667    return nrzModNMap;
1668
1669  if ((src->rep==n_rep_gap_gmp) && nCoeff_is_Z(src))
1670  {
1671    return ndCopyMap; //nrzCopyMap;
1672  }
1673  if (src->rep==n_rep_gap_rat) /*&& nCoeff_is_Z(src)) Q, bigint*/
1674  {
1675    return nrzMapQ;
1676  }
1677  if ((src->rep==n_rep_int) && nCoeff_is_Ring_2toM(src))
1678  {
1679    return nrzMapMachineInt;
1680  }
1681  if ((src->rep==n_rep_int) && nCoeff_is_Zp(src))
1682  {
1683    return nrzMapZp;
1684  }
1685  return NULL;      // default
1686}
1687
1688
1689/*
1690 * set the exponent (allocate and init tables) (TODO)
1691 */
1692
1693void nrzSetExp(int, coeffs)
1694{
1695}
1696
1697void nrzInitExp(int, coeffs)
1698{
1699}
1700
1701#ifdef LDEBUG
1702BOOLEAN nrzDBTest (number x, const char *f, const int l, const coeffs)
1703{
1704  if (SR_HDL(x) & SR_INT) return TRUE;
1705  if (mpz_sgn1((mpz_ptr) x)==0)
1706  {
1707    Print("gmp-0 %s:%d\n",f,l);
1708    return FALSE;
1709  }
1710  if (mpz_size1((mpz_ptr)x)<=MP_SMALL)
1711  {
1712    long ui=mpz_get_si((mpz_ptr)x);
1713    if ((((ui<<3)>>3)==ui)
1714    && (mpz_cmp_si((mpz_ptr)x,ui)==0))
1715    {
1716      Print("gmp-small %s:%d\n",f,l);
1717      return FALSE;
1718    }
1719  }
1720  return TRUE;
1721}
1722#endif
1723
1724void nrzWrite (number a, const coeffs)
1725{
1726  char *s,*z;
1727  if (a==NULL)
1728  {
1729    StringAppendS("o");
1730  }
1731  else
1732  {
1733    if (n_Z_IS_SMALL(a))
1734    {
1735      StringAppend("%d", SR_TO_INT(a));
1736    }
1737    else
1738    {
1739      int l=mpz_sizeinbase((mpz_ptr) a, 10) + 2;
1740      s=(char*)omAlloc(l);
1741      z=mpz_get_str(s,10,(mpz_ptr) a);
1742      StringAppendS(z);
1743      omFreeSize((ADDRESS)s,l);
1744    }
1745  }
1746}
1747
1748/*2
1749* extracts a long integer from s, returns the rest    (COPY FROM longrat0.cc)
1750*/
1751static const char * nlEatLongC(char *s, mpz_ptr i)
1752{
1753  const char * start=s;
1754
1755  if (*s<'0' || *s>'9')
1756  {
1757    mpz_set_ui(i,1);
1758    return s;
1759  }
1760  while (*s >= '0' && *s <= '9') s++;
1761  if (*s=='\0')
1762  {
1763    mpz_set_str(i,start,10);
1764  }
1765  else
1766  {
1767    char c=*s;
1768    *s='\0';
1769    mpz_set_str(i,start,10);
1770    *s=c;
1771  }
1772  return s;
1773}
1774
1775static const char * nrzRead (const char *s, number *a, const coeffs)
1776{
1777  mpz_ptr z = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1778  {
1779    mpz_init(z);
1780    s = nlEatLongC((char *) s, z);
1781  }
1782  *a = nrz_short((number) z);
1783  return s;
1784}
1785
1786static void nrzCoeffWrite  (const coeffs, BOOLEAN /*details*/)
1787{
1788  //PrintS("// ZZ\n");
1789  PrintS("//   coeff. ring is : Integers\n");
1790}
1791
1792static char* nrzCoeffString(const coeffs)
1793{
1794  return omStrDup("integer");
1795}
1796
1797static CanonicalForm nrzConvSingNFactoryN( number n, BOOLEAN setChar, const coeffs /*r*/ )
1798{
1799  if (setChar) setCharacteristic( 0 );
1800
1801  CanonicalForm term;
1802  if ( n_Z_IS_SMALL(n))
1803  {
1804    term = SR_TO_INT(n);
1805  }
1806  else
1807  {
1808    mpz_t dummy;
1809    mpz_init_set( dummy,n->z );
1810    term = make_cf( dummy );
1811  }
1812  return term;
1813}
1814
1815static number nrzConvFactoryNSingN( const CanonicalForm n, const coeffs r)
1816{
1817  if (n.isImm())
1818  {
1819    return nrzInit(n.intval(),r);
1820  }
1821  else
1822  {
1823    if ( !n.den().isOne() )
1824    {
1825     WerrorS("rational in conversion to integer");
1826     return NULL;
1827    }
1828    mpz_ptr z = (mpz_ptr) omAlloc0Bin(gmp_nrz_bin);
1829    gmp_numerator( n,z);
1830    return nrz_short((number)z);
1831  }
1832}
1833
1834static void nrzMPZ(mpz_t res, number &a, const coeffs)
1835{
1836  if (n_Z_IS_SMALL(a))
1837    mpz_init_set_si(res, SR_TO_INT(a));
1838  else
1839    mpz_init_set(res, (mpz_ptr) a);
1840}
1841
1842static coeffs nrzQuot1(number c, const coeffs r)
1843{
1844    mpz_t dummy;
1845    if(n_Z_IS_SMALL(c))
1846    {
1847      long ch = r->cfInt(c, r);
1848      mpz_init_set_ui(dummy, ch);
1849    }
1850    else
1851    {
1852      mpz_init_set(dummy, (mpz_ptr)c);
1853    }
1854    ZnmInfo info;
1855    info.base = dummy;
1856    info.exp = (unsigned long) 1;
1857    coeffs rr = nInitChar(n_Zn, (void*)&info);
1858    mpz_clear(dummy);
1859    return(rr);
1860}
1861
1862number nlReadFd(const ssiInfo *d, const coeffs);
1863void nlWriteFd(number n, const ssiInfo* d, const coeffs);
1864
1865BOOLEAN nrzInitChar(coeffs r,  void *)
1866{
1867  assume( getCoeffType(r) == n_Z );
1868
1869  r->is_field=FALSE;
1870  r->is_domain=TRUE;
1871  r->rep=n_rep_gap_gmp;
1872
1873  //r->nCoeffIsEqual = ndCoeffIsEqual;
1874  r->cfCoeffString = nrzCoeffString;
1875  //r->cfKillChar = ndKillChar;
1876  r->cfMult  = nrzMult;
1877  r->cfSub   = nrzSub;
1878  r->cfAdd   = nrzAdd;
1879  r->cfDiv   = nrzDiv;
1880  r->cfIntMod= nrzIntMod;
1881  r->cfExactDiv= nrzExactDiv;
1882  r->cfInit = nrzInit;
1883  r->cfInitMPZ = nrzInitMPZ;
1884  r->cfSize  = nrzSize;
1885  r->cfInt  = nrzInt;
1886  //#ifdef HAVE_RINGS
1887  r->cfDivComp = nrzDivComp; // only for ring stuff
1888  r->cfIsUnit = nrzIsUnit; // only for ring stuff
1889  r->cfGetUnit = nrzGetUnit; // only for ring stuff
1890  r->cfAnn = nrzAnn;
1891  r->cfExtGcd = nrzExtGcd; // only for ring stuff
1892  r->cfXExtGcd = nrzXExtGcd; // only for ring stuff
1893  r->cfQuotRem = nrzSmallestQuotRem;
1894  r->cfDivBy = nrzDivBy; // only for ring stuff
1895  //#endif
1896  r->cfInpNeg   = nrzNeg;
1897  r->cfInvers= nrzInvers;
1898  r->cfCopy  = nrzCopy;
1899  r->cfWriteLong = nrzWrite;
1900  r->cfRead = nrzRead;
1901  r->cfGreater = nrzGreater;
1902  r->cfEqual = nrzEqual;
1903  r->cfIsZero = nrzIsZero;
1904  r->cfIsOne = nrzIsOne;
1905  r->cfIsMOne = nrzIsMOne;
1906  r->cfGreaterZero = nrzGreaterZero;
1907  r->cfPower = nrzPower;
1908  r->cfGcd  = nrzGcd;
1909  r->cfLcm  = nrzLcm;
1910  r->cfDelete= nrzDelete;
1911  r->cfSetMap = nrzSetMap;
1912  r->cfCoeffWrite = nrzCoeffWrite;
1913  r->convSingNFactoryN = nrzConvSingNFactoryN;
1914  r->convFactoryNSingN = nrzConvFactoryNSingN;
1915  r->cfMPZ = nrzMPZ;
1916  r->cfFarey = nrzFarey;
1917  r->cfWriteFd=nlWriteFd;
1918  r->cfReadFd=nlReadFd;
1919
1920  r->cfQuot1 = nrzQuot1;
1921  // requires conversion to factory:
1922  r->cfChineseRemainder=nlChineseRemainderSym;
1923  // debug stuff
1924
1925#ifdef LDEBUG
1926  r->cfDBTest=nrzDBTest;
1927#endif
1928
1929  r->ch = 0;
1930  r->has_simple_Alloc=FALSE;
1931  r->has_simple_Inverse=FALSE;
1932  return FALSE;
1933}
1934
1935#elif SI_INTEGER_VARIANT == 1
1936BOOLEAN nrzInitChar(coeffs r,  void *)
1937{
1938  return nlInitChar(r,(void*)1);
1939}
1940#else
1941#error set SI_INTEGER_VARIANT
1942#endif
1943#endif
Note: See TracBrowser for help on using the repository browser.