Key mangling, and elliptic curves.
[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:
179 add sub mul and or xor
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:
191 lsl lsr
192
193int
194mp_cmp(a, b)
195 mp *a
196 mp *b
197
198int
199mp_eq(a, b)
200 mp *a
201 mp *b
202
203int
204jacobi(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
214mp *
215mp_modsqrt(p, x)
216 mp *p
217 mp *x
218 C_ARGS:
219 MP_NEW, x, p
220
221void
222div(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
248void
249gcd(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
272void
273odd(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
284int
285smallfactor(x)
286 mp *x
287 CODE:
288 RETVAL = pfilt_smallfactor(x);
289 OUTPUT:
290 RETVAL
291
a1a90aaf 292MP_Reduce *
293makereduce(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 303MP_Mont *
304mont(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
316MP_Barrett *
317barrett(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
327MP_Prime_Rabin *
328rabin(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
340MODULE = Catacomb PACKAGE = Catacomb::MP::Mont PREFIX = mpmont_
341
342MP_Mont *
343new(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
356SV *
357DESTROY(mm)
358 MP_Mont *mm
359 CODE:
360 mpmont_destroy(mm);
361 DESTROY(mm);
362 XSRETURN_UNDEF;
363
364mp *
365mpmont_reduce(mm, x)
366 MP_Mont *mm
367 mp *x
368 C_ARGS:
369 mm, MP_NEW, x
370
371mp *
372mpmont_mul(mm, x, y)
373 MP_Mont *mm
374 mp *x
375 mp *y
376 C_ARGS:
377 mm, MP_NEW, x, y
378
379mp *
380mpmont_expr(mm, g, x)
381 MP_Mont *mm
382 mp *g
383 mp *x
384 C_ARGS:
385 mm, MP_NEW, g, x
386
387mp *
388mpmont_exp(mm, g, x)
389 MP_Mont *mm
390 mp *g
391 mp *x
392 C_ARGS:
393 mm, MP_NEW, g, x
394
395mp *
396mpmont_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
417mp *
418mpmont_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
441mp *
442r(mm)
443 MP_Mont *mm
444 CODE:
a1a90aaf 445 RETVAL = MP_COPY(mm->r);
660b443c 446 OUTPUT:
447 RETVAL
448
449mp *
450r2(mm)
451 MP_Mont *mm
452 CODE:
a1a90aaf 453 RETVAL = MP_COPY(mm->r2);
660b443c 454 OUTPUT:
455 RETVAL
456
457mp *
458m(mm)
459 MP_Mont *mm
460 CODE:
a1a90aaf 461 RETVAL = MP_COPY(mm->m);
660b443c 462 OUTPUT:
463 RETVAL
464
465MODULE = Catacomb PACKAGE = Catacomb::MP::Barrett PREFIX = mpbarrett_
466
467MP_Barrett *
468new(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
479SV *
480DESTROY(mb)
481 MP_Barrett *mb
482 CODE:
483 mpbarrett_destroy(mb);
484 DESTROY(mb);
485 XSRETURN_UNDEF;
486
487mp *
488mpbarrett_reduce(mb, x)
489 MP_Barrett *mb
490 mp *x
491 C_ARGS:
492 mb, MP_NEW, x
493
494mp *
495mpbarrett_exp(mb, g, x)
496 MP_Barrett *mb
497 mp *g
498 mp *x
499 C_ARGS:
500 mb, MP_NEW, g, x
501
502mp *
503m(mb)
504 MP_Barrett *mb
505 CODE:
a1a90aaf 506 RETVAL = MP_COPY(mb->m);
507 OUTPUT:
508 RETVAL
509
510MODULE = Catacomb PACKAGE = Catacomb::MP::Reduce PREFIX = mpreduce_
511
512MP_Reduce *
513new(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
524SV *
525DESTROY(r)
526 MP_Reduce *r
527 CODE:
528 mpreduce_destroy(r);
529 DESTROY(r);
530 XSRETURN_UNDEF;
531
532mp *
533reduce(r, x)
534 MP_Reduce *r
535 mp *x
536 CODE:
537 RETVAL = mpreduce_do(r, MP_NEW, x);
538 OUTPUT:
539 RETVAL
540
541mp *
542mpreduce_exp(r, x, y)
543 MP_Reduce *r
544 mp *x
545 mp *y
546 C_ARGS:
547 r, MP_NEW, x, y
548
549mp *
550m(r)
551 MP_Reduce *r
552 CODE:
553 RETVAL = MP_COPY(r->p);
660b443c 554 OUTPUT:
555 RETVAL
556
557MODULE = Catacomb PACKAGE = Catacomb::MP::CRT
558
559MP_CRT *
560new(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
580SV *
581DESTROY(mc)
582 MP_CRT *mc
583 CODE:
584 mpcrt_destroy(mc);
585 xfree(mc->v);
586 DESTROY(mc);
587 XSRETURN_UNDEF;
588
589mp *
590solve(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 ----------------------------------------------------