chiark / gitweb /
56c8756a52d0cfa250ff0edf57ffb4a602fcfcd2
[catacomb-perl] / mp.xs
1 # ---?---
2 #
3 # $Id: mp.xs,v 1.2 2004/04/08 01:36:21 mdw Exp $
4 #
5 # Multiprecision interface
6 #
7 # (c) 2000 Straylight/Edgeware
8 #
9
10 #----- Licensing notice -----------------------------------------------------
11 #
12 # This file is part of the Perl interface to Catacomb.
13 #
14 # Catacomb/Perl is free software; you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation; either version 2 of the License, or
17 # (at your option) any later version.
18
19 # Catacomb/Perl is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 # GNU General Public License for more details.
23
24 # You should have received a copy of the GNU General Public License
25 # along with Catacomb/Perl; if not, write to the Free Software Foundation,
26 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #
28
29 MODULE = Catacomb PACKAGE = Catacomb::MP PREFIX = mp_
30
31 mp *
32 new(me, sv = 0, radix = 0)
33         SV *me
34         SV *sv
35         int radix
36         CODE:
37         RETVAL = sv ? mp_fromsv(sv, "sv", radix, 1) : MP_ZERO;
38         OUTPUT:
39         RETVAL
40
41 mp *
42 mp_copy(x)
43         mp *x
44
45 mp *
46 loadb(me, sv)
47         SV *me
48         SV *sv
49         PREINIT:
50         char *p;
51         STRLEN len;
52         CODE:
53         p = SvPV(sv, len);
54         RETVAL = mp_loadb(MP_NEW, p, len);
55         OUTPUT:
56         RETVAL
57
58 mp *
59 loadl(me, sv)
60         SV *me
61         SV *sv
62         PREINIT:
63         char *p;
64         STRLEN len;
65         CODE:
66         p = SvPV(sv, len);
67         RETVAL = mp_loadl(MP_NEW, p, len);
68         OUTPUT:
69         RETVAL
70
71 int
72 metrics(m)
73         mp *m
74         INTERFACE_MACRO:
75         XSINTERFACE_FUNC
76         XSINTERFACE_FUNC_SETMP
77         INTERFACE:
78         octets bits
79
80 SV *
81 storeb(m, i = -1)
82         mp *m
83         int i
84         PREINIT:
85         size_t sz;
86         CODE:
87         sz = (i < 0) ? mp_octets(m) : i;
88         RETVAL = NEWSV(0, sz ? sz : 1);
89         mp_storeb(m, SvPVX(RETVAL), sz);
90         SvCUR_set(RETVAL, sz);
91         SvPOK_on(RETVAL);
92         OUTPUT:
93         RETVAL
94
95 SV *
96 storel(m, i = -1)
97         mp *m
98         int i
99         PREINIT:
100         size_t sz;
101         CODE:
102         sz = (i < 0) ? mp_octets(m) : i;
103         RETVAL = NEWSV(0, sz ? sz : 1);
104         mp_storel(m, SvPVX(RETVAL), sz);
105         SvCUR_set(RETVAL, sz);
106         SvPOK_on(RETVAL);
107         OUTPUT:
108         RETVAL
109
110 SV *
111 tostring(m, radix = 10)
112         mp *m
113         int radix
114         CODE:
115         RETVAL = NEWSV(0, 0);
116         mp_writesv(m, RETVAL, radix);
117         OUTPUT:
118         RETVAL
119
120 SV *
121 toint(m)
122         mp *m
123         CODE:
124         RETVAL = newSViv(mp_toiv(m));
125         OUTPUT:
126         RETVAL
127
128 SV *
129 DESTROY(m)
130         mp *m
131         CODE:
132         mp_drop(m);
133         XSRETURN_UNDEF;
134
135 mp *
136 unop(a)
137         mp *a
138         C_ARGS:
139         MP_NEW, a
140         INTERFACE_MACRO:
141         XSINTERFACE_FUNC
142         XSINTERFACE_FUNC_SETMP
143         INTERFACE:
144         not sqr sqrt
145
146 mp *
147 neg(a)
148         mp *a
149         CODE:
150         mp_copy(a);
151         RETVAL = mp_split(a);
152         if (RETVAL->v < RETVAL->vl)
153           RETVAL->f ^= MP_NEG;
154         OUTPUT:
155         RETVAL
156
157 mp *
158 mp_factorial(me, x)
159         SV *me
160         IV x
161         C_ARGS:
162         x
163
164 mp *
165 binop(a, b)
166         mp *a
167         mp *b
168         C_ARGS:
169         MP_NEW, a, b
170         INTERFACE_MACRO:
171         XSINTERFACE_FUNC
172         XSINTERFACE_FUNC_SETMP
173         INTERFACE:
174         add sub mul and or xor
175
176 mp *
177 shiftop(a, n)
178         mp *a
179         int n
180         C_ARGS:
181         MP_NEW, a, n
182         INTERFACE_MACRO:
183         XSINTERFACE_FUNC
184         XSINTERFACE_FUNC_SETMP
185         INTERFACE:
186         lsl lsr
187
188 int
189 mp_cmp(a, b)
190         mp *a
191         mp *b
192
193 int
194 mp_eq(a, b)
195         mp *a
196         mp *b
197
198 int
199 jacobi(a, n)
200         mp *a
201         mp *n
202         CODE:
203         if (!MP_LEN(n) || !(n->v[0] & 1))
204           croak("n must be odd in Catacomb::MP::jacobi");
205         RETVAL = mp_jacobi(a, n);
206         OUTPUT:
207         RETVAL
208
209 mp *
210 mp_modsqrt(p, x)
211         mp *p
212         mp *x
213         C_ARGS:
214         MP_NEW, x, p
215
216 void
217 div(a, b)
218         mp *a
219         mp *b
220         PREINIT:
221         mp *q = MP_NEW, *r = MP_NEW;
222         PPCODE:
223         if (MP_EQ(b, MP_ZERO))
224           croak("Divide by zero in Catacomb::MP::div");
225         q = MP_NEW;
226         switch (GIMME_V) {
227           case G_ARRAY:
228             r = MP_NEW;
229             mp_div(&q, &r, a, b);
230             EXTEND(SP, 2);
231             PUSHs(RET_MP(q));
232             PUSHs(RET_MP(r));
233             break;
234           case G_VOID:
235             break;
236           default:
237             mp_div(&q, &r, a, b);
238             EXTEND(SP, 1);
239             PUSHs(RET_MP(q));
240             break;
241         }
242
243 void
244 gcd(a, b)
245         mp *a
246         mp *b
247         PREINIT:
248         mp *g = MP_NEW, *x = MP_NEW, *y = MP_NEW;
249         PPCODE:
250         switch (GIMME_V) {
251           case G_ARRAY:
252             mp_gcd(&g, &x, &y, a, b);
253             EXTEND(SP, 3);
254             PUSHs(RET_MP(g));
255             PUSHs(RET_MP(x));
256             PUSHs(RET_MP(y));
257             break;
258           case G_VOID:
259             break;
260           default:
261             mp_gcd(&g, 0, 0, a, b);
262             EXTEND(SP, 1);
263             PUSHs(RET_MP(g));
264             break;
265         }
266
267 void 
268 odd(m)
269         mp *m
270         PREINIT:
271         mp *t;
272         size_t s;
273         PPCODE:
274         t = mp_odd(MP_NEW, m, &s);
275         EXTEND(SP, 2);
276         PUSHs(RET_MP(t));
277         PUSHs(sv_2mortal(newSViv(s)));
278
279 int
280 smallfactor(x)
281         mp *x
282         CODE:
283         RETVAL = pfilt_smallfactor(x);
284         OUTPUT:
285         RETVAL
286
287 MP_Mont *
288 mont(x)
289         mp *x
290         CODE:
291         if (x->f & MP_NEG)
292           croak("Argument to Catacomb::MP::mont must be positive");
293         if (x->v == x->vl || !(x->v[0] & 1u))
294           croak("Argument to Catacomb::MP::mont must be odd");
295         RETVAL = CREATE(MP_Mont);       
296         mpmont_create(RETVAL, x);
297         OUTPUT:
298         RETVAL
299
300 MP_Barrett *
301 barrett(x)
302         mp *x
303         CODE:
304         if (x->f & MP_NEG)
305           croak("Argument to Catacomb::MP::barrett must be positive");
306         RETVAL = CREATE(mpbarrett);
307         mpbarrett_create(RETVAL, x);
308         OUTPUT:
309         RETVAL
310
311 MP_Prime_Rabin *
312 rabin(x)
313         mp *x
314         CODE:
315         if (x->f & MP_NEG)
316           croak("Argument to Catacomb::MP::rabin must be positive");
317         if (x->v == x->vl || !(x->v[0] & 1u))
318           croak("Argument to Catacomb::MP::rabin must be odd");
319         RETVAL = CREATE(MP_Prime_Rabin);
320         rabin_create(RETVAL, x);
321         OUTPUT:
322         RETVAL
323
324 MODULE = Catacomb PACKAGE = Catacomb::MP::Mont PREFIX = mpmont_
325
326 MP_Mont *
327 new(me, x)
328         SV *me
329         mp *x
330         CODE:
331         if (x->f & MP_NEG)
332           croak("Argument to Catacomb::MP::Mont::new must be positive");
333         if (x->v == x->vl || !(x->v[0] & 1u))
334           croak("Argument to Catacomb::MP::Mont::new must be odd");
335         RETVAL = CREATE(MP_Mont);       
336         mpmont_create(RETVAL, x);
337         OUTPUT:
338         RETVAL
339
340 SV *
341 DESTROY(mm)
342         MP_Mont *mm
343         CODE:
344         mpmont_destroy(mm);
345         DESTROY(mm);
346         XSRETURN_UNDEF;
347
348 mp *
349 mpmont_reduce(mm, x)
350         MP_Mont *mm
351         mp *x
352         C_ARGS:
353         mm, MP_NEW, x
354
355 mp *
356 mpmont_mul(mm, x, y)
357         MP_Mont *mm
358         mp *x
359         mp *y
360         C_ARGS:
361         mm, MP_NEW, x, y
362
363 mp *
364 mpmont_expr(mm, g, x)
365         MP_Mont *mm
366         mp *g
367         mp *x
368         C_ARGS:
369         mm, MP_NEW, g, x
370
371 mp *
372 mpmont_exp(mm, g, x)
373         MP_Mont *mm
374         mp *g
375         mp *x
376         C_ARGS:
377         mm, MP_NEW, g, x
378
379 mp *
380 mpmont_mexpr(mm, ...)
381         MP_Mont *mm
382         PREINIT:
383         mp_expfactor *v;
384         size_t i, j, n;
385         CODE:
386         if (items < 3 || !(items & 1)) {
387           croak("Usage: Catacomb::MP::Mont::mexpr"
388                 "(mm, g_0, x_0, g_1, x_1, ...");
389         }
390         n = (items - 1)/2;
391         v = xmalloc(n * sizeof(mp_expfactor));
392         for (i = 1, j = 0; i < items; i += 2, j++) {
393           v[j].base = mp_fromsv(ST(i), "g_i", 0, 0);
394           v[j].exp = mp_fromsv(ST(i + 1), "x_i", 0, 0);
395         }
396         RETVAL = mpmont_mexpr(mm, MP_NEW, v, n);
397         xfree(v);
398         OUTPUT:
399         RETVAL
400
401 mp *
402 mpmont_mexp(mm, ...)
403         MP_Mont *mm
404         PREINIT:
405         mp_expfactor *v;
406         size_t i, j, n;
407         CODE:
408         if (items < 3 || !(items & 1)) {
409           croak("Usage: Catacomb::MP::Mont::mexp"
410                 "(mm, g_0, x_0, g_1, x_1, ...");
411         }
412         n = (items - 1)/2;
413         v = xmalloc(n * sizeof(mp_expfactor));
414         for (i = 1, j = 0; i < items; i += 2, j++) {
415           v[j].base = mp_fromsv(ST(i), "g_%lu", 0, 0, (unsigned long)i);
416           v[j].exp = mp_fromsv(ST(i + 1), "x_%lu", 0, 0, (unsigned long)i);
417         }
418         RETVAL = mpmont_mexp(mm, MP_NEW, v, n);
419         xfree(v);
420         OUTPUT:
421         RETVAL
422
423 mp *
424 r(mm)
425         MP_Mont *mm
426         CODE:
427         RETVAL = mp_copy(mm->r);
428         OUTPUT:
429         RETVAL
430
431 mp *
432 r2(mm)
433         MP_Mont *mm
434         CODE:
435         RETVAL = mp_copy(mm->r2);
436         OUTPUT:
437         RETVAL
438
439 mp *
440 m(mm)
441         MP_Mont *mm
442         CODE:
443         RETVAL = mp_copy(mm->m);
444         OUTPUT:
445         RETVAL
446
447 MODULE = Catacomb PACKAGE = Catacomb::MP::Barrett PREFIX = mpbarrett_
448
449 MP_Barrett *
450 new(me, x)
451         SV *me
452         mp *x
453         CODE:
454         if (x->f & MP_NEG)
455           croak("Argument to Catacomb::MP::Barrett::new must be positive");
456         RETVAL = CREATE(mpbarrett);
457         mpbarrett_create(RETVAL, x);
458         OUTPUT:
459         RETVAL
460
461 SV *
462 DESTROY(mb)
463         MP_Barrett *mb
464         CODE:
465         mpbarrett_destroy(mb);
466         DESTROY(mb);
467         XSRETURN_UNDEF;
468
469 mp *
470 mpbarrett_reduce(mb, x)
471         MP_Barrett *mb
472         mp *x
473         C_ARGS:
474         mb, MP_NEW, x
475
476 mp *
477 mpbarrett_exp(mb, g, x)
478         MP_Barrett *mb
479         mp *g
480         mp *x
481         C_ARGS:
482         mb, MP_NEW, g, x
483
484 mp *
485 m(mb)
486         MP_Barrett *mb
487         CODE:
488         RETVAL = mp_copy(mb->m);
489         OUTPUT:
490         RETVAL
491
492 MODULE = Catacomb PACKAGE = Catacomb::MP::CRT
493
494 MP_CRT *
495 new(me, ...)
496         SV *me
497         PREINIT:
498         mpcrt_mod *v;
499         size_t n, i;
500         CODE:
501         if (items < 1)
502           croak("Usage: Catacomb::MP::CRT::new(me, n_0, n_1, ...)");
503         n = items - 1;
504         v = xmalloc(n * sizeof(mpcrt_mod));
505         for (i = 0; i < n; i++) {
506           v[i].m = mp_copy(mp_fromsv(ST(i + 1), "n_%lu", 0, 0, 
507                            (unsigned long)i));
508         }
509         RETVAL = CREATE(MP_CRT);
510         mpcrt_create(RETVAL, v, n, 0);
511         OUTPUT:
512         RETVAL
513
514 SV *
515 DESTROY(mc)
516         MP_CRT *mc
517         CODE:
518         mpcrt_destroy(mc);
519         xfree(mc->v);
520         DESTROY(mc);
521         XSRETURN_UNDEF;
522
523 mp *
524 solve(mc, ...)
525         MP_CRT *mc
526         PREINIT:
527         mp **v;
528         size_t n, i;
529         CODE:
530         n = mc->k;
531         if (items - 1 != n)
532           croak("Wrong number of residues for this CRT context");
533         for (i = 0; i < n; i++)
534           v[i] = mp_fromsv(ST(i + 1), "r_%lu", 0, 0, (unsigned long)i);
535         RETVAL = mpcrt_solve(mc, MP_NEW, v);
536         xfree(v);
537         OUTPUT:
538         RETVAL
539
540 #----- That's all, folks ----------------------------------------------------