source: git/kernel/rmodulon.cc @ d3b2eb

spielwiese
Last change on this file since d3b2eb was d3b2eb, checked in by Oliver Wienand <wienand@…>, 17 years ago
polys.cc: debug comment kutil.cc, rmodulo*: silly mistake corrected polys1.cc: pContent update git-svn-id: file:///usr/local/Singular/svn/trunk@10068 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 6.7 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: rmodulon.cc,v 1.5 2007-05-23 07:47:31 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
21#ifdef HAVE_RINGMODN
22
23NATNUMBER nrnModul;
24
25NATNUMBER XSGCD3(NATNUMBER a, NATNUMBER b, NATNUMBER c)
26{
27  while ((a != 0 && b != 0) || (a != 0 && c != 0) || (b != 0 && c != 0))
28  {
29    if (a > b)
30    {
31      if (b > c) a = a % b;       // a > b > c
32      else
33      {
34        if (a > c) a = a % c;     // a > b, c > b, a > c ==> a > c > b
35        else c = c % a;           // c > a > b
36      }
37    }
38    else
39    {
40      if (a > c) b = b % a;       // a > b > c
41      else
42      {
43        if (b > c) b = b % c;     // a > b, c > b, a > c ==> a > c > b
44        else c = c % b;           // c > a > b
45      }
46    }
47  }
48  return a + b + c;
49}
50
51NATNUMBER XSGCD2(NATNUMBER a, NATNUMBER b)
52{
53  NATNUMBER TMP;
54  while (a != 0 && b != 0)
55  {
56     TMP = a % b;
57     a = b;
58     b = TMP;
59  }
60  return a;
61}
62
63/*
64 * Multiply two numbers
65 */
66number nrnMult (number a,number b)
67{
68  if (((NATNUMBER)a == 0) || ((NATNUMBER)b == 0))
69    return (number)0;
70  else
71    return nrnMultM(a,b);
72}
73
74/*
75 * Give the smallest non unit k, such that a * x = k = b * y has a solution
76 */
77number nrnLcm (number a,number b,ring r)
78{
79  NATNUMBER erg = XSGCD2(nrnModul, (NATNUMBER) a) * XSGCD2(nrnModul, (NATNUMBER) b) / XSGCD3(nrnModul, (NATNUMBER) a, (NATNUMBER) b);
80  if (erg == nrnModul) return NULL;   // Schneller als return erg % nrnModul ?
81  return (number) erg;
82}
83
84/*
85 * Give the largest non unit k, such that a = x * k, b = y * k has
86 * a solution.
87 */
88number nrnGcd (number a,number b,ring r)
89{
90  return (number) XSGCD3(nrnModul, (NATNUMBER) a, (NATNUMBER) b);
91}
92
93void nrnPower (number a, int i, number * result)
94{
95  if (i==0)
96  {
97    //npInit(1,result);
98    *(NATNUMBER *)result = 1;
99  }
100  else if (i==1)
101  {
102    *result = a;
103  }
104  else
105  {
106    nrnPower(a,i-1,result);
107    *result = nrnMultM(a,*result);
108  }
109}
110
111/*
112 * create a number from int
113 */
114number nrnInit (int i)
115{
116  long ii = i;
117  while (ii < 0) ii += nrnModul;
118  while ((ii>1) && (ii >= nrnModul)) ii -= nrnModul;
119  return (number) ii;
120}
121
122/*
123 * convert a number to int (-p/2 .. p/2)
124 */
125int nrnInt(number &n)
126{
127  if ((NATNUMBER)n > (nrnModul >>1)) return (int)((NATNUMBER)n - nrnModul);
128  else return (int)((NATNUMBER)n);
129}
130
131number nrnAdd (number a, number b)
132{
133  return nrnAddM(a,b);
134}
135
136number nrnSub (number a, number b)
137{
138  return nrnSubM(a,b);
139}
140
141BOOLEAN nrnIsZero (number  a)
142{
143  return 0 == (NATNUMBER)a;
144}
145
146BOOLEAN nrnIsOne (number a)
147{
148  return 1 == (NATNUMBER)a;
149}
150
151BOOLEAN nrnIsMOne (number a)
152{
153  return nrnModul == (NATNUMBER)a + 1;
154}
155
156BOOLEAN nrnEqual (number a,number b)
157{
158  return nrnEqualM(a,b);
159}
160
161BOOLEAN nrnGreater (number a,number b)
162{
163  nrnDivBy(a, b);
164}
165
166int nrnComp(number a, number b)
167{
168   NATNUMBER bs = XSGCD2((NATNUMBER) b, nrnModul);
169   NATNUMBER as = XSGCD2((NATNUMBER) a, nrnModul);
170   if (bs == as) return 0;
171   if (as % bs == 0) return -1;
172   if (bs % as == 0) return 1;
173   return 2;
174}
175
176BOOLEAN nrnDivBy (number a,number b)
177{
178  return (XSGCD2((NATNUMBER) b / XSGCD2((NATNUMBER) a, (NATNUMBER) b), nrnModul) == 1);
179}
180
181BOOLEAN nrnGreaterZero (number k)
182{
183  return (((NATNUMBER) k) != 0) && ((NATNUMBER) k <= (nrnModul>>1));
184}
185
186//#ifdef HAVE_DIV_MOD
187#if 1 //ifdef HAVE_NTL // in ntl.a
188//extern void XGCD(long& d, long& s, long& t, long a, long b);
189#include <NTL/ZZ.h>
190#ifdef NTL_CLIENT
191NTL_CLIENT
192#endif
193#else
194void XGCD(long& d, long& s, long& t, long a, long b)
195{
196   long  u, v, u0, v0, u1, v1, u2, v2, q, r;
197
198   long aneg = 0, bneg = 0;
199
200   if (a < 0) {
201      a = -a;
202      aneg = 1;
203   }
204
205   if (b < 0) {
206      b = -b;
207      bneg = 1;
208   }
209
210   u1=1; v1=0;
211   u2=0; v2=1;
212   u = a; v = b;
213
214   while (v != 0) {
215      q = u / v;
216      r = u % v;
217      u = v;
218      v = r;
219      u0 = u2;
220      v0 = v2;
221      u2 =  u1 - q*u2;
222      v2 = v1- q*v2;
223      u1 = u0;
224      v1 = v0;
225   }
226
227   if (aneg)
228      u1 = -u1;
229
230   if (bneg)
231      v1 = -v1;
232
233   d = u;
234   s = u1;
235   t = v1;
236}
237#endif
238//#endif
239
240NATNUMBER InvModN(NATNUMBER a)
241{
242   long d, s, t;
243
244   // TODO in chain wird XSGCD2 aufgerufen
245   XGCD(d, s, t, a, nrnModul);
246   assume (d == 1);
247   if (s < 0)
248      return s + nrnModul;
249   else
250      return s;
251}
252
253inline number nrnInversM (number c)
254{
255  // Table !!!
256  NATNUMBER inv;
257  inv = InvModN((NATNUMBER)c);
258  return (number) inv;
259}
260
261number nrnDiv (number a,number b)
262{
263  NATNUMBER tmp = XSGCD3(nrnModul, (NATNUMBER) a, (NATNUMBER) b);
264  a = (number) ((NATNUMBER) a / tmp);
265  b = (number) ((NATNUMBER) b / tmp);
266  if (XSGCD2(nrnModul, (NATNUMBER) b) == 1)
267  {
268    return (number) nrnMult(a, nrnInversM(b));
269  }
270  else
271  {
272    WerrorS("div by zero divisor");
273    return (number)0;
274  }
275}
276
277number nrnIntDiv (number a,number b)
278{
279  if ((NATNUMBER)a==0)
280  {
281    if ((NATNUMBER)b==0)
282      return (number) 1;
283    if ((NATNUMBER)b==1)
284      return (number) 0;
285    return (number) ( nrnModul / (NATNUMBER) b);
286  }
287  else
288  {
289    if ((NATNUMBER)b==0)
290      return (number) 0;
291    return (number) ((NATNUMBER) a / (NATNUMBER) b);
292  }
293}
294
295number  nrnInvers (number c)
296{
297  if (XSGCD2(nrnModul, (NATNUMBER) c) != 1)
298  {
299    WerrorS("division by zero divisor");
300    return (number)0;
301  }
302  return nrnInversM(c);
303}
304
305number nrnNeg (number c)
306{
307  if ((NATNUMBER)c==0) return c;
308  return nrnNegM(c);
309}
310
311nMapFunc nrnSetMap(ring src, ring dst)
312{
313  return NULL;      /* default */
314}
315
316
317/*
318 * set the exponent (allocate and init tables) (TODO)
319 */
320
321void nrnSetExp(int m, ring r)
322{
323  nrnModul = m;
324//  PrintS("Modul: ");
325//  Print("%d\n", nrnModul);
326}
327
328void nrnInitExp(int m, ring r)
329{
330  nrnModul = m;
331
332  if (m < 2)
333  {
334    WarnS("nInitChar failed");
335  }
336}
337
338#ifdef LDEBUG
339BOOLEAN nrnDBTest (number a, char *f, int l)
340{
341  if (((NATNUMBER)a<0) || ((NATNUMBER)a>nrnModul))
342  {
343    return FALSE;
344  }
345  return TRUE;
346}
347#endif
348
349void nrnWrite (number &a)
350{
351  if ((NATNUMBER)a > (nrnModul >>1)) StringAppend("-%d",(int)(nrnModul-((NATNUMBER)a)));
352  else                          StringAppend("%d",(int)((NATNUMBER)a));
353}
354
355char* nrnEati(char *s, int *i)
356{
357
358  if (((*s) >= '0') && ((*s) <= '9'))
359  {
360    (*i) = 0;
361    do
362    {
363      (*i) *= 10;
364      (*i) += *s++ - '0';
365      if ((*i) >= (MAX_INT_VAL / 10)) (*i) = (*i) % nrnModul;
366    }
367    while (((*s) >= '0') && ((*s) <= '9'));
368    if ((*i) >= nrnModul) (*i) = (*i) % nrnModul;
369  }
370  else (*i) = 1;
371  return s;
372}
373
374char * nrnRead (char *s, number *a)
375{
376  int z;
377  int n=1;
378
379  s = nrnEati(s, &z);
380  if ((*s) == '/')
381  {
382    s++;
383    s = nrnEati(s, &n);
384  }
385  if (n == 1)
386    *a = (number)z;
387  else
388      *a = nrnDiv((number)z,(number)n);
389  return s;
390}
391#endif
Note: See TracBrowser for help on using the repository browser.