source: git/libpolys/coeffs/rintegers3.cc @ 003f71

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