Various changes. Kinda in the middle of it here, but it seems to work.
[catacomb-perl] / mp.xs
CommitLineData
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 29MODULE = Catacomb PACKAGE = Catacomb::MP PREFIX = mp_
30
31mp *
32new(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
42mp *
a1a90aaf 43copy(x)
660b443c 44 mp *x
a1a90aaf 45 CODE:
46 RETVAL = MP_COPY(x);
47 OUTPUT:
48 RETVAL
660b443c 49
50mp *
51loadb(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
63mp *
64loadl(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
76int
77metrics(m)
78 mp *m
79 INTERFACE_MACRO:
80 XSINTERFACE_FUNC
81 XSINTERFACE_FUNC_SETMP
82 INTERFACE:
83 octets bits
84
85SV *
86storeb(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
100SV *
101storel(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
115SV *
116tostring(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
125SV *
126toint(m)
127 mp *m
128 CODE:
129 RETVAL = newSViv(mp_toiv(m));
130 OUTPUT:
131 RETVAL
132
133SV *
134DESTROY(m)
135 mp *m
136 CODE:
137 mp_drop(m);
138 XSRETURN_UNDEF;
139
140mp *
141unop(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
151mp *
152neg(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
162mp *
163mp_factorial(me, x)
164 SV *me
165 IV x
166 C_ARGS:
167 x
168
169mp *
170binop(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:
f9952aec 179 add sub mul and2c or2c nand2c nor2c xor2c and or nand nor xor
660b443c 180
181mp *
182shiftop(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:
f9952aec 191 lsl lsr lsl2c lsr2c
192
193bool
194testbitop(a, n)
195 mp *a
196 unsigned long n
197 INTERFACE_MACRO:
198 XSINTERFACE_FUNC
199 XSINTERFACE_FUNC_SETMP
200 INTERFACE:
201 testbit testbit2c
202
203mp *
204flipbits(a, n)
205 mp *a
206 unsigned long n
207 C_ARGS:
208 MP_NEW, a, n
209 INTERFACE_MACRO:
210 XSINTERFACE_FUNC
211 XSINTERFACE_FUNC_SETMP
212 INTERFACE:
213 setbit clearbit setbit2c clearbit2c
660b443c 214
215int
216mp_cmp(a, b)
217 mp *a
218 mp *b
219
220int
221mp_eq(a, b)
222 mp *a
223 mp *b
224
225int
226jacobi(a, n)
227 mp *a
228 mp *n
229 CODE:
230 if (!MP_LEN(n) || !(n->v[0] & 1))
231 croak("n must be odd in Catacomb::MP::jacobi");
232 RETVAL = mp_jacobi(a, n);
233 OUTPUT:
234 RETVAL
235
236mp *
237mp_modsqrt(p, x)
238 mp *p
239 mp *x
240 C_ARGS:
241 MP_NEW, x, p
242
243void
244div(a, b)
245 mp *a
246 mp *b
247 PREINIT:
248 mp *q = MP_NEW, *r = MP_NEW;
249 PPCODE:
250 if (MP_EQ(b, MP_ZERO))
251 croak("Divide by zero in Catacomb::MP::div");
252 q = MP_NEW;
253 switch (GIMME_V) {
254 case G_ARRAY:
255 r = MP_NEW;
256 mp_div(&q, &r, a, b);
257 EXTEND(SP, 2);
258 PUSHs(RET_MP(q));
259 PUSHs(RET_MP(r));
260 break;
261 case G_VOID:
262 break;
263 default:
264 mp_div(&q, &r, a, b);
265 EXTEND(SP, 1);
266 PUSHs(RET_MP(q));
267 break;
268 }
269
270void
271gcd(a, b)
272 mp *a
273 mp *b
274 PREINIT:
275 mp *g = MP_NEW, *x = MP_NEW, *y = MP_NEW;
276 PPCODE:
277 switch (GIMME_V) {
278 case G_ARRAY:
279 mp_gcd(&g, &x, &y, a, b);
280 EXTEND(SP, 3);
281 PUSHs(RET_MP(g));
282 PUSHs(RET_MP(x));
283 PUSHs(RET_MP(y));
284 break;
285 case G_VOID:
286 break;
287 default:
288 mp_gcd(&g, 0, 0, a, b);
289 EXTEND(SP, 1);
290 PUSHs(RET_MP(g));
291 break;
292 }
293
294void
295odd(m)
296 mp *m
297 PREINIT:
298 mp *t;
299 size_t s;
300 PPCODE:
301 t = mp_odd(MP_NEW, m, &s);
302 EXTEND(SP, 2);
303 PUSHs(RET_MP(t));
304 PUSHs(sv_2mortal(newSViv(s)));
305
306int
307smallfactor(x)
308 mp *x
309 CODE:
310 RETVAL = pfilt_smallfactor(x);
311 OUTPUT:
312 RETVAL
313
a1a90aaf 314MP_Reduce *
315makereduce(x)
316 mp *x
317 CODE:
318 if (!MP_POSP(x))
319 croak("Argument to Catacomb::MP::makereduce must be positive");
320 RETVAL = CREATE(MP_Reduce);
321 mpreduce_create(RETVAL, x);
322 OUTPUT:
323 RETVAL
324
660b443c 325MP_Mont *
326mont(x)
327 mp *x
328 CODE:
a1a90aaf 329 if (!MP_POSP(x))
660b443c 330 croak("Argument to Catacomb::MP::mont must be positive");
a1a90aaf 331 if (!MP_ODDP(x))
660b443c 332 croak("Argument to Catacomb::MP::mont must be odd");
333 RETVAL = CREATE(MP_Mont);
334 mpmont_create(RETVAL, x);
335 OUTPUT:
336 RETVAL
337
338MP_Barrett *
339barrett(x)
340 mp *x
341 CODE:
a1a90aaf 342 if (!MP_POSP(x))
660b443c 343 croak("Argument to Catacomb::MP::barrett must be positive");
344 RETVAL = CREATE(mpbarrett);
345 mpbarrett_create(RETVAL, x);
346 OUTPUT:
347 RETVAL
348
349MP_Prime_Rabin *
350rabin(x)
351 mp *x
352 CODE:
a1a90aaf 353 if (!MP_POSP(x))
660b443c 354 croak("Argument to Catacomb::MP::rabin must be positive");
a1a90aaf 355 if (!MP_ODDP(x))
660b443c 356 croak("Argument to Catacomb::MP::rabin must be odd");
357 RETVAL = CREATE(MP_Prime_Rabin);
358 rabin_create(RETVAL, x);
359 OUTPUT:
360 RETVAL
361
362MODULE = Catacomb PACKAGE = Catacomb::MP::Mont PREFIX = mpmont_
363
364MP_Mont *
365new(me, x)
366 SV *me
367 mp *x
368 CODE:
a1a90aaf 369 if (!MP_POSP(x))
660b443c 370 croak("Argument to Catacomb::MP::Mont::new must be positive");
a1a90aaf 371 if (!MP_ODDP(x))
660b443c 372 croak("Argument to Catacomb::MP::Mont::new must be odd");
373 RETVAL = CREATE(MP_Mont);
374 mpmont_create(RETVAL, x);
375 OUTPUT:
376 RETVAL
377
378SV *
379DESTROY(mm)
380 MP_Mont *mm
381 CODE:
382 mpmont_destroy(mm);
383 DESTROY(mm);
384 XSRETURN_UNDEF;
385
386mp *
387mpmont_reduce(mm, x)
388 MP_Mont *mm
389 mp *x
390 C_ARGS:
391 mm, MP_NEW, x
392
393mp *
394mpmont_mul(mm, x, y)
395 MP_Mont *mm
396 mp *x
397 mp *y
398 C_ARGS:
399 mm, MP_NEW, x, y
400
401mp *
402mpmont_expr(mm, g, x)
403 MP_Mont *mm
404 mp *g
405 mp *x
406 C_ARGS:
407 mm, MP_NEW, g, x
408
409mp *
410mpmont_exp(mm, g, x)
411 MP_Mont *mm
412 mp *g
413 mp *x
414 C_ARGS:
415 mm, MP_NEW, g, x
416
417mp *
418mpmont_mexpr(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::mexpr"
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_i", "Catacomb::MP", 0, 0);
432 v[j].exp = mp_fromsv(ST(i + 1), "x_i", "Catacomb::MP", 0, 0);
660b443c 433 }
434 RETVAL = mpmont_mexpr(mm, MP_NEW, v, n);
435 xfree(v);
436 OUTPUT:
437 RETVAL
438
439mp *
440mpmont_mexp(mm, ...)
441 MP_Mont *mm
442 PREINIT:
443 mp_expfactor *v;
444 size_t i, j, n;
445 CODE:
446 if (items < 3 || !(items & 1)) {
447 croak("Usage: Catacomb::MP::Mont::mexp"
448 "(mm, g_0, x_0, g_1, x_1, ...");
449 }
450 n = (items - 1)/2;
451 v = xmalloc(n * sizeof(mp_expfactor));
452 for (i = 1, j = 0; i < items; i += 2, j++) {
a1a90aaf 453 v[j].base = mp_fromsv(ST(i), "g_%lu",
454 "Catacomb::MP", 0, 0, (unsigned long)i);
455 v[j].exp = mp_fromsv(ST(i + 1), "x_%lu",
456 "Catacomb::MP", 0, 0, (unsigned long)i);
660b443c 457 }
458 RETVAL = mpmont_mexp(mm, MP_NEW, v, n);
459 xfree(v);
460 OUTPUT:
461 RETVAL
462
463mp *
464r(mm)
465 MP_Mont *mm
466 CODE:
a1a90aaf 467 RETVAL = MP_COPY(mm->r);
660b443c 468 OUTPUT:
469 RETVAL
470
471mp *
472r2(mm)
473 MP_Mont *mm
474 CODE:
a1a90aaf 475 RETVAL = MP_COPY(mm->r2);
660b443c 476 OUTPUT:
477 RETVAL
478
479mp *
480m(mm)
481 MP_Mont *mm
482 CODE:
a1a90aaf 483 RETVAL = MP_COPY(mm->m);
660b443c 484 OUTPUT:
485 RETVAL
486
487MODULE = Catacomb PACKAGE = Catacomb::MP::Barrett PREFIX = mpbarrett_
488
489MP_Barrett *
490new(me, x)
491 SV *me
492 mp *x
493 CODE:
a1a90aaf 494 if (!MP_POSP(x))
660b443c 495 croak("Argument to Catacomb::MP::Barrett::new must be positive");
496 RETVAL = CREATE(mpbarrett);
497 mpbarrett_create(RETVAL, x);
498 OUTPUT:
499 RETVAL
500
501SV *
502DESTROY(mb)
503 MP_Barrett *mb
504 CODE:
505 mpbarrett_destroy(mb);
506 DESTROY(mb);
507 XSRETURN_UNDEF;
508
509mp *
510mpbarrett_reduce(mb, x)
511 MP_Barrett *mb
512 mp *x
513 C_ARGS:
514 mb, MP_NEW, x
515
516mp *
517mpbarrett_exp(mb, g, x)
518 MP_Barrett *mb
519 mp *g
520 mp *x
521 C_ARGS:
522 mb, MP_NEW, g, x
523
524mp *
525m(mb)
526 MP_Barrett *mb
527 CODE:
a1a90aaf 528 RETVAL = MP_COPY(mb->m);
529 OUTPUT:
530 RETVAL
531
532MODULE = Catacomb PACKAGE = Catacomb::MP::Reduce PREFIX = mpreduce_
533
534MP_Reduce *
535new(me, x)
536 SV *me
537 mp *x
538 CODE:
539 if (!MP_POSP(x))
540 croak("Argument to Catacomb::MP::Reduce::new must be positive");
541 RETVAL = CREATE(mpreduce);
542 mpreduce_create(RETVAL, x);
543 OUTPUT:
544 RETVAL
545
546SV *
547DESTROY(r)
548 MP_Reduce *r
549 CODE:
550 mpreduce_destroy(r);
551 DESTROY(r);
552 XSRETURN_UNDEF;
553
554mp *
555reduce(r, x)
556 MP_Reduce *r
557 mp *x
558 CODE:
559 RETVAL = mpreduce_do(r, MP_NEW, x);
560 OUTPUT:
561 RETVAL
562
563mp *
564mpreduce_exp(r, x, y)
565 MP_Reduce *r
566 mp *x
567 mp *y
568 C_ARGS:
569 r, MP_NEW, x, y
570
571mp *
572m(r)
573 MP_Reduce *r
574 CODE:
575 RETVAL = MP_COPY(r->p);
660b443c 576 OUTPUT:
577 RETVAL
578
579MODULE = Catacomb PACKAGE = Catacomb::MP::CRT
580
581MP_CRT *
582new(me, ...)
583 SV *me
584 PREINIT:
585 mpcrt_mod *v;
586 size_t n, i;
587 CODE:
588 if (items < 1)
589 croak("Usage: Catacomb::MP::CRT::new(me, n_0, n_1, ...)");
590 n = items - 1;
591 v = xmalloc(n * sizeof(mpcrt_mod));
592 for (i = 0; i < n; i++) {
a1a90aaf 593 v[i].m = mp_copy(mp_fromsv(ST(i + 1), "n_%lu",
594 "Catacomb::MP", 0, 0,
660b443c 595 (unsigned long)i));
596 }
597 RETVAL = CREATE(MP_CRT);
598 mpcrt_create(RETVAL, v, n, 0);
599 OUTPUT:
600 RETVAL
601
602SV *
603DESTROY(mc)
604 MP_CRT *mc
605 CODE:
606 mpcrt_destroy(mc);
607 xfree(mc->v);
608 DESTROY(mc);
609 XSRETURN_UNDEF;
610
611mp *
612solve(mc, ...)
613 MP_CRT *mc
614 PREINIT:
615 mp **v;
616 size_t n, i;
617 CODE:
618 n = mc->k;
619 if (items - 1 != n)
620 croak("Wrong number of residues for this CRT context");
a1a90aaf 621 for (i = 0; i < n; i++) {
622 v[i] = mp_fromsv(ST(i + 1), "r_%lu", "Catacomb::MP",
623 0, 0, (unsigned long)i);
624 }
660b443c 625 RETVAL = mpcrt_solve(mc, MP_NEW, v);
626 xfree(v);
627 OUTPUT:
628 RETVAL
629
630#----- That's all, folks ----------------------------------------------------