Expunge revision histories in files.
[catacomb-perl] / mp.xs
CommitLineData
660b443c 1# ---?---
2#
a24b5cfd 3# $Id: mp.xs,v 1.2 2004/04/08 01:36:21 mdw Exp $
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:
37 RETVAL = sv ? mp_fromsv(sv, "sv", radix, 1) : MP_ZERO;
38 OUTPUT:
39 RETVAL
40
41mp *
42mp_copy(x)
43 mp *x
44
45mp *
46loadb(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
58mp *
59loadl(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
71int
72metrics(m)
73 mp *m
74 INTERFACE_MACRO:
75 XSINTERFACE_FUNC
76 XSINTERFACE_FUNC_SETMP
77 INTERFACE:
78 octets bits
79
80SV *
81storeb(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
95SV *
96storel(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
110SV *
111tostring(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
120SV *
121toint(m)
122 mp *m
123 CODE:
124 RETVAL = newSViv(mp_toiv(m));
125 OUTPUT:
126 RETVAL
127
128SV *
129DESTROY(m)
130 mp *m
131 CODE:
132 mp_drop(m);
133 XSRETURN_UNDEF;
134
135mp *
136unop(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
146mp *
147neg(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
157mp *
158mp_factorial(me, x)
159 SV *me
160 IV x
161 C_ARGS:
162 x
163
164mp *
165binop(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
176mp *
177shiftop(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
188int
189mp_cmp(a, b)
190 mp *a
191 mp *b
192
193int
194mp_eq(a, b)
195 mp *a
196 mp *b
197
198int
199jacobi(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
209mp *
210mp_modsqrt(p, x)
211 mp *p
212 mp *x
213 C_ARGS:
214 MP_NEW, x, p
215
216void
217div(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
243void
244gcd(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
267void
268odd(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
279int
280smallfactor(x)
281 mp *x
282 CODE:
283 RETVAL = pfilt_smallfactor(x);
284 OUTPUT:
285 RETVAL
286
287MP_Mont *
288mont(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
300MP_Barrett *
301barrett(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
311MP_Prime_Rabin *
312rabin(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
324MODULE = Catacomb PACKAGE = Catacomb::MP::Mont PREFIX = mpmont_
325
326MP_Mont *
327new(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
340SV *
341DESTROY(mm)
342 MP_Mont *mm
343 CODE:
344 mpmont_destroy(mm);
345 DESTROY(mm);
346 XSRETURN_UNDEF;
347
348mp *
349mpmont_reduce(mm, x)
350 MP_Mont *mm
351 mp *x
352 C_ARGS:
353 mm, MP_NEW, x
354
355mp *
356mpmont_mul(mm, x, y)
357 MP_Mont *mm
358 mp *x
359 mp *y
360 C_ARGS:
361 mm, MP_NEW, x, y
362
363mp *
364mpmont_expr(mm, g, x)
365 MP_Mont *mm
366 mp *g
367 mp *x
368 C_ARGS:
369 mm, MP_NEW, g, x
370
371mp *
372mpmont_exp(mm, g, x)
373 MP_Mont *mm
374 mp *g
375 mp *x
376 C_ARGS:
377 mm, MP_NEW, g, x
378
379mp *
380mpmont_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
401mp *
402mpmont_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
423mp *
424r(mm)
425 MP_Mont *mm
426 CODE:
427 RETVAL = mp_copy(mm->r);
428 OUTPUT:
429 RETVAL
430
431mp *
432r2(mm)
433 MP_Mont *mm
434 CODE:
435 RETVAL = mp_copy(mm->r2);
436 OUTPUT:
437 RETVAL
438
439mp *
440m(mm)
441 MP_Mont *mm
442 CODE:
443 RETVAL = mp_copy(mm->m);
444 OUTPUT:
445 RETVAL
446
447MODULE = Catacomb PACKAGE = Catacomb::MP::Barrett PREFIX = mpbarrett_
448
449MP_Barrett *
450new(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
461SV *
462DESTROY(mb)
463 MP_Barrett *mb
464 CODE:
465 mpbarrett_destroy(mb);
466 DESTROY(mb);
467 XSRETURN_UNDEF;
468
469mp *
470mpbarrett_reduce(mb, x)
471 MP_Barrett *mb
472 mp *x
473 C_ARGS:
474 mb, MP_NEW, x
475
476mp *
477mpbarrett_exp(mb, g, x)
478 MP_Barrett *mb
479 mp *g
480 mp *x
481 C_ARGS:
482 mb, MP_NEW, g, x
483
484mp *
485m(mb)
486 MP_Barrett *mb
487 CODE:
488 RETVAL = mp_copy(mb->m);
489 OUTPUT:
490 RETVAL
491
492MODULE = Catacomb PACKAGE = Catacomb::MP::CRT
493
494MP_CRT *
495new(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
514SV *
515DESTROY(mc)
516 MP_CRT *mc
517 CODE:
518 mpcrt_destroy(mc);
519 xfree(mc->v);
520 DESTROY(mc);
521 XSRETURN_UNDEF;
522
523mp *
524solve(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 ----------------------------------------------------