source: git/libpolys/coeffs/rintegers3.cc @ 9d96b14

spielwiese
Last change on this file since 9d96b14 was 9d96b14, checked in by Hans Schoenemann <hannes@…>, 3 years ago
typo in comment
  • Property mode set to 100644
File size: 26.9 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT: numbers (integers)
6*/
7#ifdef HAVE_RINGS
8#if SI_INTEGER_VARIANT == 3
9
10//make sure that a small number is an immediate integer
11//bascially copied from longrat.cc nlShort3
12//TODO: is there any point in checking 0 first???
13//TODO: it is not clear that this works in 32/64 bit everywhere.
14//      too many hacks.
15#ifdef LDEBUG
16#define nrzTest(A) nrzDBTest(A,__FILE__,__LINE__,NULL)
17BOOLEAN nrzDBTest (number x, const char *f, const int l, const coeffs);
18#else
19#define nrzTest(A)
20#endif
21
22#undef CF_DEBUG
23static inline number nrz_short(number x)
24{
25#if CF_DEBUG
26  StringAppendS("short(");
27  nrzWrite(x, NULL);
28#endif
29  if (mpz_sgn1((mpz_ptr) x)==0)
30  {
31    mpz_clear((mpz_ptr)x);
32    omFreeBin(x, gmp_nrz_bin);
33#if CF_DEBUG
34    StringAppendS(")=0");
35#endif
36    return INT_TO_SR(0);
37  }
38  if (mpz_size1((mpz_ptr)x)<=MP_SMALL)
39  {
40    long ui=mpz_get_si((mpz_ptr)x);
41    if ((((ui<<3)>>3)==ui)
42    && (mpz_cmp_si((mpz_ptr)x,ui)==0))
43    {
44      mpz_clear((mpz_ptr)x);
45      omFreeBin(x, gmp_nrz_bin);
46#if CF_DEBUG
47    StringAppendS(")=imm");
48#endif
49      return INT_TO_SR(ui);
50    }
51  }
52#if CF_DEBUG
53  StringAppendS(")");
54#endif
55  return x;
56}
57
58
59static int nrzSize(number a, const coeffs)
60{
61  if (a==INT_TO_SR(0)) return 0;
62  if (n_Z_IS_SMALL(a)) return 1;
63  return ((mpz_ptr)a)->_mp_alloc;
64}
65
66
67/*
68 * Multiply two numbers
69 * check for 0, 1, -1 maybe
70 */
71#if CF_DEBUG
72number _nrzMult(number, number, const coeffs);
73number nrzMult(number a, number b, const coeffs R)
74{
75  StringSetS("Mult: ");
76  nrzWrite(a, R);
77  StringAppendS(" by ");
78  nrzWrite(b, R);
79  number c = _nrzMult(a, b, R);
80  StringAppendS(" is ");
81  nrzWrite(c, R);
82  char * s = StringEndS();
83  Print("%s\n", s);
84  omFree(s);
85  return c;
86}
87number _nrzMult (number a, number b, const coeffs R)
88#else
89number nrzMult (number a, number b, const coeffs R)
90#endif
91{
92  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
93  {
94  //from longrat.cc
95    if (SR_TO_INT(a)==0)
96      return a;
97    if (SR_TO_INT(b)==0)
98      return b;
99    long r=(long)((unsigned long)(SR_HDL(a)-1L))*((unsigned long)(SR_HDL(b)>>1));
100    if ((r/(SR_HDL(b)>>1))==(SR_HDL(a)-1L))
101    {
102      number u=((number) ((r>>1)+SR_INT));
103    //  if (((((long)SR_HDL(u))<<1)>>1)==SR_HDL(u)) return (u);
104      return nrzInit(SR_HDL(u)>>2, R);
105    }
106    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
107    mpz_init(erg);
108    mpz_set_si(erg, SR_TO_INT(a));
109    mpz_mul_si(erg, erg, SR_TO_INT(b));
110    nrzTest((number)erg);
111    return (number) erg;
112  }
113  else if (n_Z_IS_SMALL(a))
114  {
115    if (SR_TO_INT(a)==0)
116      return a;
117    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
118    mpz_init_set(erg, (mpz_ptr) b);
119    mpz_mul_si(erg, erg, SR_TO_INT(a));
120    nrzTest((number)erg);
121    return (number) erg;
122  }
123  else if (n_Z_IS_SMALL(b))
124  {
125    if (SR_TO_INT(b)==0)
126      return b;
127    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
128    mpz_init_set(erg, (mpz_ptr) a);
129    mpz_mul_si(erg, erg, SR_TO_INT(b));
130    nrzTest((number)erg);
131    return (number) erg;
132  }
133  else
134  {
135    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
136    mpz_init(erg);
137    mpz_mul(erg, (mpz_ptr) a, (mpz_ptr) b);
138    nrzTest((number)erg);
139    return (number) erg;
140  }
141}
142
143
144static long int_gcd(long a, long b)
145{
146  long r;
147  a = ABS(a);
148  b = ABS(b);
149  if (!a) return b;
150  if (!b) return a;
151  do
152  {
153    r = a % b;
154    a = b;
155    b = r;
156  } while (b);
157  return ABS(a); // % in c doeas not imply a signn
158                 // it would be unlikely to see a negative here
159                 // but who knows
160}
161
162/*
163 * Give the smallest non unit k, such that a * x = k = b * y has a solution
164 */
165static number nrzLcm (number a, number b, const coeffs R)
166{
167  #ifdef CF_DEBUG
168  PrintS("nrzLcm\n");
169  #endif
170  mpz_ptr erg;
171  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
172  {
173    long g = int_gcd(SR_TO_INT(a), SR_TO_INT(b));
174    return nrzMult(a, INT_TO_SR(SR_TO_INT(b)/g), R);
175  }
176  else
177  {
178    erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
179    if (n_Z_IS_SMALL(a))
180    {
181      mpz_init_set(erg, (mpz_ptr) b);
182      unsigned long g = mpz_gcd_ui(NULL, erg, (unsigned long) ABS(SR_TO_INT(a)));
183      mpz_mul_si(erg, erg, SR_TO_INT(a)/g);
184    }
185    else if (n_Z_IS_SMALL(b))
186    {
187      mpz_init_set(erg, (mpz_ptr) a);
188      unsigned long g = mpz_gcd_ui(NULL, erg, (unsigned long) ABS(SR_TO_INT(b)));
189      mpz_mul_si(erg, erg, SR_TO_INT(b)/g);
190    }
191    else
192    {
193      mpz_init(erg);
194      mpz_lcm(erg, (mpz_ptr) a, (mpz_ptr) b);
195    }
196  }
197  return (number) erg;
198}
199
200static number nrzCopy(number a, const coeffs)
201{
202  if (n_Z_IS_SMALL(a)) return a;
203  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
204  mpz_init_set(erg, (mpz_ptr) a);
205  return (number) erg;
206}
207
208/*
209 * Give the largest non unit k, such that a = x * k, b = y * k has
210 * a solution.
211 */
212static number nrzGcd (number a,number b,const coeffs R)
213{
214  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
215  {
216    long g = int_gcd(SR_TO_INT(a), SR_TO_INT(b));
217    return INT_TO_SR(g);
218  }
219  else if (n_Z_IS_SMALL(a))
220  {
221    if (a==INT_TO_SR(0))
222      return nrzCopy(b, R);
223    unsigned long g = mpz_gcd_ui(NULL, (mpz_ptr)b, (unsigned long) ABS(SR_TO_INT(a)));
224    return INT_TO_SR( g);
225  }
226  else if (n_Z_IS_SMALL(b))
227  {
228    if (b==INT_TO_SR(0))
229      return nrzCopy(a, R);
230    unsigned long g = mpz_gcd_ui(NULL, (mpz_ptr)a, (unsigned long) ABS(SR_TO_INT(b)));
231    return INT_TO_SR(g);
232  }
233  else
234  {
235    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
236    mpz_init(erg);
237    mpz_gcd(erg, (mpz_ptr) a, (mpz_ptr) b);
238    return (number) erg;
239  }
240}
241
242/*
243 * Give the largest non unit k, such that a = x * k, b = y * k has
244 * a solution and r, s, s.t. k = s*a + t*b
245 */
246static long int_extgcd(long a, long b, long * u, long* x, long * v, long* y)
247{
248  long q, r;
249  if (!a)
250  {
251    *u = 0;
252    *v = 1;
253    *x = -1;
254    *y = 0;
255    return b;
256  }
257  if (!b)
258  {
259    *u = 1;
260    *v = 0;
261    *x = 0;
262    *y = 1;
263    return a;
264  }
265  *u=1;
266  *v=0;
267  *x=0;
268  *y=1;
269  do
270  {
271    q = a/b;
272    r = a%b;
273    assume (q*b+r == a);
274    a = b;
275    b = r;
276
277    r = -(*v)*q+(*u);
278    (*u) =(*v);
279    (*v) = r;
280
281    r = -(*y)*q+(*x);
282    (*x) = (*y);
283    (*y) = r;
284  } while (b);
285
286  return a;
287}
288
289static number  nrzExtGcd (number a, number b, number *s, number *t, const coeffs)
290{
291  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
292  {
293    long u, v, x, y;
294    long g = int_extgcd(SR_TO_INT(a), SR_TO_INT(b), &u, &v, &x, &y);
295    *s = INT_TO_SR(u);
296    *t = INT_TO_SR(v);
297    return INT_TO_SR(g);
298  }
299  else
300  {
301    mpz_t aa, bb;
302    if (n_Z_IS_SMALL(a))
303    {
304      mpz_init_set_si(aa, SR_TO_INT(a));
305    }
306    else
307    {
308      mpz_init_set(aa, (mpz_ptr) a);
309    }
310    if (n_Z_IS_SMALL(b))
311    {
312      mpz_init_set_si(bb, SR_TO_INT(b));
313    }
314    else
315    {
316      mpz_init_set(bb, (mpz_ptr) b);
317    }
318    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
319    mpz_ptr bs = (mpz_ptr) omAllocBin(gmp_nrz_bin);
320    mpz_ptr bt = (mpz_ptr) omAllocBin(gmp_nrz_bin);
321    mpz_init(erg);
322    mpz_init(bs);
323    mpz_init(bt);
324    mpz_gcdext(erg, bs, bt, aa, bb);
325    *s = nrz_short((number) bs);
326    *t = nrz_short((number) bt);
327    mpz_clear(aa);
328    mpz_clear(bb);
329    return nrz_short((number) erg);
330  }
331}
332#if CF_DEBUG
333static number _nrzXExtGcd(number, number, number *, number *, number *, number *, const coeffs);
334static number nrzXExtGcd(number a, number b, number *x, number * y, number * u, number * v, const coeffs R)
335{
336  char * s;
337  StringSetS("XExtGcd: ");
338  nrzWrite(a, R);
339  StringAppendS(" by ");
340  nrzWrite(b, R);
341  number c = _nrzXExtGcd(a, b, x, y, u, v, R);
342  StringAppendS(" is ");
343  nrzWrite(c, R);
344  StringAppendS("[[");
345  nrzWrite(*x, R);
346  StringAppendS(", ");
347  nrzWrite(*y, R);
348  StringAppendS("], ");
349  nrzWrite(*u, R);
350  StringAppendS(", ");
351  nrzWrite(*v, R);
352  s=StringEndS();
353  Print("%s]]\n", s);
354  omFree(s);
355  return c;
356}
357static number  _nrzXExtGcd (number a, number b, number *s, number *t, number *u, number *v, const coeffs )
358#else
359static number  nrzXExtGcd (number a, number b, number *s, number *t, number *u, number *v, const coeffs )
360#endif
361{
362  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
363  {
364    long uu, vv, x, y;
365    long g = int_extgcd(SR_TO_INT(a), SR_TO_INT(b), &uu, &vv, &x, &y);
366    *s = INT_TO_SR(uu);
367    *t = INT_TO_SR(vv);
368    *u = INT_TO_SR(x);
369    *v = INT_TO_SR(y);
370    return INT_TO_SR(g);
371  }
372  else
373  {
374    mpz_t aa, bb;
375    if (n_Z_IS_SMALL(a))
376    {
377      mpz_init_set_si(aa, SR_TO_INT(a));
378    }
379    else
380    {
381      mpz_init_set(aa, (mpz_ptr) a);
382    }
383    if (n_Z_IS_SMALL(b))
384    {
385      mpz_init_set_si(bb, SR_TO_INT(b));
386    }
387    else
388    {
389      mpz_init_set(bb, (mpz_ptr) b);
390    }
391    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
392    mpz_ptr bs = (mpz_ptr) omAllocBin(gmp_nrz_bin);
393    mpz_ptr bt = (mpz_ptr) omAllocBin(gmp_nrz_bin);
394    mpz_init(erg);
395    mpz_init(bs);
396    mpz_init(bt);
397
398    mpz_gcdext(erg, bs, bt, aa, bb);
399
400    mpz_ptr bu = (mpz_ptr) omAllocBin(gmp_nrz_bin);
401    mpz_ptr bv = (mpz_ptr) omAllocBin(gmp_nrz_bin);
402
403    mpz_init_set(bu, (mpz_ptr) bb);
404    mpz_init_set(bv, (mpz_ptr) aa);
405
406    mpz_clear(aa);
407    mpz_clear(bb);
408    assume(mpz_cmp_si(erg, 0));
409
410    mpz_div(bu, bu, erg);
411    mpz_div(bv, bv, erg);
412
413    mpz_mul_si(bu, bu, -1);
414    *u = nrz_short((number) bu);
415    *v = nrz_short((number) bv);
416
417    *s = nrz_short((number) bs);
418    *t = nrz_short((number) bt);
419    return nrz_short((number) erg);
420  }
421}
422#if CF_DEBUG
423static number _nrzQuotRem(number, number, number *, const coeffs);
424static number nrzQuotRem(number a, number b, number * r, const coeffs R)
425{
426  StringSetS("QuotRem: ");
427  nrzWrite(a, R);
428  StringAppendS(" by ");
429  nrzWrite(b, R);
430  number c = _nrzQuotRem(a, b, r, R);
431  StringAppendS(" is ");
432  nrzWrite(c, R);
433  if (r) {
434    StringAppendS("+R(");
435    nrzWrite(*r, R);
436    StringAppendS(")");
437  }
438  char * s = StringEndS();
439  Print("%s\n", s);
440  omFree(s);
441  return c;
442}
443static number _nrzQuotRem (number a, number b, number * r, const coeffs )
444#else
445static number nrzQuotRem (number a, number b, number * r, const coeffs )
446#endif
447{
448  assume(SR_TO_INT(b));
449  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
450  {
451    if (r)
452      *r = INT_TO_SR(SR_TO_INT(a) % SR_TO_INT(b));
453    return INT_TO_SR(SR_TO_INT(a)/SR_TO_INT(b));
454  }
455  else if (n_Z_IS_SMALL(a))
456  {
457    //a is small, b is not, so q=0, r=a
458    if (r)
459      *r = a;
460    return INT_TO_SR(0);
461  }
462  else if (n_Z_IS_SMALL(b))
463  {
464    unsigned long rr;
465    mpz_ptr qq = (mpz_ptr) omAllocBin(gmp_nrz_bin);
466    mpz_init(qq);
467    mpz_t rrr;
468    mpz_init(rrr);
469    rr = mpz_divmod_ui(qq, rrr, (mpz_ptr) a, (unsigned long)ABS(SR_TO_INT(b)));
470    mpz_clear(rrr);
471
472    if (r)
473      *r = INT_TO_SR(rr);
474    if (SR_TO_INT(b)<0)
475    {
476      mpz_mul_si(qq, qq, -1);
477    }
478    return nrz_short((number)qq);
479  }
480  mpz_ptr qq = (mpz_ptr) omAllocBin(gmp_nrz_bin),
481             rr = (mpz_ptr) omAllocBin(gmp_nrz_bin);
482  mpz_init(qq);
483  mpz_init(rr);
484  mpz_divmod(qq, rr, (mpz_ptr)a, (mpz_ptr)b);
485  if (r)
486    *r = (number) rr;
487  else
488  {
489    mpz_clear(rr);
490  }
491  nrzTest((number)qq);
492  return (number) qq;
493}
494
495static void nrzPower (number a, int i, number * result, const coeffs)
496{
497  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
498  mpz_init(erg);
499  mpz_t aa;
500  if (n_Z_IS_SMALL(a))
501    mpz_init_set_si(aa, SR_TO_INT(a));
502  else
503    mpz_init_set(aa, (mpz_ptr) a);
504  mpz_pow_ui(erg, aa, i);
505  *result = nrz_short((number) erg);
506}
507
508/*
509 * create a number from int
510 * TODO: do not create an mpz if not necessary
511 */
512number nrzInit (long i, const coeffs)
513{
514  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
515  mpz_init_set_si(erg, i);
516  return nrz_short((number) erg);
517}
518
519static number nrzInitMPZ(mpz_t m, const coeffs)
520{
521  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
522  mpz_init_set(erg, m);
523  return nrz_short((number) erg);
524}
525
526
527static void nrzDelete(number *a, const coeffs)
528{
529  if (*a == NULL) return;
530  if (n_Z_IS_SMALL(*a)==0)
531  {
532    mpz_clear((mpz_ptr) *a);
533    omFreeBin((ADDRESS) *a, gmp_nrz_bin);
534  }
535  *a = NULL;
536}
537
538/*
539 * convert a number to int
540 */
541static long nrzInt(number &n, const coeffs)
542{
543  if (n_Z_IS_SMALL(n)) return SR_TO_INT(n);
544  return mpz_get_si( (mpz_ptr)n);
545}
546#if CF_DEBUG
547static number _nrzAdd(number, number, const coeffs);
548static number nrzAdd(number a, number b, const coeffs R)
549{
550  StringSetS("Add: ");
551  nrzWrite(a, R);
552  StringAppendS(" to ");
553  nrzWrite(b, R);
554  number c = _nrzAdd(a, b, R);
555  StringAppendS(" is ");
556  nrzWrite(c, R);
557  char * s = StringEndS();
558  Print("%s\n", s);
559  omFree(s);
560  return c;
561}
562static number _nrzAdd (number a, number b, const coeffs )
563#else
564static number nrzAdd (number a, number b, const coeffs )
565#endif
566{
567  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
568  {
569    long c = SR_TO_INT(a) + SR_TO_INT(b);
570    if (INT_IS_SMALL(c))
571      return INT_TO_SR(c);
572    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
573    mpz_init_set_si(erg, c);
574
575    nrzTest((number)erg);
576    return (number) erg;
577  }
578  else if (n_Z_IS_SMALL(a))
579  {
580    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
581    mpz_init(erg);
582    if (SR_TO_INT(a)>0)
583      mpz_add_ui(erg, (mpz_ptr) b, (unsigned long)SR_TO_INT(a));
584    else
585      mpz_sub_ui(erg, (mpz_ptr) b, (unsigned long)-(SR_TO_INT(a)));
586    return nrz_short((number) erg);
587  }
588  else if (n_Z_IS_SMALL(b))
589  {
590    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
591    mpz_init(erg);
592    if (SR_TO_INT(b)>0)
593      mpz_add_ui(erg, (mpz_ptr) a, (unsigned long)SR_TO_INT(b));
594    else
595      mpz_sub_ui(erg, (mpz_ptr) a, (unsigned long)-(SR_TO_INT(b)));
596    return nrz_short((number) erg);
597  }
598  else
599  {
600    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
601    mpz_init(erg);
602    mpz_add(erg, (mpz_ptr) a, (mpz_ptr) b);
603    return nrz_short((number) erg);
604  }
605}
606
607static number nrzSub (number a, number b,  const coeffs )
608{
609  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
610  {
611    long c = SR_TO_INT(a) - SR_TO_INT(b);
612    if (INT_IS_SMALL(c))
613      return INT_TO_SR(c);
614    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
615    mpz_init_set_si(erg, c);
616    nrzTest((number)erg);
617    return (number) erg;
618  }
619  else if (n_Z_IS_SMALL(a))
620  {
621    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
622    mpz_init(erg);
623
624    if (SR_TO_INT(a)>0)
625      mpz_ui_sub(erg, (unsigned long)SR_TO_INT(a), (mpz_ptr) b);
626    else
627    {
628      mpz_add_ui(erg, (mpz_ptr) b, (unsigned long)-SR_TO_INT(a));
629      mpz_neg(erg, erg);
630    }
631    return nrz_short((number) erg);
632  }
633  else if (n_Z_IS_SMALL(b))
634  {
635    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
636    mpz_init(erg);
637    if (SR_TO_INT(b)>0)
638      mpz_sub_ui(erg, (mpz_ptr) a, (unsigned long)SR_TO_INT(b));
639    else
640      mpz_add_ui(erg, (mpz_ptr) a, (unsigned long)-SR_TO_INT(b));
641    return nrz_short((number) erg);
642  }
643  else
644  {
645    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
646    mpz_init(erg);
647    mpz_sub(erg, (mpz_ptr) a, (mpz_ptr) b);
648    return nrz_short((number) erg);
649  }
650}
651
652static BOOLEAN nrzGreater (number a,number b, const coeffs)
653{
654  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
655    return ((long)a)>((long)b);
656  else if (n_Z_IS_SMALL(a))
657    return 0 > mpz_cmp_si((mpz_ptr)b,SR_TO_INT(a));
658  else if (n_Z_IS_SMALL(b))
659    return 0 < mpz_cmp_si((mpz_ptr)a,SR_TO_INT(b));
660  return 0 < mpz_cmp((mpz_ptr) a, (mpz_ptr) b);
661}
662
663static BOOLEAN nrzGreaterZero (number k, const coeffs C)
664{
665  return nrzGreater(k, INT_TO_SR(0), C);
666}
667
668static number  nrzGetUnit (number n, const coeffs r)
669{
670  if (nrzGreaterZero(n, r))
671    return INT_TO_SR(1);
672  /*else*/
673    return INT_TO_SR(-1);
674}
675
676static number nrzAnn(number n, const coeffs)
677{
678  if (SR_TO_INT(n))  // in Z: the annihilator of !=0 is 0
679    return INT_TO_SR(0);
680  else
681    return INT_TO_SR(1);
682}
683
684static BOOLEAN nrzIsUnit (number a, const coeffs)
685{
686  return ABS(SR_TO_INT(a))==1;
687}
688
689static BOOLEAN nrzIsZero (number  a, const coeffs)
690{
691  return (a==INT_TO_SR(0));
692}
693
694static BOOLEAN nrzIsOne (number a, const coeffs)
695{
696  return a==INT_TO_SR(1);
697}
698
699static BOOLEAN nrzIsMOne (number a, const coeffs)
700{
701  return a==INT_TO_SR(-1);
702}
703
704static BOOLEAN nrzEqual (number a,number b, const coeffs)
705{
706  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
707    return a==b;
708  else if (n_Z_IS_SMALL(a) || n_Z_IS_SMALL(b))
709    return FALSE;
710  else
711    return 0 == mpz_cmp((mpz_ptr) a, (mpz_ptr) b);
712}
713
714static BOOLEAN nrzDivBy (number a,number b, const coeffs)
715{
716  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
717  {
718    return SR_TO_INT(a) %SR_TO_INT(b) ==0;
719  }
720  else if (n_Z_IS_SMALL(a))
721  {
722    return a==INT_TO_SR(0);
723  }
724  else if (n_Z_IS_SMALL(b))
725  {
726    return mpz_divisible_ui_p((mpz_ptr)a, (unsigned long)ABS(SR_TO_INT(b))) != 0;
727  }
728  else
729    return mpz_divisible_p((mpz_ptr) a, (mpz_ptr) b) != 0;
730}
731
732static int nrzDivComp(number a, number b, const coeffs r)
733{
734  if (nrzDivBy(a, b, r))
735  {
736    if (nrzDivBy(b, a, r)) return 2;
737    return -1;
738  }
739  if (nrzDivBy(b, a, r)) return 1;
740  return 0;
741}
742
743static number nrzDiv (number a,number b, const coeffs)
744{
745  assume(SR_TO_INT(b));
746  if (n_Z_IS_SMALL(a) && n_Z_IS_SMALL(b))
747  {
748    //if (SR_TO_INT(a) % SR_TO_INT(b))
749    //{
750    //  WerrorS("1:Division by non divisible element.");
751    //  WerrorS("Result is without remainder.");
752    //}
753    return INT_TO_SR(SR_TO_INT(a)/SR_TO_INT(b));
754  }
755  else if (n_Z_IS_SMALL(a))
756  {
757    //if (SR_TO_INT(a))
758    //{
759    //  WerrorS("2:Division by non divisible element.");
760    //  WerrorS("Result is without remainder.");
761    //}
762    return INT_TO_SR(0);
763  }
764  else if (n_Z_IS_SMALL(b))
765  {
766    mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
767    mpz_t r;
768    mpz_init(r);
769    mpz_init(erg);
770    if (mpz_divmod_ui(erg, r, (mpz_ptr) a, (unsigned long)ABS(SR_TO_INT(b)))) {
771    //  WerrorS("3:Division by non divisible element.");
772    //  WerrorS("Result is without remainder.");
773    }
774    mpz_clear(r);
775    if (SR_TO_INT(b)<0)
776      mpz_neg(erg, erg);
777    return nrz_short((number) erg);
778  }
779  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
780  mpz_init(erg);
781  mpz_t r;
782  mpz_init(r);
783  mpz_tdiv_qr(erg, r, (mpz_ptr) a, (mpz_ptr) b);
784#if CF_DEBUG
785  StringSetS("division of");
786  nrzWrite(a, R);
787  StringAppendS(" by ");
788  nrzWrite(b, R);
789  StringAppendS(" is ");
790  number du;
791  nrzWrite(du = (number)erg, R);
792  StringAppendS(" rest ");
793  nrzWrite(du = (number)r, R);
794  char * s = StringEndS();
795  Print("%s\n", s);
796  omFree(s);
797#endif
798
799  if (mpz_sgn1(r)!=0)
800  {
801    //WerrorS("4:Division by non divisible element.");
802    //WerrorS("Result is without remainder.");
803  }
804  mpz_clear(r);
805  return nrz_short((number) erg);
806}
807
808static number nrzExactDiv (number a,number b, const coeffs)
809{
810  assume(SR_TO_INT(b));
811  mpz_t aa, bb;
812  if (n_Z_IS_SMALL(a))
813    mpz_init_set_si(aa, SR_TO_INT(a));
814  else
815    mpz_init_set(aa, (mpz_ptr) a);
816  if (n_Z_IS_SMALL(b))
817    mpz_init_set_si(bb, SR_TO_INT(b));
818  else
819    mpz_init_set(bb, (mpz_ptr) b);
820  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
821  mpz_init(erg);
822  mpz_tdiv_q(erg, (mpz_ptr) aa, (mpz_ptr) bb);
823  mpz_clear(aa);
824  mpz_clear(bb);
825  nrzTest((number)erg);
826  return (number) erg;
827}
828
829static number nrzIntMod (number a,number b, const coeffs)
830{
831  mpz_t aa, bb;
832  assume(SR_TO_INT(b));
833  if (n_Z_IS_SMALL(a))
834    mpz_init_set_si(aa, SR_TO_INT(a));
835  else
836    mpz_init_set(aa, (mpz_ptr) a);
837  if (n_Z_IS_SMALL(b))
838    mpz_init_set_si(bb, SR_TO_INT(b));
839  else
840    mpz_init_set(bb, (mpz_ptr) b);
841
842  mpz_t erg;
843  mpz_init(erg);
844  mpz_ptr r = (mpz_ptr) omAllocBin(gmp_nrz_bin);
845  mpz_init(r);
846  mpz_tdiv_qr(erg, r, (mpz_ptr) aa, (mpz_ptr) bb);
847  mpz_clear(erg);
848  mpz_clear(aa);
849  mpz_clear(bb);
850
851  return nrz_short((number) r);
852}
853
854static number  nrzInvers (number c, const coeffs r)
855{
856  if (!nrzIsUnit((number) c, r))
857  {
858    WerrorS("Non invertible element.");
859    return (number)NULL;
860  }
861  return c; // has to be 1 or -1....
862}
863
864static number nrzNeg (number c, const coeffs)
865{
866// nNeg inplace !!!
867  if (n_Z_IS_SMALL(c))
868    return INT_TO_SR(-SR_TO_INT(c));
869  mpz_mul_si((mpz_ptr) c, (mpz_ptr) c, -1);
870  return c;
871}
872
873static number nrzFarey(number r, number N, const coeffs R)
874{
875  number a0 = nrzCopy(N, R);
876  number b0 = nrzInit(0, R);
877  number a1 = nrzCopy(r, R);
878  number b1 = nrzInit(1, R);
879  number two = nrzInit(2, R);
880#if 0
881  PrintS("Farey start with ");
882  n_Print(r, R);
883  PrintS(" mod ");
884  n_Print(N, R);
885  PrintLn();
886#endif
887  while (1)
888  {
889    number as = nrzMult(a1, a1, R);
890    n_InpMult(as, two, R);
891    if (nrzGreater(N, as, R))
892    {
893      nrzDelete(&as, R);
894      break;
895    }
896    nrzDelete(&as, R);
897    number q = nrzDiv(a0, a1, R);
898    number t = nrzMult(a1, q, R),
899           s = nrzSub(a0, t, R);
900    nrzDelete(&a0, R);
901    a0 = a1;
902    a1 = s;
903    nrzDelete(&t, R);
904
905    t = nrzMult(b1, q, R);
906    s = nrzSub(b0, t, R);
907    nrzDelete(&b0, R);
908    b0 = b1;
909    b1 = s;
910    nrzDelete(&t, R);
911    nrzDelete(&q, R);
912  }
913  number as = nrzMult(b1, b1, R);
914  n_InpMult(as, two, R);
915  nrzDelete(&two, R);
916  if (nrzGreater(as, N, R))
917  {
918    nrzDelete(&a0, R);
919    nrzDelete(&a1, R);
920    nrzDelete(&b0, R);
921    nrzDelete(&b1, R);
922    nrzDelete(&as, R);
923    return NULL;
924  }
925  nrzDelete(&as, R);
926  nrzDelete(&a0, R);
927  nrzDelete(&b0, R);
928
929  number a, b, ab;
930  coeffs Q = nInitChar(n_Q, 0);
931  nMapFunc f = n_SetMap(R, Q);
932  a = f(a1, R, Q);
933  b = f(b1, R, Q);
934  ab = n_Div(a, b, Q);
935  n_Delete(&a, Q);
936  n_Delete(&b, Q);
937  nKillChar(Q);
938
939  nrzDelete(&a1, R);
940  nrzDelete(&b1, R);
941  return ab;
942}
943
944static number nrzMapMachineInt(number from, const coeffs /*src*/, const coeffs /*dst*/)
945{
946  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
947  mpz_init_set_ui(erg, (unsigned long) from);
948  return nrz_short((number) erg);
949}
950
951static number nrzMapZp(number from, const coeffs /*src*/, const coeffs /*dst*/)
952{
953  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
954  mpz_init_set_si(erg, (long) from);
955  return nrz_short((number) erg);
956}
957
958static number nrzModNMap(number from, const coeffs /* src */, const coeffs /*dst*/)
959{
960  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
961  mpz_init_set(erg, (mpz_ptr) from);
962  return nrz_short((number) erg);
963}
964
965static number nrzMapQ(number from, const coeffs /* src */, const coeffs dst)
966{
967  if (SR_HDL(from) & SR_INT)
968    return nrzInit(SR_TO_INT(from),dst);
969  if (from->s!=3)
970  {
971    WerrorS("rational in map to integer");
972    return NULL;
973  }
974  mpz_ptr erg = (mpz_ptr) omAllocBin(gmp_nrz_bin);
975  mpz_init_set(erg, from->z);
976  return nrz_short((number) erg);
977}
978
979static nMapFunc nrzSetMap(const coeffs src, const coeffs /*dst*/)
980{
981  /* dst = rintegers */
982  if (src->rep==n_rep_gmp) //nCoeff_is_Zn(src) || nCoeff_is_Ring_PtoM(src))
983    return nrzModNMap;
984
985  if ((src->rep==n_rep_gap_gmp) && nCoeff_is_Z(src))
986  {
987    return ndCopyMap; //nrzCopyMap;
988  }
989  if (src->rep==n_rep_gap_rat) /*&& nCoeff_is_Z(src)) Q, bigint*/
990  {
991    return nrzMapQ;
992  }
993  if ((src->rep==n_rep_int) && nCoeff_is_Ring_2toM(src))
994  {
995    return nrzMapMachineInt;
996  }
997  if ((src->rep==n_rep_int) && nCoeff_is_Zp(src))
998  {
999    return nrzMapZp;
1000  }
1001  return NULL;      // default
1002}
1003
1004
1005/*
1006 * set the exponent (allocate and init tables) (TODO)
1007 */
1008
1009void nrzSetExp(int, coeffs)
1010{
1011}
1012
1013void nrzInitExp(int, coeffs)
1014{
1015}
1016
1017#ifdef LDEBUG
1018BOOLEAN nrzDBTest (number x, const char *f, const int l, const coeffs)
1019{
1020  if (SR_HDL(x) & SR_INT) return TRUE;
1021  if (mpz_sgn1((mpz_ptr) x)==0)
1022  {
1023    Print("gmp-0 %s:%d\n",f,l);
1024    return FALSE;
1025  }
1026  if (mpz_size1((mpz_ptr)x)<=MP_SMALL)
1027  {
1028    long ui=mpz_get_si((mpz_ptr)x);
1029    if ((((ui<<3)>>3)==ui)
1030    && (mpz_cmp_si((mpz_ptr)x,ui)==0))
1031    {
1032      Print("gmp-small %s:%d\n",f,l);
1033      return FALSE;
1034    }
1035  }
1036  return TRUE;
1037}
1038#endif
1039
1040void nrzWrite (number a, const coeffs)
1041{
1042  char *s,*z;
1043  if (a==NULL)
1044  {
1045    StringAppendS("o");
1046  }
1047  else
1048  {
1049    if (n_Z_IS_SMALL(a))
1050    {
1051      StringAppend("%d", SR_TO_INT(a));
1052    }
1053    else
1054    {
1055      int l=mpz_sizeinbase((mpz_ptr) a, 10) + 2;
1056      s=(char*)omAlloc(l);
1057      z=mpz_get_str(s,10,(mpz_ptr) a);
1058      StringAppendS(z);
1059      omFreeSize((ADDRESS)s,l);
1060    }
1061  }
1062}
1063
1064/*2
1065* extracts a long integer from s, returns the rest    (COPY FROM longrat0.cc)
1066*/
1067static const char * nlEatLongC(char *s, mpz_ptr i)
1068{
1069  const char * start=s;
1070
1071  if (*s<'0' || *s>'9')
1072  {
1073    mpz_set_ui(i,1);
1074    return s;
1075  }
1076  while (*s >= '0' && *s <= '9') s++;
1077  if (*s=='\0')
1078  {
1079    mpz_set_str(i,start,10);
1080  }
1081  else
1082  {
1083    char c=*s;
1084    *s='\0';
1085    mpz_set_str(i,start,10);
1086    *s=c;
1087  }
1088  return s;
1089}
1090
1091static const char * nrzRead (const char *s, number *a, const coeffs)
1092{
1093  mpz_ptr z = (mpz_ptr) omAllocBin(gmp_nrz_bin);
1094  {
1095    mpz_init(z);
1096    s = nlEatLongC((char *) s, z);
1097  }
1098  *a = nrz_short((number) z);
1099  return s;
1100}
1101
1102static CanonicalForm nrzConvSingNFactoryN( number n, BOOLEAN setChar, const coeffs /*r*/ )
1103{
1104  if (setChar) setCharacteristic( 0 );
1105
1106  CanonicalForm term;
1107  if ( n_Z_IS_SMALL(n))
1108  {
1109    term = SR_TO_INT(n);
1110  }
1111  else
1112  {
1113    mpz_t dummy;
1114    mpz_init_set( dummy,n->z );
1115    term = make_cf( dummy );
1116  }
1117  return term;
1118}
1119
1120static number nrzConvFactoryNSingN( const CanonicalForm n, const coeffs r)
1121{
1122  if (n.isImm())
1123  {
1124    return nrzInit(n.intval(),r);
1125  }
1126  else
1127  {
1128    if ( !n.den().isOne() )
1129    {
1130     WerrorS("rational in conversion to integer");
1131     return NULL;
1132    }
1133    mpz_ptr z = (mpz_ptr) omAlloc0Bin(gmp_nrz_bin);
1134    gmp_numerator( n,z);
1135    return nrz_short((number)z);
1136  }
1137}
1138
1139static void nrzMPZ(mpz_t res, number &a, const coeffs)
1140{
1141  if (n_Z_IS_SMALL(a))
1142    mpz_init_set_si(res, SR_TO_INT(a));
1143  else
1144    mpz_init_set(res, (mpz_ptr) a);
1145}
1146
1147static coeffs nrzQuot1(number c, const coeffs r)
1148{
1149    mpz_t dummy;
1150    if(n_Z_IS_SMALL(c))
1151    {
1152      long ch = r->cfInt(c, r);
1153      mpz_init_set_ui(dummy, ch);
1154    }
1155    else
1156    {
1157      mpz_init_set(dummy, (mpz_ptr)c);
1158    }
1159    ZnmInfo info;
1160    info.base = dummy;
1161    info.exp = (unsigned long) 1;
1162    coeffs rr = nInitChar(n_Zn, (void*)&info);
1163    mpz_clear(dummy);
1164    return(rr);
1165}
1166
1167number nlReadFd(const ssiInfo *d, const coeffs);
1168void nlWriteFd(number n, const ssiInfo* d, const coeffs);
1169
1170BOOLEAN nrzInitChar(coeffs r,  void *)
1171{
1172  assume( getCoeffType(r) == n_Z );
1173
1174  r->is_field=FALSE;
1175  r->is_domain=TRUE;
1176  r->rep=n_rep_gap_gmp;
1177
1178  //r->nCoeffIsEqual = ndCoeffIsEqual;
1179  r->cfCoeffName = nrzCoeffName;
1180  //r->cfKillChar = ndKillChar;
1181  r->cfMult  = nrzMult;
1182  r->cfSub   = nrzSub;
1183  r->cfAdd   = nrzAdd;
1184  r->cfDiv   = nrzDiv;
1185  r->cfIntMod= nrzIntMod;
1186  r->cfExactDiv= nrzExactDiv;
1187  r->cfInit = nrzInit;
1188  r->cfInitMPZ = nrzInitMPZ;
1189  r->cfSize  = nrzSize;
1190  r->cfInt  = nrzInt;
1191  //#ifdef HAVE_RINGS
1192  r->cfDivComp = nrzDivComp; // only for ring stuff
1193  r->cfIsUnit = nrzIsUnit; // only for ring stuff
1194  r->cfGetUnit = nrzGetUnit; // only for ring stuff
1195  r->cfAnn = nrzAnn;
1196  r->cfExtGcd = nrzExtGcd; // only for ring stuff
1197  r->cfXExtGcd = nrzXExtGcd; // only for ring stuff
1198  r->cfEucNorm = nrzEucNorm;
1199  r->cfQuotRem = nrzSmallestQuotRem;
1200  r->cfDivBy = nrzDivBy; // only for ring stuff
1201  //#endif
1202  r->cfInpNeg   = nrzNeg;
1203  r->cfInvers= nrzInvers;
1204  r->cfCopy  = nrzCopy;
1205  r->cfWriteLong = nrzWrite;
1206  r->cfRead = nrzRead;
1207  r->cfGreater = nrzGreater;
1208  r->cfEqual = nrzEqual;
1209  r->cfIsZero = nrzIsZero;
1210  r->cfIsOne = nrzIsOne;
1211  r->cfIsMOne = nrzIsMOne;
1212  r->cfGreaterZero = nrzGreaterZero;
1213  r->cfPower = nrzPower;
1214  r->cfGcd  = nrzGcd;
1215  r->cfLcm  = nrzLcm;
1216  r->cfDelete= nrzDelete;
1217  r->cfSetMap = nrzSetMap;
1218  r->convSingNFactoryN = nrzConvSingNFactoryN;
1219  r->convFactoryNSingN = nrzConvFactoryNSingN;
1220  r->cfMPZ = nrzMPZ;
1221  r->cfFarey = nrzFarey;
1222  r->cfWriteFd=nlWriteFd;
1223  r->cfReadFd=nlReadFd;
1224
1225  r->cfQuot1 = nrzQuot1;
1226  // requires conversion to factory:
1227  r->cfChineseRemainder=nlChineseRemainderSym;
1228  // debug stuff
1229
1230#ifdef LDEBUG
1231  r->cfDBTest=nrzDBTest;
1232#endif
1233
1234  r->ch = 0;
1235  r->has_simple_Alloc=FALSE;
1236  r->has_simple_Inverse=FALSE;
1237  return FALSE;
1238}
1239#endif
1240#endif
Note: See TracBrowser for help on using the repository browser.