source: git/kernel/rmodulon.cc @ befecbc

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