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