source: git/kernel/rmodulon.cc @ 8e1c4e

spielwiese
Last change on this file since 8e1c4e was 8e1c4e, checked in by Oliver Wienand <wienand@…>, 16 years ago
kutil.cc: extendedspoly fehler pp_Mult_nn__T.cc: nIsZero rmodulon.cc: gcd/lcm ringspezifisch, umsortiert git-svn-id: file:///usr/local/Singular/svn/trunk@10545 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 9.3 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: rmodulon.cc,v 1.13 2008-01-31 16:13:55 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;
25
26int_number nrnModul = NULL;
27int_number nrnMinusOne = NULL;
28unsigned long nrnExponent = 0;
29unsigned long long nrnBase = 0;
30
31
32/*
33 * create a number from int
34 */
35number nrnInit (int i)
36{
37  int_number erg = (int_number) omAlloc(sizeof(MP_INT)); // 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  omFree((ADDRESS) *a);
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) omAlloc(sizeof(MP_INT)); // 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) omAlloc(sizeof(MP_INT)); // 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) omAlloc(sizeof(MP_INT)); // 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) omAlloc(sizeof(MP_INT)); // 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) omAlloc(sizeof(MP_INT)); // 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) omAlloc(sizeof(MP_INT)); // 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  int_number erg = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
131  mpz_init(erg);
132  if (a == NULL) a = (number) nrnModul;
133  if (b == NULL) b = (number) nrnModul;
134  mpz_gcd(erg, (int_number) a, (int_number) b);
135  mpz_gcd(erg, erg, nrnModul);
136  return (number) erg;
137}
138
139/* Not needed any more, but may have room for improvement
140number nrnGcd3 (number a,number b, number c,ring r)
141{
142  int_number erg = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
143  mpz_init(erg);
144  if (a == NULL) a = (number) nrnModul;
145  if (b == NULL) b = (number) nrnModul;
146  if (c == NULL) c = (number) nrnModul;
147  mpz_gcd(erg, (int_number) a, (int_number) b);
148  mpz_gcd(erg, erg, (int_number) c);
149  mpz_gcd(erg, erg, nrnModul);
150  return (number) erg;
151}
152*/
153
154/*
155 * Give the largest non unit k, such that a = x * k, b = y * k has
156 * a solution and r, s, s.t. k = s*a + t*b
157 */
158number  nrnExtGcd (number a, number b, number *s, number *t)
159{
160  int_number erg = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
161  int_number bs = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
162  int_number bt = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
163  mpz_init(erg);
164  mpz_init(bs);
165  mpz_init(bt);
166  mpz_gcdext(erg, bs, bt, (int_number) a, (int_number) b);
167  mpz_mod(bs, bs, nrnModul);
168  mpz_mod(bt, bt, nrnModul);
169  *s = (number) bs;
170  *t = (number) bt;
171  return (number) erg;
172}
173
174BOOLEAN nrnIsZero (number  a)
175{
176  return 0 == mpz_cmpabs_ui((int_number) a, 0);
177}
178
179BOOLEAN nrnIsOne (number a)
180{
181  return 0 == mpz_cmp_si((int_number) a, 1);
182}
183
184BOOLEAN nrnIsMOne (number a)
185{
186  return 0 == mpz_cmp((int_number) a, nrnMinusOne);
187}
188
189BOOLEAN nrnEqual (number a,number b)
190{
191  return 0 == mpz_cmp((int_number) a, (int_number) b);
192}
193
194BOOLEAN nrnGreater (number a,number b)
195{
196  return 0 < mpz_cmp((int_number) a, (int_number) b);
197}
198
199BOOLEAN nrnGreaterZero (number k)
200{
201  return 0 <= mpz_cmp_si((int_number) k, 0);
202}
203
204BOOLEAN nrnIsUnit (number a)
205{
206  number tmp = nrnGcd(a, (number) nrnModul, NULL);
207  bool res = nrnIsOne(tmp);
208  nrnDelete(&tmp, NULL);
209  return res;
210}
211
212number  nrnGetUnit (number k)
213{
214  number unit = nrnIntDiv(k, nrnGcd(k, 0, currRing));
215  number gcd = nrnGcd(unit, 0, currRing);
216  if (!nrnIsOne(gcd))
217  {
218    number tmp = nrnMult(unit, unit);
219    number gcd_new = nrnGcd(tmp, 0, currRing);
220    while (!nrnEqual(gcd_new, gcd))
221    {
222      nrnDelete(&gcd, NULL);
223      gcd = gcd_new;
224      tmp = nrnMult(tmp, unit);
225      gcd_new = nrnGcd(tmp, 0, currRing);
226    }
227    unit = nrnAdd(unit, nrnIntDiv(0, gcd_new));
228    nrnDelete(&gcd_new, NULL);
229  }
230  nrnDelete(&gcd, NULL);
231  return unit;
232}
233
234BOOLEAN nrnDivBy (number a,number b)
235{
236  number bs = nrnIntDiv(b, nrnGcd(a, b, NULL));
237  bool res = nrnIsUnit(bs);
238  nrnDelete(&bs, NULL);
239  return res;
240}
241
242int nrnComp(number a, number b)
243{
244  if (nrnEqual(a, b)) return 0;
245  if (nrnDivBy(a, b)) return -1;
246  if (nrnDivBy(b, a)) return 1;
247  return 2;
248}
249
250number nrnDiv (number a,number b)
251{
252  if (a == NULL) a = (number) nrnModul;
253  int_number erg = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
254  mpz_init(erg);
255  if (mpz_divisible_p((int_number) a, (int_number) b))
256  {
257    mpz_divexact(erg, (int_number) a, (int_number) b);
258    return (number) erg;
259  }
260  else
261  {
262    int_number gcd = (int_number) nrnGcd(a, b, NULL);
263    int_number erg = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
264    mpz_init(erg);
265    mpz_divexact(erg, (int_number) b, gcd);
266    if (!nrnIsUnit((number) erg))
267    {
268      WarnS("Division not possible, even by cancelling zero divisors.");
269      WarnS("Result is zero.");
270      mpz_set_ui(erg, 0);
271      mpz_clear(gcd);
272      omFree(gcd);
273      return (number) erg;
274    }
275    int_number tmp = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
276    mpz_init(tmp);
277    tmp = (int_number) nrnInvers((number) erg);
278    mpz_divexact(erg, (int_number) a, gcd);
279    mpz_mul(erg, erg, tmp);
280    mpz_clear(gcd);
281    omFree(gcd);
282    mpz_clear(tmp);
283    omFree(tmp);
284    mpz_mod(erg, erg, nrnModul);
285    return (number) erg;
286  }
287}
288
289number nrnIntDiv (number a,number b)
290{
291  int_number erg = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
292  mpz_init(erg);
293  if (a == NULL) a = (number) nrnModul;
294  mpz_tdiv_q(erg, (int_number) a, (int_number) b);
295  return (number) erg;
296}
297
298nMapFunc nrnSetMap(ring src, ring dst)
299{
300  return NULL;      /* default */
301}
302
303/*
304 * set the exponent (allocate and init tables) (TODO)
305 */
306
307void mpz_set_ull(int_number res, unsigned long long xx)
308{
309  unsigned long h = xx >> 32;
310  mpz_set_ui (res, h);
311  mpz_mul_2exp (res, res, 32);
312  mpz_add_ui (res, res, (unsigned long) xx);
313}
314
315void nrnSetExp(int m, ring r)
316{
317  if ((nrnBase == r->ringflaga) && (nrnExponent == r->ringflagb)) return;
318  nrnBase = r->ringflaga;
319  nrnExponent = r->ringflagb;
320  if (nrnModul != NULL)
321  {
322    mpz_clear(nrnModul);
323    omFree(nrnModul);
324    mpz_clear(nrnMinusOne);
325    omFree(nrnMinusOne);
326  }
327  nrnModul = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
328  mpz_init(nrnModul);
329  mpz_set_ull(nrnModul, nrnBase);
330  mpz_pow_ui(nrnModul, nrnModul, nrnExponent);
331
332  nrnMinusOne = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
333  mpz_init(nrnMinusOne);
334  mpz_sub_ui(nrnMinusOne, nrnModul, 1);
335}
336
337void nrnInitExp(int m, ring r)
338{
339  nrnSetExp(m, r);
340  if (mpz_cmp_ui(nrnModul,2) <= 0)
341  {
342    WarnS("nInitChar failed");
343  }
344}
345
346#ifdef LDEBUG
347BOOLEAN nrnDBTest (number a, char *f, int l)
348{
349  if ( (mpz_cmp_si((int_number) a, 0) < 0) || (mpz_cmp((int_number) a, nrnModul) > 0) )
350  {
351    return FALSE;
352  }
353  return TRUE;
354}
355#endif
356
357void nrnWrite (number &a)
358{
359  char *s,*z;
360  if (a==NULL)
361  {
362    StringAppendS("o");
363  }
364  else
365  {
366    int l=mpz_sizeinbase((int_number) a, 10);
367    if (a->s<2) l=si_max(l,mpz_sizeinbase((int_number) a,10));
368    l+=2;
369    s=(char*)omAlloc(l);
370    z=mpz_get_str(s,10,(int_number) a);
371    StringAppendS(z);
372    omFreeSize((ADDRESS)s,l);
373  }
374}
375
376/*2
377* extracts a long integer from s, returns the rest    (COPY FROM longrat0.cc)
378*/
379char * nlCPEatLongC(char *s, MP_INT *i)
380{
381  char * start=s;
382  if (!(*s >= '0' && *s <= '9'))
383  {
384    mpz_init_set_si(i, 1);
385    return s;
386  }
387  mpz_init(i);
388  while (*s >= '0' && *s <= '9') s++;
389  if (*s=='\0')
390  {
391    mpz_set_str(i,start,10);
392  }
393  else
394  {
395    char c=*s;
396    *s='\0';
397    mpz_set_str(i,start,10);
398    *s=c;
399  }
400  return s;
401}
402
403char * nrnRead (char *s, number *a)
404{
405  int_number z = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
406  {
407    s = nlCPEatLongC(s, z);
408  }
409  *a = (number) z;
410  return s;
411}
412#endif
Note: See TracBrowser for help on using the repository browser.