source: git/kernel/rmodulon.cc @ 3901ebf

spielwiese
Last change on this file since 3901ebf was 31e857, checked in by Oliver Wienand <wienand@…>, 16 years ago
rmodulon.cc: gmp_bin git-svn-id: file:///usr/local/Singular/svn/trunk@10546 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 9.8 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: rmodulon.cc,v 1.14 2008-02-01 10:31:44 wienand Exp $ */
5/*
6* ABSTRACT: numbers modulo n
7*/
8
9#include <string.h>
10#include "mod2.h"
11#include <mylimits.h>
12#include "structs.h"
13#include "febase.h"
14#include "omalloc.h"
15#include "numbers.h"
16#include "longrat.h"
17#include "mpr_complex.h"
18#include "ring.h"
19#include "rmodulon.h"
20#include "gmp.h"
21
22#ifdef HAVE_RINGMODN
23
24typedef MP_INT *int_number;
25omBin gmp_bin = omGetSpecBin(sizeof(MP_INT));
26
27int_number nrnModul = NULL;
28int_number nrnMinusOne = NULL;
29unsigned long nrnExponent = 0;
30unsigned long long nrnBase = 0;
31
32/*
33 * create a number from int
34 */
35number nrnInit (int i)
36{
37  int_number erg = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
38  mpz_init_set_si(erg, i);
39  mpz_mod(erg, erg, nrnModul);
40  return (number) erg;
41}
42
43void nrnDelete(number *a, const ring r)
44{
45  mpz_clear((int_number) *a);
46  omFreeBin((ADDRESS) *a, gmp_bin);
47}
48
49/*
50 * convert a number to int (-p/2 .. p/2)
51 */
52int nrnInt(number &n)
53{
54  return (int) mpz_get_si( (int_number) &n);
55}
56
57/*
58 * Multiply two numbers
59 */
60number nrnMult (number a, number b)
61{
62  int_number erg = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
63  mpz_init(erg);
64  mpz_mul(erg, (int_number) a, (int_number) b);
65  mpz_mod(erg, erg, nrnModul);
66  return (number) erg;
67}
68
69void nrnPower (number a, int i, number * result)
70{
71  int_number erg = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
72  mpz_init(erg);
73  mpz_powm_ui(erg, (int_number) a, i, nrnModul);
74  *result = (number) erg;
75}
76
77number nrnAdd (number a, number b)
78{
79  int_number erg = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
80  mpz_init(erg);
81  mpz_add(erg, (int_number) a, (int_number) b);
82  mpz_mod(erg, erg, nrnModul);
83  return (number) erg;
84}
85
86number nrnSub (number a, number b)
87{
88  int_number erg = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
89  mpz_init(erg);
90  mpz_sub(erg, (int_number) a, (int_number) b);
91  mpz_mod(erg, erg, nrnModul);
92  return (number) erg;
93}
94
95number nrnNeg (number c)
96{
97  int_number erg = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
98  mpz_init(erg);
99  mpz_sub(erg, nrnModul, (int_number) c);
100  return (number) erg;
101}
102
103number  nrnInvers (number c)
104{
105  int_number erg = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
106  mpz_init(erg);
107  mpz_invert(erg, (int_number) c, nrnModul);
108  return (number) erg;
109}
110
111/*
112 * Give the smallest non unit k, such that a * x = k = b * y has a solution
113 * TODO: lcm(gcd,gcd) besser als gcd(lcm) ?
114 */
115number nrnLcm (number a,number b,ring r)
116{
117  number erg = nrnGcd(NULL, a, NULL);
118  number tmp = nrnGcd(NULL, b, NULL);
119  mpz_lcm((int_number) erg, (int_number) erg, (int_number) tmp);
120  nrnDelete(&tmp, NULL);
121  return (number) erg;
122}
123
124/*
125 * Give the largest non unit k, such that a = x * k, b = y * k has
126 * a solution.
127 */
128number nrnGcd (number a,number b,ring r)
129{
130  if ((a == NULL) && (b == NULL)) return nrnInit(0);
131  int_number erg = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
132  mpz_init_set(erg, nrnModul);
133  if (a != NULL) mpz_gcd(erg, erg, (int_number) a);
134  if (b != NULL) mpz_gcd(erg, erg, (int_number) b);
135  return (number) erg;
136}
137
138/* Not needed any more, but may have room for improvement
139number nrnGcd3 (number a,number b, number c,ring r)
140{
141  int_number erg = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
142  mpz_init(erg);
143  if (a == NULL) a = (number) nrnModul;
144  if (b == NULL) b = (number) nrnModul;
145  if (c == NULL) c = (number) nrnModul;
146  mpz_gcd(erg, (int_number) a, (int_number) b);
147  mpz_gcd(erg, erg, (int_number) c);
148  mpz_gcd(erg, erg, nrnModul);
149  return (number) erg;
150}
151*/
152
153/*
154 * Give the largest non unit k, such that a = x * k, b = y * k has
155 * a solution and r, s, s.t. k = s*a + t*b
156 */
157number  nrnExtGcd (number a, number b, number *s, number *t)
158{
159  int_number erg = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
160  int_number bs = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
161  int_number bt = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
162  mpz_init(erg);
163  mpz_init(bs);
164  mpz_init(bt);
165  mpz_gcdext(erg, bs, bt, (int_number) a, (int_number) b);
166  mpz_mod(bs, bs, nrnModul);
167  mpz_mod(bt, bt, nrnModul);
168  *s = (number) bs;
169  *t = (number) bt;
170  return (number) erg;
171}
172
173BOOLEAN nrnIsZero (number  a)
174{
175  return 0 == mpz_cmpabs_ui((int_number) a, 0);
176}
177
178BOOLEAN nrnIsOne (number a)
179{
180  return 0 == mpz_cmp_si((int_number) a, 1);
181}
182
183BOOLEAN nrnIsMOne (number a)
184{
185  return 0 == mpz_cmp((int_number) a, nrnMinusOne);
186}
187
188BOOLEAN nrnEqual (number a,number b)
189{
190  return 0 == mpz_cmp((int_number) a, (int_number) b);
191}
192
193BOOLEAN nrnGreater (number a,number b)
194{
195  return 0 < mpz_cmp((int_number) a, (int_number) b);
196}
197
198BOOLEAN nrnGreaterZero (number k)
199{
200  return 0 <= mpz_cmp_si((int_number) k, 0);
201}
202
203BOOLEAN nrnIsUnit (number a)
204{
205  number tmp = nrnGcd(a, (number) nrnModul, NULL);
206  bool res = nrnIsOne(tmp);
207  nrnDelete(&tmp, NULL);
208  return res;
209}
210
211number  nrnGetUnit (number k)
212{
213  int_number unit = (int_number) nrnGcd(k, 0, currRing);
214  mpz_tdiv_q(unit, (int_number) k, unit);
215  int_number gcd = (int_number) nrnGcd((number) unit, 0, currRing);
216  if (!nrnIsOne((number) gcd))
217  {
218    int_number ctmp;
219    // tmp := unit^2
220    int_number tmp = (int_number) nrnMult((number) unit,(number) unit);
221    // gcd_new := gcd(tmp, 0)
222    int_number gcd_new = (int_number) nrnGcd((number) tmp, 0, currRing);
223    while (!nrnEqual((number) gcd_new,(number) gcd))
224    {
225      // gcd := gcd_new
226      ctmp = gcd;
227      gcd = gcd_new;
228      gcd_new = ctmp;
229      // tmp := tmp * unit
230      mpz_mul(tmp, tmp, unit);
231      mpz_mod(tmp, tmp, nrnModul);
232      // gcd_new := gcd(tmp, 0)
233      mpz_gcd(gcd_new, tmp, nrnModul);
234    }
235    // unit := unit + nrnModul / gcd_new
236    mpz_tdiv_q(tmp, nrnModul, gcd_new);
237    mpz_add(unit, unit, tmp);
238    mpz_mod(unit, unit, nrnModul);
239    nrnDelete((number*) &gcd_new, NULL);
240    nrnDelete((number*) &tmp, NULL);
241  }
242  nrnDelete((number*) &gcd, NULL);
243  return (number) unit;
244}
245
246BOOLEAN nrnDivBy (number a,number b)
247{
248  number bs = nrnGcd(a, b, NULL);
249  mpz_tdiv_q((int_number) bs, (int_number) b, (int_number) bs);
250  bool res = nrnIsUnit(bs);
251  nrnDelete(&bs, NULL);
252  return res;
253}
254
255int nrnComp(number a, number b)
256{
257  if (nrnEqual(a, b)) return 0;
258  if (mpz_divisible_p((int_number) a, (int_number) b)) return -1;
259  if (mpz_divisible_p((int_number) b, (int_number) a)) return 1;
260  return 2;
261}
262
263number nrnDiv (number a,number b)
264{
265  if (a == NULL) a = (number) nrnModul;
266  int_number erg = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
267  mpz_init(erg);
268  if (mpz_divisible_p((int_number) a, (int_number) b))
269  {
270    mpz_divexact(erg, (int_number) a, (int_number) b);
271    return (number) erg;
272  }
273  else
274  {
275    int_number gcd = (int_number) nrnGcd(a, b, NULL);
276    mpz_divexact(erg, (int_number) b, gcd);
277    if (!nrnIsUnit((number) erg))
278    {
279      WarnS("Division not possible, even by cancelling zero divisors.");
280      WarnS("Result is zero.");
281      mpz_set_ui(erg, 0);
282      nrnDelete((number*) &gcd, NULL);
283      return (number) erg;
284    }
285    // a / gcd(a,b) * [b / gcd (a,b)]^(-1)
286    int_number tmp = (int_number) nrnInvers((number) erg);
287    mpz_divexact(erg, (int_number) a, gcd);
288    mpz_mul(erg, erg, tmp);
289    nrnDelete((number*) &gcd, NULL);
290    nrnDelete((number*) &tmp, NULL);
291    mpz_mod(erg, erg, nrnModul);
292    return (number) erg;
293  }
294}
295
296number nrnIntDiv (number a,number b)
297{
298  int_number erg = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
299  mpz_init(erg);
300  if (a == NULL) a = (number) nrnModul;
301  mpz_tdiv_q(erg, (int_number) a, (int_number) b);
302  return (number) erg;
303}
304
305nMapFunc nrnSetMap(ring src, ring dst)
306{
307  return NULL;      /* default */
308}
309
310/*
311 * set the exponent (allocate and init tables) (TODO)
312 */
313
314void mpz_set_ull(int_number res, unsigned long long xx)
315{
316  unsigned long h = xx >> 32;
317  mpz_set_ui (res, h);
318  mpz_mul_2exp (res, res, 32);
319  mpz_add_ui (res, res, (unsigned long) xx);
320}
321
322void nrnSetExp(int m, ring r)
323{
324  if ((nrnBase == r->ringflaga) && (nrnExponent == r->ringflagb)) return;
325  nrnBase = r->ringflaga;
326  nrnExponent = r->ringflagb;
327  if (nrnModul != NULL)
328  {
329    nrnDelete((number*) &nrnModul, NULL);
330    nrnDelete((number*) &nrnMinusOne, NULL);
331  }
332  nrnModul = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
333  mpz_init(nrnModul);
334  mpz_set_ull(nrnModul, nrnBase);
335  mpz_pow_ui(nrnModul, nrnModul, nrnExponent);
336
337  nrnMinusOne = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
338  mpz_init(nrnMinusOne);
339  mpz_sub_ui(nrnMinusOne, nrnModul, 1);
340}
341
342void nrnInitExp(int m, ring r)
343{
344  nrnSetExp(m, r);
345  if (mpz_cmp_ui(nrnModul,2) <= 0)
346  {
347    WarnS("nInitChar failed");
348  }
349}
350
351#ifdef LDEBUG
352BOOLEAN nrnDBTest (number a, char *f, int l)
353{
354  if ( (mpz_cmp_si((int_number) a, 0) < 0) || (mpz_cmp((int_number) a, nrnModul) > 0) )
355  {
356    return FALSE;
357  }
358  return TRUE;
359}
360#endif
361
362void nrnWrite (number &a)
363{
364  char *s,*z;
365  if (a==NULL)
366  {
367    StringAppendS("o");
368  }
369  else
370  {
371    int l=mpz_sizeinbase((int_number) a, 10);
372    if (a->s<2) l=si_max(l,mpz_sizeinbase((int_number) a,10));
373    l+=2;
374    s=(char*)omAlloc(l);
375    z=mpz_get_str(s,10,(int_number) a);
376    StringAppendS(z);
377    omFreeSize((ADDRESS)s,l);
378  }
379}
380
381/*2
382* extracts a long integer from s, returns the rest    (COPY FROM longrat0.cc)
383*/
384char * nlCPEatLongC(char *s, MP_INT *i)
385{
386  char * start=s;
387  if (!(*s >= '0' && *s <= '9'))
388  {
389    mpz_init_set_si(i, 1);
390    return s;
391  }
392  mpz_init(i);
393  while (*s >= '0' && *s <= '9') s++;
394  if (*s=='\0')
395  {
396    mpz_set_str(i,start,10);
397  }
398  else
399  {
400    char c=*s;
401    *s='\0';
402    mpz_set_str(i,start,10);
403    *s=c;
404  }
405  return s;
406}
407
408char * nrnRead (char *s, number *a)
409{
410  int_number z = (int_number) omAllocBin(gmp_bin); // evtl. spaeter mit bin
411  {
412    s = nlCPEatLongC(s, z);
413  }
414  *a = (number) z;
415  return s;
416}
417#endif
Note: See TracBrowser for help on using the repository browser.