source: git/libpolys/coeffs/rintegers3.cc @ f7e671

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