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