-
Notifications
You must be signed in to change notification settings - Fork 1
/
GMPz.pm
executable file
·552 lines (477 loc) · 20 KB
/
GMPz.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
package Math::GMPz;
use strict;
use warnings;
use Math::GMPz::Random;
require Exporter;
*import = \&Exporter::import;
require DynaLoader;
use constant _UOK_T => 1;
use constant _IOK_T => 2;
use constant _NOK_T => 3;
use constant _POK_T => 4;
use constant _MATH_MPFR_T => 5;
use constant _MATH_GMPf_T => 6;
use constant _MATH_GMPq_T => 7;
use constant _MATH_GMPz_T => 8;
use constant _MATH_GMP_T => 9;
use constant _MATH_MPC_T => 10;
use constant GMPZ_PV_NV_BUG => Math::GMPz::Random::_has_pv_nv_bug();
use subs qw( __GNU_MP_VERSION __GNU_MP_VERSION_MINOR __GNU_MP_VERSION_PATCHLEVEL
__GNU_MP_RELEASE __GMP_CC __GMP_CFLAGS GMP_LIMB_BITS GMP_NAIL_BITS
MATH_GMPz_IV_MAX MATH_GMPz_IV_MIN MATH_GMPz_UV_MAX);
use overload
'+' => \&overload_add,
'-' => \&overload_sub,
'*' => \&overload_mul,
'/' => \&overload_div,
'+=' => \&overload_add_eq,
'-=' => \&overload_sub_eq,
'*=' => \&overload_mul_eq,
'/=' => \&overload_div_eq,
'%' => \&overload_mod,
'%=' => \&overload_mod_eq,
'<<' => \&overload_lshift,
'<<=' => \&overload_lshift_eq,
'>>' => \&overload_rshift,
'>>=' => \&overload_rshift_eq,
'&' => \&overload_and,
'&=' => \&overload_and_eq,
'|' => \&overload_ior,
'|=' => \&overload_ior_eq,
'^' => \&overload_xor,
'^=' => \&overload_xor_eq,
'~' => \&overload_com,
'**' => \&overload_pow,
'**=' => \&overload_pow_eq,
'sqrt' => \&overload_sqrt,
'""' => \&overload_string,
'++' => \&overload_inc,
'--' => \&overload_dec,
'>' => \&overload_gt,
'>=' => \&overload_gte,
'<' => \&overload_lt,
'<=' => \&overload_lte,
'<=>' => \&overload_spaceship,
'==' => \&overload_equiv,
'!=' => \&overload_not_equiv,
'!' => \&overload_not,
'=' => \&overload_copy,
'abs' => \&overload_abs;
my @untagged = qw(
__GNU_MP_VERSION __GNU_MP_VERSION_MINOR __GNU_MP_VERSION_PATCHLEVEL
__GNU_MP_RELEASE __GMP_CC __GMP_CFLAGS IOK_flag NOK_flag POK_flag
);
my @tagged = qw(
GMPZ_PV_NV_BUG MATH_GMPz_IV_MAX MATH_GMPz_IV_MIN MATH_GMPz_UV_MAX
Rmpz_abs Rmpz_add Rmpz_add_ui Rmpz_addmul Rmpz_addmul_ui Rmpz_and Rmpz_bin_ui
Rmpz_bin_uiui Rmpz_bin_si Rmpz_cdiv_q Rmpz_cdiv_q_2exp Rmpz_cdiv_q_ui Rmpz_cdiv_qr
Rmpz_cdiv_qr_ui Rmpz_cdiv_r Rmpz_cdiv_r_2exp Rmpz_cdiv_r_ui Rmpz_cdiv_ui
Rmpz_clear Rmpz_clrbit Rmpz_cmp Rmpz_cmp_d Rmpz_cmp_si Rmpz_cmp_ui
Rmpz_cmp_sj Rmpz_cmp_uj Rmpz_cmpabs Rmpz_cmpabs_d Rmpz_cmpabs_ui
Rmpz_com Rmpz_combit Rmpz_congruent_2exp_p
Rmpz_congruent_p Rmpz_congruent_ui_p Rmpz_div Rmpz_divmod Rmpz_div_ui
Rmpz_divmod_ui Rmpz_div_2exp Rmpz_mod_2exp Rmpz_divexact Rmpz_divexact_ui
Rmpz_divisible_2exp_p Rmpz_divisible_p Rmpz_divisible_ui_p Rmpz_even_p
Rmpz_export Rmpz_export_UV
Rmpz_fac_ui Rmpz_2fac_ui Rmpz_mfac_uiui Rmpz_primorial_ui
Rmpz_fdiv_q Rmpz_fdiv_q_2exp Rmpz_fdiv_q_ui
Rmpz_fdiv_qr Rmpz_fdiv_qr_ui Rmpz_fdiv_r Rmpz_fdiv_r_2exp Rmpz_fdiv_r_ui
Rmpz_fdiv_ui Rmpz_fib2_ui Rmpz_fib_ui Rmpz_fits_sint_p Rmpz_fits_slong_p
Rmpz_fits_sshort_p Rmpz_fits_uint_p Rmpz_fits_ulong_p Rmpz_fits_ushort_p
Rmpz_fprintf Rmpz_sprintf Rmpz_snprintf
Rmpz_gcd Rmpz_gcd_ui Rmpz_gcdext Rmpz_get_d_2exp Rmpz_get_si Rmpz_get_str
Rmpz_get_d Rmpz_get_NV
Rmpz_get_ui Rmpz_getlimbn Rmpz_hamdist Rmpz_import Rmpz_import_UV
Rmpz_init Rmpz_init2
Rmpz_init2_nobless Rmpz_init_nobless Rmpz_init_set Rmpz_init_set_d
Rmpz_init_set_IV Rmpz_init_set_IV_nobless Rmpz_init_set_NV Rmpz_init_set_NV_nobless
Rmpz_set_IV Rmpz_set_NV Rmpz_cmp_NV Rmpz_cmp_IV
Rmpz_get_IV Rmpz_fits_IV_p
Rmpz_init_set_d_nobless Rmpz_init_set_nobless Rmpz_init_set_si
Rmpz_init_set_si_nobless Rmpz_init_set_str Rmpz_init_set_str_nobless
Rmpz_init_set_ui Rmpz_init_set_ui_nobless Rmpz_inp_str Rmpz_inp_raw
Rmpz_invert Rmpz_ior new_from_MBI
Rmpz_jacobi Rmpz_kronecker Rmpz_kronecker_si Rmpz_kronecker_ui Rmpz_lcm
Rmpz_lcm_ui Rmpz_legendre Rmpz_lucnum2_ui Rmpz_lucnum_ui Rmpz_mod Rmpz_mod_ui
Rmpz_mul Rmpz_mul_2exp Rmpz_mul_si Rmpz_mul_ui Rmpz_neg
Rmpz_nextprime Rmpz_prevprime
Rmpz_odd_p Rmpz_out_str Rmpz_out_raw
Rmpz_perfect_power_p Rmpz_perfect_square_p
Rmpz_popcount Rmpz_pow_ui Rmpz_powm Rmpz_powm_sec Rmpz_powm_ui Rmpz_printf
Rmpz_probab_prime_p Rmpz_realloc2 Rmpz_remove Rmpz_root Rmpz_rootrem
Rmpz_rrandomb Rmpz_scan0 Rmpz_scan1 Rmpz_set Rmpz_set_d Rmpz_set_f Rmpz_set_q
Rmpz_set_si Rmpz_set_sj Rmpz_set_str Rmpz_set_ui Rmpz_set_uj
Rmpz_setbit Rmpz_sgn Rmpz_si_kronecker
Rmpz_size Rmpz_sizeinbase Rmpz_sqrt Rmpz_sqrtrem Rmpz_sub Rmpz_sub_ui
Rmpz_submul Rmpz_submul_ui Rmpz_swap Rmpz_tdiv_q Rmpz_tdiv_q_2exp
Rmpz_tdiv_q_ui Rmpz_tdiv_qr Rmpz_tdiv_qr_ui Rmpz_tdiv_r Rmpz_tdiv_r_2exp
Rmpz_tdiv_r_ui Rmpz_tdiv_ui Rmpz_tstbit Rmpz_ui_kronecker Rmpz_ui_pow_ui
Rmpz_ui_sub Rmpz_urandomb Rmpz_urandomm Rmpz_xor
rand_init rand_clear
TRmpz_out_str TRmpz_inp_str
zgmp_randseed zgmp_randseed_ui zgmp_randclear
zgmp_randinit_default zgmp_randinit_mt zgmp_randinit_lc_2exp zgmp_randinit_lc_2exp_size
zgmp_randinit_set zgmp_randinit_default_nobless zgmp_randinit_mt_nobless
zgmp_randinit_lc_2exp_nobless zgmp_randinit_lc_2exp_size_nobless zgmp_randinit_set_nobless
zgmp_urandomb_ui zgmp_urandomm_ui
);
@Math::GMPz::EXPORT_OK = (@untagged, @tagged);
our $VERSION = '0.62';
#$VERSION = eval $VERSION;
Math::GMPz->DynaLoader::bootstrap($VERSION);
$Math::GMPz::NULL = _Rmpz_NULL();
$Math::GMPz::utf8_no_downgrade = 0; # allow utf8::downgrade of utf8 strings
# passed to Rmpz_import.
$Math::GMPz::utf8_no_warn = 0; # warn if utf8 string is passed to Rmpz_import.
$Math::GMPz::utf8_no_croak = 0; # croak if utf8::downgrade fails in Rmpz_import.
$Math::GMPz::utf8_no_fail = 0; # warn if $Math::GMPz::utf8_no_croak is true &&
# utf8::downgrade fails in Rmpz_import.
$Math::GMPz::RETYPE = 1; # This variable used to be initially set to 0, but
# this has changed, beginning with Math::GMPz-0.62.
# This enables a Math::GMPz object to be coerced to
# a Math::GMPq or Math::MPFR object in certain overloaded
# operations. (See the 'OPERATOR OVERLOADING' section of
# the POD documentation for details.)
# Setting this variable to 0 will cause these "certain
# overloaded operations" to throw a fatal error.
%Math::GMPz::EXPORT_TAGS =(mpz => \@tagged);
sub dl_load_flags {0} # Prevent DynaLoader from complaining and croaking
sub new {
# This function caters for 2 possibilities:
# 1) that 'new' has been called OOP style - in which
# case there will be a maximum of 3 args
# 2) that 'new' has been called as a function - in
# which case there will be a maximum of 2 args.
# If there are no args, then we just want to return an
# initialized Math::GMPz
if(!@_) {return Rmpz_init()}
if(@_ > 3) {die "Too many arguments supplied to new()"}
# If 'new' has been called OOP style, the first arg is the string
# "Math::GMPz" which we don't need - so let's remove it. However,
# if the first arg is a Math::GMPz object (which is a possibility),
# then we'll get a fatal error when we check it for equivalence to
# the string "Math::GMPz". So we first need to check that it's not
# an object - which we'll do by using the ref() function.
# Also first check that the POK flag is set - to avoid setting the
# POK flag on perl-5.18 and earlier.
if(!ref($_[0]) && Math::GMPz::_SvPOK($_[0]) && $_[0] eq "Math::GMPz") {
shift;
if(!@_) {return Rmpz_init()}
}
# @_ can now contain a maximum of 2 args - the value, and iff the value is
# a string, (optionally) the base of the numeric string.
if(@_ > 2) {die "Too many arguments supplied to new() - expected no more than two"}
my ($arg1, $type, $base);
# $_[0] is the value, $_[1] (if supplied) is the base of the number
# in the string $[_0].
$arg1 = shift;
$base = 0;
$type = _itsa($arg1);
if(!$type) {die "Inappropriate argument supplied to new()"}
# Create a Math::GMPz object that has $arg1 as its value.
# Die if there are any additional args (unless $type == _POK_T)
if($type == _IOK_T || $type == _UOK_T) {
if(@_ ) {die "Too many arguments supplied to new() - expected only one"}
return Rmpz_init_set_IV($arg1);
}
if($type == _POK_T) { # POK
if(@_ > 1) {die "Too many arguments supplied to new() - expected no more than two"}
$base = shift if @_;
if($base < 0 || $base == 1 || $base > 62) {die "Invalid value for base"}
$arg1 =~ s/^(\s+)?\+//; # Rmpz_init_set_str() dies if there's a leading '+'.
return Rmpz_init_set_str($arg1, $base);
}
if($type == _NOK_T) {
if(@_ ) {die "Too many arguments supplied to new() - expected only one"}
return Rmpz_init_set_NV($arg1);
}
if($type == _MATH_GMPz_T || $type == _MATH_GMP_T) { # Math::GMPz or Math::GMP object
if(@_) {die "Too many arguments supplied to new() - expected only one"}
return Rmpz_init_set($arg1);
}
if($type == -1) { # Math::BigInt
if(@_) {die "Too many arguments supplied to new() - expected only one"}
return _new_from_MBI($arg1);
}
die "Unrecognised argument provided to new()";
}
sub new_from_MBI {
return _new_from_MBI($_[0]) if _itsa($_[0]) == -1;
die "Inappropriate arg supplied to new_from_MBI function";
}
sub Rmpz_out_str {
if(@_ == 2) {
die "Inappropriate 1st arg supplied to Rmpz_out_str" if _itsa($_[0]) != _MATH_GMPz_T && _itsa($_[0]) != _MATH_GMP_T;
return _Rmpz_out_str($_[0], $_[1]);
}
if(@_ == 3) {
if(_itsa($_[0]) == _MATH_GMPz_T || _itsa($_[0]) == _MATH_GMP_T) {return _Rmpz_out_strS($_[0], $_[1], $_[2])}
die "Incorrect args supplied to Rmpz_out_str" if _itsa($_[1]) != _MATH_GMPz_T && _itsa($_[1]) != _MATH_GMP_T;
return _Rmpz_out_strP($_[0], $_[1], $_[2]);
}
if(@_ == 4) {
die "Inappropriate 2nd arg supplied to Rmpz_out_str" if _itsa($_[1]) != _MATH_GMPz_T && _itsa($_[1]) != _MATH_GMP_T;
return _Rmpz_out_strPS($_[0], $_[1], $_[2], $_[3]);
}
die "Wrong number of arguments supplied to Rmpz_out_str()";
}
sub TRmpz_out_str {
if(@_ == 3) {
die "Inappropriate 3rd arg supplied to TRmpz_out_str" if _itsa($_[2]) != _MATH_GMPz_T && _itsa($_[2]) != _MATH_GMP_T;
return _TRmpz_out_str($_[0], $_[1], $_[2]);
}
if(@_ == 4) {
if(_itsa($_[2]) == _MATH_GMPz_T || _itsa($_[2]) == _MATH_GMP_T) {return _TRmpz_out_strS($_[0], $_[1], $_[2], $_[3])}
die "Incorrect args supplied to TRmpz_out_str" if _itsa($_[3]) != _MATH_GMPz_T && _itsa($_[3]) != _MATH_GMP_T;
return _TRmpz_out_strP($_[0], $_[1], $_[2], $_[3]);
}
if(@_ == 5) {
die "Inappropriate 4th arg supplied to TRmpz_out_str" if _itsa($_[3]) != _MATH_GMPz_T && _itsa($_[3]) != _MATH_GMP_T;
return _TRmpz_out_strPS($_[0], $_[1], $_[2], $_[3], $_[4]);
}
die "Wrong number of arguments supplied to TRmpz_out_str()";
}
# _Rmpz_get_IV may have returned a "string" - in which case we want to coerce it
# to an IV. It would be more efficient to do this in XS space (TODO), but in the
# meantime I've taken the soft option of having perl perform the coercion:
sub Rmpz_get_IV {
my $ret = _Rmpz_get_IV(shift);
$ret += 0 unless _SvIOK($ret); # Set the IV flag
return $ret;
}
sub Rpi_x {
Rmpz_set_ui($_[0], 1);
Rmpz_mul_2exp($_[0], $_[0], $_[1]);
Rmpz_tdiv_q_ui($_[0], $_[0], int(0.693147180559945 * $_[1]));
}
sub prime_ratio {
return int($_[0] * 0.3465735902799726);
}
sub Rprovable_small {
my $lim = 341550071728321;
my $last = 0;
if(Rmpz_cmp_ui($_[0], 2) < 0 || Rmpz_cmp_d($_[0], $lim) >= 0)
{die "Argument to provable_small (= ", Rmpz_get_str($_[0], 10), " must be in range [2..341550071728321]"}
if(Rmpz_cmp_ui($_[0], 18) < 0) {
if(Rmpz_cmp_ui($_[0], 2) <= 0) {Rmpz_set_ui($_[0], 2)}
if(!Rmpz_cmp_ui($_[0], 3)) {Rmpz_set_ui($_[0], 3)}
if(Rmpz_cmp_ui($_[0], 5) <= 0) {Rmpz_set_ui($_[0], 5)}
if(Rmpz_cmp_ui($_[0], 7) <= 0) {Rmpz_set_ui($_[0], 7)}
if(Rmpz_cmp_ui($_[0], 11) <= 0) {Rmpz_set_ui($_[0], 11)}
if(Rmpz_cmp_ui($_[0], 13) <= 0) {Rmpz_set_ui($_[0], 13)}
Rmpz_set_ui($_[0], 17);
}
else {
if(!Rmpz_tstbit($_[0], 0)) {Rmpz_add_ui($_[0], $_[0], 1)};
while(Rmpz_cmp_d($_[0], $lim) < 0) {
if(Rrm_gmp($_[0], 2) && Rrm_gmp($_[0], 3) && Rrm_gmp($_[0], 5) && Rrm_gmp($_[0], 7)
&& Rrm_gmp($_[0], 11) && Rrm_gmp($_[0], 13) && Rrm_gmp($_[0], 17))
{$last = 1;
last;
}
Rmpz_add_ui($_[0], $_[0], 2);
}
if(!$last) {Rmpz_set_ui($_[0], 0)}
}
}
sub Rprime_test {
my $ul = $_[1] + 1;
for(2..$ul) {
if(!Rrm_gmp($_[0], $_)) {return 0}
}
return 1;
}
sub Rnext_germaine_prime {
my $last = 0;
my @range = Rsieve_gmp($_[4], $_[5], $_[2]);
Rmpz_set($_[0], $_[2]);
my $sub = 0;
my $mod;
for(@range) {
Rmpz_add_ui($_[0], $_[0], $_ - $sub);
$sub = $_;
$mod = Rmpz_tdiv_ui($_[0], 3);
if($mod == 2) {
if(Rprime_test($_[0], $_[3])) {
Rmpz_mul_2exp($_[1], $_[0], 1);
Rmpz_add_ui($_[1], $_[1], 1);
if(Rprime_test($_[1], $_[3])) {
$last = 1;
last;
}
}
}
}
if(!$last) {
Rmpz_set_ui($_[0], 0);
Rmpz_set_ui($_[1], 0);
}
}
sub merten {
my $gamma = 0.57721566490153286; # Euler's constant
return 1 / exp($gamma) / log($_[0]);
}
sub Rgenerator_zp {
my $s = Rmpz_sizeinbase($_[1], 2);
my $order = Rmpz_init2($s);
my $temp = Rmpz_init2($s);
my $check = Rmpz_init2($s);
Rmpz_set($order, $_[1]);
Rmpz_sub_ui($order, $order, 1);
Rmpz_set($check, $order);
my $nok = (1,0);
for(@{$_[2]}) {
if(!Rmpz_divisible_ui_p($order, $_)) {$nok = 1}
Rmpz_set_ui($temp, $_);
Rmpz_remove($check, $check, $temp);
}
if($nok) {die "Incorrect factors supplied to 3rd argument to Rgenerator_zp() function"}
if(defined($_[3])) {
$nok = 0;
for(@{$_[3]}) {
if(!Rmpz_divisible_p($order, $_)) {$nok = 1}
Rmpz_remove($check, $check, $_);
}
if($nok) {die "Incorrect factors supplied to 4th argument to Rgenerator_zp function"}
}
if(Rmpz_cmp_ui($check, 1)) {die "Incomplete factorisation supplied to Rgenerator_zp function"};
while(1) {
my $flag = 1;
if(Rmpz_cmp($_[0], $order) > 0){warn "Generator greater than order. Re-setting generator %= order and continuing....";
Rmpz_tdiv_r($_[0], $_[0], $order);
}
for(@{$_[2]}) {
Rmpz_divexact_ui($temp, $order, $_);
Rmpz_powm($check, $_[0], $temp, $_[1]);
if(!Rmpz_cmp_ui($check, 1)) {
$flag = 0;
last;
}
}
if($flag && defined($_[3])) {
for(@{$_[3]}) {
Rmpz_divexact($temp, $order, $_);
Rmpz_powm($check, $_[0], $temp, $_[1]);
if(!Rmpz_cmp_ui($check, 1)) {
$flag = 0;
last;
}
}
}
if($flag) {last}
Rmpz_add_ui($_[0], $_[0], 1);
}
}
sub Rnext_proven {
my $s = Rmpz_sizeinbase($_[1], 2);
my $r = Rmpz_init2($s);
my $c = Rmpz_init2($s);
my $two = Rmpz_init_set_ui(2);
if(!defined($_[5])) {
Rmpz_set($r, $_[1]);
Rmpz_sub_ui($r, $r, 1);
}
else {Rmpz_set($r, $_[5])}
while(1) {
if($_[2]) {print STDERR "."}
if(Rmpz_cmp_si($r, 1) < 0) {die "Failed to find next prime in Rnext_proven function"}
Rmpz_mul_2exp($_[0], $r, 1);
Rmpz_mul($_[0], $_[1], $_[0]);
Rmpz_add_ui($_[0], $_[0], 1);
if(Math::GMPz::trial_div_ul($_[0], $_[4]) == 1) {
Rmpz_set($c, $_[0]);
Rmpz_sub_ui($c, $c, 1);
Rmpz_powm($c, $two, $c, $_[0]);
if(!Rmpz_cmp_ui($c, 1)) {
if($_[2]) {print STDERR "*"}
Rmpz_mul_2exp($c, $r, 1);
Rmpz_powm($c, $two, $c, $_[0]);
Rmpz_sub_ui($c, $c, 1);
Rmpz_gcd($c, $c, $_[0]);
if(!Rmpz_cmp_ui($c, 1)) {last}
}
}
Rmpz_sub_ui($r, $r, 1);
}
if($_[3]) {
if(!Rmpz_probab_prime_p($_[0], 10)) {die "Rnext_proven returned a composite"}
}
if($_[2]) {print STDERR Rmpz_sizeinbase($_[0], 2), "\n"}
}
sub _rewrite {
my $len = length($_[0]);
my @split = ();
my @ret = ();
for(my $i = 0; $i < $len - 1; $i++) {
if(substr($_[0], $i, 1) eq '%') {
if(substr($_[0], $i + 1, 1) eq '%') { $i++ }
else { push(@split, $i) }
}
}
push(@split, $len);
shift(@split);
my $start = 0;
for(@split) {
push(@ret, substr($_[0], $start, $_ - $start));
$start = $_;
}
return @ret;
}
sub Rmpz_printf {
local $| = 1;
push @_, 0 if @_ == 1; # add a dummy second argument
die "Rmpz_printf must pass 2 arguments: format string, and variable" if @_ != 2;
wrap_gmp_printf(@_);
}
sub Rmpz_fprintf {
push @_, 0 if @_ == 2; # add a dummy third argument
die "Rmpz_fprintf must pass 3 arguments: filehandle, format string, and variable" if @_ != 3;
wrap_gmp_fprintf(@_);
}
sub Rmpz_sprintf {
my $len;
if(@_ == 3) { # optional arg wasn't provided
$len = wrap_gmp_sprintf($_[0], $_[1], 0, $_[2]); # Set missing arg to 0
}
else {
die "Rmpz_sprintf must pass 4 arguments: buffer, format string, variable, buflen" if @_ != 4;
$len = wrap_gmp_sprintf(@_);
}
return $len;
}
sub Rmpz_snprintf {
my $len;
if(@_ == 4) { # optional arg wasn't provided
$len = wrap_gmp_sprintf($_[0], $_[1], $_[2], 0, $_[3]); # Set missing arg to 0
}
else {
die "Rmpz_snprintf must pass 5 arguments: buffer, bytes written, format string, variable and buflen" if @_ != 5;
$len = wrap_gmp_snprintf(@_);
}
return $len;
}
sub __GNU_MP_VERSION () {return ___GNU_MP_VERSION()}
sub __GNU_MP_VERSION_MINOR () {return ___GNU_MP_VERSION_MINOR()}
sub __GNU_MP_VERSION_PATCHLEVEL () {return ___GNU_MP_VERSION_PATCHLEVEL()}
sub __GNU_MP_RELEASE () {return ___GNU_MP_RELEASE()}
sub __GMP_CC () {return ___GMP_CC()}
sub __GMP_CFLAGS () {return ___GMP_CFLAGS()}
sub GMP_LIMB_BITS () {return _GMP_LIMB_BITS()}
sub GMP_NAIL_BITS () {return _GMP_NAIL_BITS()}
*zgmp_randseed = \&Math::GMPz::Random::Rgmp_randseed;
*zgmp_randseed_ui = \&Math::GMPz::Random::Rgmp_randseed_ui;
*zgmp_randclear = \&Math::GMPz::Random::Rgmp_randclear;
*zgmp_randinit_default = \&Math::GMPz::Random::Rgmp_randinit_default;
*zgmp_randinit_mt = \&Math::GMPz::Random::Rgmp_randinit_mt;
*zgmp_randinit_lc_2exp = \&Math::GMPz::Random::Rgmp_randinit_lc_2exp;
*zgmp_randinit_lc_2exp_size = \&Math::GMPz::Random::Rgmp_randinit_lc_2exp_size;
*zgmp_randinit_set = \&Math::GMPz::Random::Rgmp_randinit_set;
*zgmp_randinit_default_nobless = \&Math::GMPz::Random::Rgmp_randinit_default_nobless;
*zgmp_randinit_mt_nobless = \&Math::GMPz::Random::Rgmp_randinit_mt_nobless;
*zgmp_randinit_lc_2exp_nobless = \&Math::GMPz::Random::Rgmp_randinit_lc_2exp_nobless;
*zgmp_randinit_lc_2exp_size_nobless = \&Math::GMPz::Random::Rgmp_randinit_lc_2exp_size_nobless;
*zgmp_randinit_set_nobless = \&Math::GMPz::Random::Rgmp_randinit_set_nobless;
*zgmp_urandomb_ui = \&Math::GMPz::Random::Rgmp_urandomb_ui;
*zgmp_urandomm_ui = \&Math::GMPz::Random::Rgmp_urandomm_ui;
1;
__END__