File Coverage

blib/lib/Math/AnyNum.pm
Criterion Covered Total %
statement 12 14 85.7
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 17 19 89.4


line stmt bran cond sub pod time code
1             package Math::AnyNum;
2              
3 1     1   50475 use 5.014;
  1         4  
4 1     1   4 use strict;
  1         2  
  1         16  
5 1     1   4 use warnings;
  1         1  
  1         40  
6              
7 1     1   4 no warnings qw(numeric uninitialized);
  1         2  
  1         26  
8              
9 1     1   118 use Math::MPFR qw();
  0            
  0            
10             use Math::GMPq qw();
11             use Math::GMPz qw();
12             use Math::MPC qw();
13              
14             use POSIX qw(ULONG_MAX LONG_MIN);
15              
16             our $VERSION = '0.17';
17             our ($ROUND, $PREC);
18              
19             BEGIN {
20             $ROUND = Math::MPFR::MPFR_RNDN();
21             $PREC = 192;
22             }
23              
24             use overload
25             '""' => \&stringify,
26             '0+' => \&numify,
27             bool => \&boolify,
28              
29             '+' => \&add,
30             '*' => \&mul,
31              
32             '==' => \&eq,
33             '!=' => \&ne,
34              
35             '&' => \&and,
36             '|' => \&or,
37             '^' => \&xor,
38             '~' => \¬,
39              
40             '>' => sub { $_[2] ? (goto <) : (goto >) },
41             '>=' => sub { $_[2] ? (goto &le) : (goto &ge) },
42             '<' => sub { $_[2] ? (goto >) : (goto <) },
43             '<=' => sub { $_[2] ? (goto &ge) : (goto &le) },
44              
45             '<=>' => sub { $_[2] ? -(&cmp($_[0], $_[1]) // return undef) : &cmp($_[0], $_[1]) },
46              
47             '>>' => sub { @_ = ($_[1], $_[0]) if $_[2]; goto &rsft },
48             '<<' => sub { @_ = ($_[1], $_[0]) if $_[2]; goto &lsft },
49             '/' => sub { @_ = ($_[1], $_[0]) if $_[2]; goto &div },
50             '-' => sub { @_ = ($_[1], $_[0]) if $_[2]; goto &sub },
51              
52             '**' => sub { @_ = $_[2] ? @_[1, 0] : @_[0, 1]; goto &pow },
53             '%' => sub { @_ = $_[2] ? @_[1, 0] : @_[0, 1]; goto &mod },
54              
55             atan2 => sub { @_ = $_[2] ? @_[1, 0] : @_[0, 1]; goto &atan2 },
56              
57             eq => sub { "$_[0]" eq "$_[1]" },
58             ne => sub { "$_[0]" ne "$_[1]" },
59              
60             cmp => sub { $_[2] ? ("$_[1]" cmp $_[0]->stringify) : ($_[0]->stringify cmp "$_[1]") },
61              
62             neg => \&neg,
63             sin => \&sin,
64             cos => \&cos,
65             exp => \&exp,
66             log => \&ln,
67             int => \&int,
68             abs => \&abs,
69             sqrt => \&sqrt;
70              
71             {
72              
73             my %const = ( # prototypes are assigned in import()
74             e => \&e,
75             phi => \&phi,
76             tau => \&tau,
77             pi => \&pi,
78             ln2 => \&ln2,
79             euler => \&euler,
80             i => \&i,
81             catalan => \&catalan,
82             Inf => \&inf,
83             NaN => \&nan,
84             );
85              
86             my %trig = (
87             sin => sub (_) { goto &sin }, # built-in function
88             sinh => \&sinh,
89             asin => \&asin,
90             asinh => \&asinh,
91              
92             cos => sub (_) { goto &cos }, # built-in function
93             cosh => \&cosh,
94             acos => \&acos,
95             acosh => \&acosh,
96              
97             tan => \&tan,
98             tanh => \&tanh,
99             atan => \&atan,
100             atanh => \&atanh,
101              
102             cot => \&cot,
103             coth => \&coth,
104             acot => \&acot,
105             acoth => \&acoth,
106              
107             sec => \&sec,
108             sech => \&sech,
109             asec => \&asec,
110             asech => \&asech,
111              
112             csc => \&csc,
113             csch => \&csch,
114             acsc => \&acsc,
115             acsch => \&acsch,
116              
117             atan2 => \&atan2,
118             deg2rad => \°2rad,
119             rad2deg => \&rad2deg,
120             );
121              
122             my %special = (
123             beta => \&beta,
124             zeta => \&zeta,
125             eta => \&eta,
126              
127             gamma => \&gamma,
128             lgamma => \&lgamma,
129             lngamma => \&lngamma,
130             digamma => \&digamma,
131              
132             Ai => \&Ai,
133             Ei => \&Ei,
134             Li => \&Li,
135             Li2 => \&Li2,
136              
137             lgrt => \&lgrt,
138             LambertW => \&LambertW,
139              
140             BesselJ => \&BesselJ,
141             BesselY => \&BesselY,
142              
143             pow => \&pow,
144             sqr => \&sqr,
145             norm => \&norm,
146             sqrt => sub (_) { goto &sqrt }, # built-in function
147             cbrt => \&cbrt,
148             root => \&root,
149              
150             exp => sub (_) { goto &exp }, # built-in function
151             exp2 => \&exp2,
152             exp10 => \&exp10,
153              
154             ln => sub ($) { goto &ln }, # used in overloading
155             log => \&log, # built-in function
156             log2 => \&log2,
157             log10 => \&log10,
158              
159             mod => \&mod,
160             abs => sub (_) { goto &abs }, # built-in function
161              
162             erf => \&erf,
163             erfc => \&erfc,
164              
165             hypot => \&hypot,
166             agm => \&agm,
167              
168             bernreal => \&bernreal,
169             harmreal => \&harmreal,
170              
171             polygonal_root => \&polygonal_root,
172             polygonal_root2 => \&polygonal_root2,
173             );
174              
175             my %ntheory = (
176             factorial => \&factorial,
177             dfactorial => \&dfactorial,
178             mfactorial => \&mfactorial,
179             primorial => \&primorial,
180             binomial => \&binomial,
181              
182             rising_factorial => \&rising_factorial,
183             falling_factorial => \&falling_factorial,
184              
185             lucas => \&lucas,
186             fibonacci => \&fibonacci,
187              
188             faulhaber_sum => \&faulhaber_sum,
189              
190             bernfrac => \&bernfrac,
191             harmfrac => \&harmfrac,
192              
193             lcm => \&lcm,
194             gcd => \&gcd,
195             valuation => \&valuation,
196             kronecker => \&kronecker,
197              
198             remdiv => \&remdiv,
199             divmod => \&divmod,
200              
201             iadd => \&iadd,
202             isub => \&isub,
203             imul => \&imul,
204             idiv => \&idiv,
205             imod => \&imod,
206              
207             ipow => \&ipow,
208             ipow2 => \&ipow2,
209             ipow10 => \&ipow10,
210              
211             iroot => \&iroot,
212             isqrt => \&isqrt,
213             icbrt => \&icbrt,
214              
215             ilog => \&ilog,
216             ilog2 => \&ilog2,
217             ilog10 => \&ilog10,
218              
219             isqrtrem => \&isqrtrem,
220             irootrem => \&irootrem,
221              
222             polygonal => \&polygonal,
223             ipolygonal_root => \&ipolygonal_root,
224             ipolygonal_root2 => \&ipolygonal_root2,
225              
226             powmod => \&powmod,
227             invmod => \&invmod,
228              
229             is_power => \&is_power,
230             is_square => \&is_square,
231             is_polygonal => \&is_polygonal,
232             is_polygonal2 => \&is_polygonal2,
233              
234             is_prime => \&is_prime,
235             is_coprime => \&is_coprime,
236             next_prime => \&next_prime,
237             );
238              
239             my %misc = (
240             rand => \&rand,
241             irand => \&irand,
242              
243             seed => \&seed,
244             iseed => \&iseed,
245              
246             floor => \&floor,
247             ceil => \&ceil,
248             round => \&round,
249             sgn => \&sgn,
250             acmp => \&acmp,
251              
252             popcount => \&popcount,
253              
254             neg => sub ($) { goto &neg }, # used in overloading
255             inv => \&inv,
256             conj => \&conj,
257             real => \&real,
258             imag => \&imag,
259             reals => \&reals,
260              
261             int => sub (_) { goto &int }, # built-in function
262             rat => \&rat,
263             float => \&float,
264             complex => \&complex,
265              
266             numerator => \&numerator,
267             denominator => \&denominator,
268             nude => \&nude,
269              
270             digits => \&digits,
271              
272             as_bin => \&as_bin,
273             as_hex => \&as_hex,
274             as_oct => \&as_oct,
275             as_int => \&as_int,
276             as_frac => \&as_frac,
277             as_dec => \&as_dec,
278              
279             rat_approx => \&rat_approx,
280              
281             is_inf => \&is_inf,
282             is_ninf => \&is_ninf,
283             is_neg => \&is_neg,
284             is_pos => \&is_pos,
285             is_nan => \&is_nan,
286             is_rat => \&is_rat,
287             is_real => \&is_real,
288             is_imag => \&is_imag,
289             is_int => \&is_int,
290             is_complex => \&is_complex,
291             is_zero => \&is_zero,
292             is_one => \&is_one,
293             is_mone => \&is_mone,
294              
295             is_odd => \&is_odd,
296             is_even => \&is_even,
297             is_div => \&is_div,
298             );
299              
300             sub import {
301             shift;
302              
303             my $caller = caller(0);
304              
305             while (@_) {
306             my $name = shift(@_);
307              
308             if ($name eq ':overload') {
309             overload::constant
310             integer => sub { bless \Math::GMPz::Rmpz_init_set_ui($_[0]) },
311             float => sub { bless \_str2obj($_[0]) },
312             binary => sub {
313             my $const = ($_[0] =~ tr/_//dr);
314             my $prefix = substr($const, 0, 2);
315             bless \(
316             $prefix eq '0x' ? Math::GMPz::Rmpz_init_set_str(substr($const, 2) || 0, 16)
317             : $prefix eq '0b' ? Math::GMPz::Rmpz_init_set_str(substr($const, 2) || 0, 2)
318             : Math::GMPz::Rmpz_init_set_str(substr($const, 1) || 0, 8)
319             );
320             };
321              
322             # Export 'Inf', 'NaN' and 'i' as constants
323             foreach my $pair (['Inf', inf()], ['NaN', nan()], ['i', i()]) {
324             my $sub = $caller . '::' . $pair->[0];
325             no strict 'refs';
326             no warnings 'redefine';
327             my $value = $pair->[1];
328             *$sub = sub () { $value };
329             }
330             }
331             elsif (exists $const{$name}) {
332             no strict 'refs';
333             no warnings 'redefine';
334             my $caller_sub = $caller . '::' . $name;
335             my $sub = $const{$name};
336             my $value = $sub->();
337             *$caller_sub = sub() { $value }
338             }
339             elsif ( exists($special{$name})
340             or exists($trig{$name})
341             or exists($ntheory{$name})
342             or exists($misc{$name})) {
343             no strict 'refs';
344             no warnings 'redefine';
345             my $caller_sub = $caller . '::' . $name;
346             *$caller_sub = $ntheory{$name} // $special{$name} // $trig{$name} // $misc{$name};
347             }
348             elsif ($name eq ':trig') {
349             push @_, keys(%trig);
350             }
351             elsif ($name eq ':ntheory') {
352             push @_, keys(%ntheory);
353             }
354             elsif ($name eq ':special') {
355             push @_, keys(%special);
356             }
357             elsif ($name eq ':misc') {
358             push @_, keys(%misc);
359             }
360             elsif ($name eq ':all') {
361             push @_, keys(%const), keys(%trig), keys(%special), keys(%ntheory), keys(%misc);
362             }
363             elsif ($name eq 'PREC') {
364             my $prec = CORE::int(shift(@_));
365             if ( $prec < Math::MPFR::RMPFR_PREC_MIN()
366             or $prec > Math::MPFR::RMPFR_PREC_MAX()) {
367             die "invalid value for <>: must be between "
368             . Math::MPFR::RMPFR_PREC_MIN() . " and "
369             . Math::MPFR::RMPFR_PREC_MAX()
370             . ", but got <<$prec>>";
371             }
372             $PREC = $prec;
373             }
374             else {
375             die "unknown import: <<$name>>";
376             }
377             }
378             return;
379             }
380              
381             sub unimport {
382             overload::remove_constant('binary', '', 'float', '', 'integer');
383             }
384             }
385              
386             # Converts a string into an mpq object
387             sub _str2obj {
388             my ($s) = @_;
389              
390             $s || goto &_zero;
391              
392             $s = lc($s);
393              
394             if ($s eq 'inf' or $s eq '+inf') {
395             goto &_inf;
396             }
397             elsif ($s eq '-inf') {
398             goto &_ninf;
399             }
400             elsif ($s eq 'nan') {
401             goto &_nan;
402             }
403              
404             # Remove underscores
405             $s =~ tr/_//d;
406              
407             # Performance improvement for Perl integers
408             if (CORE::int($s) eq $s and $s > LONG_MIN and $s < ULONG_MAX) {
409             return (
410             $s < 0
411             ? Math::GMPz::Rmpz_init_set_si($s)
412             : Math::GMPz::Rmpz_init_set_ui($s)
413             );
414             }
415              
416             # Complex number
417             if (substr($s, -1) eq 'i') {
418              
419             if ($s eq 'i' or $s eq '+i') {
420             my $r = Math::MPC::Rmpc_init2($PREC);
421             Math::MPC::Rmpc_set_ui_ui($r, 0, 1, $ROUND);
422             return $r;
423             }
424             elsif ($s eq '-i') {
425             my $r = Math::MPC::Rmpc_init2($PREC);
426             Math::MPC::Rmpc_set_si_si($r, 0, -1, $ROUND);
427             return $r;
428             }
429              
430             my ($re, $im);
431              
432             state $numeric_re = qr/[+-]?+(?=\.?[0-9])[0-9]*+(?:\.[0-9]++)?(?:[Ee](?:[+-]?+[0-9]+))?/;
433             state $unsigned_re = qr/(?=\.?[0-9])[0-9]*+(?:\.[0-9]++)?(?:[Ee](?:[+-]?+[0-9]+))?/;
434              
435             if ($s =~ /^($numeric_re)\s*([-+])\s*($unsigned_re)i\z/o) {
436             ($re, $im) = ($1, $3);
437             $im = "-$im" if $2 eq '-';
438             }
439             elsif ($s =~ /^($numeric_re)i\z/o) {
440             ($re, $im) = (0, $1);
441             }
442             elsif ($s =~ /^($numeric_re)\s*([-+])\s*i\z/o) {
443             ($re, $im) = ($1, 1);
444             $im = -1 if $2 eq '-';
445             }
446              
447             if (defined($re) and defined($im)) {
448              
449             my $r = Math::MPC::Rmpc_init2($PREC);
450              
451             $re = _str2obj($re);
452             $im = _str2obj($im);
453              
454             my $sig = join(' ', ref($re), ref($im));
455              
456             if ($sig eq q{Math::MPFR Math::MPFR}) {
457             Math::MPC::Rmpc_set_fr_fr($r, $re, $im, $ROUND);
458             }
459             elsif ($sig eq q{Math::GMPz Math::GMPz}) {
460             Math::MPC::Rmpc_set_z_z($r, $re, $im, $ROUND);
461             }
462             elsif ($sig eq q{Math::GMPz Math::MPFR}) {
463             Math::MPC::Rmpc_set_z_fr($r, $re, $im, $ROUND);
464             }
465             elsif ($sig eq q{Math::MPFR Math::GMPz}) {
466             Math::MPC::Rmpc_set_fr_z($r, $re, $im, $ROUND);
467             }
468             else { # this should never happen
469             $re = _any2mpfr($re);
470             $im = _any2mpfr($im);
471             Math::MPC::Rmpc_set_fr_fr($r, $re, $im, $ROUND);
472             }
473              
474             return $r;
475             }
476             }
477              
478             # Floating point value
479             if ($s =~ tr/e.//) {
480             my $r = Math::MPFR::Rmpfr_init2($PREC);
481             if (Math::MPFR::Rmpfr_set_str($r, $s, 10, $ROUND)) {
482             Math::MPFR::Rmpfr_set_nan($r);
483             }
484             return $r;
485             }
486              
487             # Fractional value
488             if (index($s, '/') != -1 and $s =~ m{^\s*[-+]?[0-9]+\s*/\s*[-+]?[1-9]+[0-9]*\s*\z}) {
489             my $r = Math::GMPq::Rmpq_init();
490             Math::GMPq::Rmpq_set_str($r, $s, 10);
491             Math::GMPq::Rmpq_canonicalize($r);
492             return $r;
493             }
494              
495             $s =~ s/^\+//;
496              
497             eval { Math::GMPz::Rmpz_init_set_str($s, 10) } // goto &_nan;
498             }
499              
500             # Parse a base-10 string as a base-10 fraction
501             sub _str2frac {
502             my ($str) = @_;
503              
504             my $sign = substr($str, 0, 1);
505             if ($sign eq '-') {
506             substr($str, 0, 1, '');
507             $sign = '-';
508             }
509             else {
510             substr($str, 0, 1, '') if ($sign eq '+');
511             $sign = '';
512             }
513              
514             my $i;
515             if (($i = index($str, 'e')) != -1) {
516              
517             my $exp = substr($str, $i + 1);
518              
519             # Handle specially numbers with very big exponents
520             # (not a very good solution, but this will happen very rarely, if ever)
521             if (CORE::abs($exp) >= 1000000) {
522             Math::MPFR::Rmpfr_set_str((my $mpfr = Math::MPFR::Rmpfr_init2($PREC)), "$sign$str", 10, $ROUND);
523             Math::MPFR::Rmpfr_get_q((my $mpq = Math::GMPq::Rmpq_init()), $mpfr);
524             return Math::GMPq::Rmpq_get_str($mpq, 10);
525             }
526              
527             my ($before, $after) = split(/\./, substr($str, 0, $i));
528              
529             if (!defined($after)) { # return faster for numbers like "13e2"
530             if ($exp >= 0) {
531             return ("$sign$before" . ('0' x $exp));
532             }
533             else {
534             $after = '';
535             }
536             }
537              
538             my $numerator = "$before$after";
539             my $denominator = "1";
540              
541             if ($exp < 1) {
542             $denominator .= '0' x (CORE::abs($exp) + CORE::length($after));
543             }
544             else {
545             my $diff = ($exp - CORE::length($after));
546             if ($diff >= 0) {
547             $numerator .= '0' x $diff;
548             }
549             else {
550             my $s = "$before$after";
551             substr($s, $exp + CORE::length($before), 0, '.');
552             return _str2frac("$sign$s");
553             }
554             }
555              
556             "$sign$numerator/$denominator";
557             }
558             elsif (($i = index($str, '.')) != -1) {
559             my ($before, $after) = (substr($str, 0, $i), substr($str, $i + 1));
560             if (($after =~ tr/0//) == CORE::length($after)) {
561             return "$sign$before";
562             }
563             $sign . ("$before$after/1" =~ s/^0+//r) . ('0' x CORE::length($after));
564             }
565             else {
566             "$sign$str";
567             }
568             }
569              
570             #
571             ## MPZ
572             #
573             sub _mpz2mpq {
574             my $r = Math::GMPq::Rmpq_init();
575             Math::GMPq::Rmpq_set_z($r, $_[0]);
576             $r;
577             }
578              
579             sub _mpz2mpfr {
580             my $r = Math::MPFR::Rmpfr_init2($PREC);
581             Math::MPFR::Rmpfr_set_z($r, $_[0], $ROUND);
582             $r;
583             }
584              
585             sub _mpz2mpc {
586             my $r = Math::MPC::Rmpc_init2($PREC);
587             Math::MPC::Rmpc_set_z($r, $_[0], $ROUND);
588             $r;
589             }
590              
591             #
592             ## MPQ
593             #
594              
595             sub _mpq2mpz {
596             my $z = Math::GMPz::Rmpz_init();
597             Math::GMPz::Rmpz_set_q($z, $_[0]);
598             $z;
599             }
600              
601             sub _mpq2mpfr {
602             my $r = Math::MPFR::Rmpfr_init2($PREC);
603             Math::MPFR::Rmpfr_set_q($r, $_[0], $ROUND);
604             $r;
605             }
606              
607             sub _mpq2mpc {
608             my $r = Math::MPC::Rmpc_init2($PREC);
609             Math::MPC::Rmpc_set_q($r, $_[0], $ROUND);
610             $r;
611             }
612              
613             #
614             ## MPFR
615             #
616              
617             sub _mpfr2mpc {
618             my $r = Math::MPC::Rmpc_init2($PREC);
619             Math::MPC::Rmpc_set_fr($r, $_[0], $ROUND);
620             $r;
621             }
622              
623             #
624             ## Any
625             #
626              
627             sub _any2mpc {
628             my ($x) = @_;
629              
630             ref($x) eq 'Math::MPC' && return $x;
631             ref($x) eq 'Math::GMPq' && goto &_mpq2mpc;
632             ref($x) eq 'Math::GMPz' && goto &_mpz2mpc;
633              
634             goto &_mpfr2mpc;
635             }
636              
637             sub _any2mpfr {
638             my ($x) = @_;
639              
640             ref($x) eq 'Math::MPFR' && return $x;
641             ref($x) eq 'Math::GMPq' && goto &_mpq2mpfr;
642             ref($x) eq 'Math::GMPz' && goto &_mpz2mpfr;
643              
644             my $fr = Math::MPFR::Rmpfr_init2($PREC);
645             Math::MPC::RMPC_IM($fr, $x);
646              
647             Math::MPFR::Rmpfr_zero_p($fr)
648             ? Math::MPC::RMPC_RE($fr, $x)
649             : Math::MPFR::Rmpfr_set_nan($fr);
650              
651             $fr;
652             }
653              
654             sub _any2mpz {
655             my ($x) = @_;
656              
657             ref($x) eq 'Math::GMPz' && return $x;
658             ref($x) eq 'Math::GMPq' && goto &_mpq2mpz;
659              
660             if (ref($x) eq 'Math::MPFR') {
661             if (Math::MPFR::Rmpfr_number_p($x)) {
662             my $z = Math::GMPz::Rmpz_init();
663             Math::MPFR::Rmpfr_get_z($z, $x, Math::MPFR::MPFR_RNDZ);
664             return $z;
665             }
666             return;
667             }
668              
669             (@_) = _any2mpfr($x);
670             goto &_any2mpz;
671             }
672              
673             sub _any2mpq {
674             my ($x) = @_;
675              
676             ref($x) eq 'Math::GMPq' && return $x;
677             ref($x) eq 'Math::GMPz' && goto &_mpz2mpq;
678              
679             if (ref($x) eq 'Math::MPFR') {
680             if (Math::MPFR::Rmpfr_number_p($x)) {
681             my $q = Math::GMPq::Rmpq_init();
682             Math::MPFR::Rmpfr_get_q($q, $x);
683             return $q;
684             }
685             return;
686             }
687              
688             (@_) = _any2mpfr($x);
689             goto &_any2mpq;
690             }
691              
692             sub _any2ui {
693             my ($x) = @_;
694             goto(ref($x) =~ tr/:/_/rs);
695              
696             Math_GMPz: {
697              
698             if (Math::GMPz::Rmpz_fits_ulong_p($x)) {
699             goto &Math::GMPz::Rmpz_get_ui;
700             }
701              
702             return;
703             }
704              
705             Math_GMPq: {
706              
707             if (Math::GMPq::Rmpq_integer_p($x)) {
708             @_ = ($x = _mpq2mpz($x));
709             goto Math_GMPz;
710             }
711              
712             my $d = CORE::int(Math::GMPq::Rmpq_get_d($x));
713             return (($d < 0 or $d > ULONG_MAX) ? undef : $d);
714             }
715              
716             Math_MPFR: {
717              
718             if (Math::MPFR::Rmpfr_integer_p($x) and Math::MPFR::Rmpfr_fits_ulong_p($x, $ROUND)) {
719             push @_, $ROUND;
720             goto &Math::MPFR::Rmpfr_get_ui;
721             }
722              
723             if (Math::MPFR::Rmpfr_number_p($x)) {
724             my $d = CORE::int(Math::MPFR::Rmpfr_get_d($x, $ROUND));
725             return (($d < 0 or $d > ULONG_MAX) ? undef : $d);
726             }
727              
728             return;
729             }
730              
731             Math_MPC: {
732             @_ = ($x = _any2mpfr($x));
733             goto Math_MPFR;
734             }
735             }
736              
737             sub _any2si {
738             my ($x) = @_;
739             goto(ref($x) =~ tr/:/_/rs);
740              
741             Math_GMPz: {
742              
743             if (Math::GMPz::Rmpz_fits_slong_p($x)) {
744             goto &Math::GMPz::Rmpz_get_si;
745             }
746              
747             if (Math::GMPz::Rmpz_fits_ulong_p($x)) {
748             goto &Math::GMPz::Rmpz_get_ui;
749             }
750              
751             return;
752             }
753              
754             Math_GMPq: {
755              
756             if (Math::GMPq::Rmpq_integer_p($x)) {
757             @_ = ($x = _mpq2mpz($x));
758             goto Math_GMPz;
759             }
760              
761             my $d = CORE::int(Math::GMPq::Rmpq_get_d($x));
762             return (($d < LONG_MIN or $d > ULONG_MAX) ? undef : $d);
763             }
764              
765             Math_MPFR: {
766              
767             if (Math::MPFR::Rmpfr_integer_p($x)) {
768             if (Math::MPFR::Rmpfr_fits_slong_p($x, $ROUND)) {
769             push @_, $ROUND;
770             goto &Math::MPFR::Rmpfr_get_si;
771             }
772              
773             if (Math::MPFR::Rmpfr_fits_ulong_p($x, $ROUND)) {
774             push @_, $ROUND;
775             goto &Math::MPFR::Rmpfr_get_ui;
776             }
777             }
778              
779             if (Math::MPFR::Rmpfr_number_p($x)) {
780             my $d = CORE::int(Math::MPFR::Rmpfr_get_d($x, $ROUND));
781             return (($d < LONG_MIN or $d > ULONG_MAX) ? undef : $d);
782             }
783              
784             return;
785             }
786              
787             Math_MPC: {
788             @_ = ($x = _any2mpfr($x));
789             goto Math_MPFR;
790             }
791             }
792              
793             #
794             ## Anything to MPFR (including strings)
795             #
796             sub _star2mpfr {
797             my ($x) = @_;
798              
799             $x =
800             ref($x) eq __PACKAGE__ ? $$x
801             : ref($x) ? _star2obj($x)
802             : _str2obj($x);
803              
804             ref($x) eq 'Math::MPFR' and return $x;
805              
806             (@_) = $x;
807             ref($x) eq 'Math::GMPz' && goto &_mpz2mpfr;
808             ref($x) eq 'Math::GMPq' && goto &_mpq2mpfr;
809             goto &_any2mpfr;
810             }
811              
812             #
813             ## Anything to GMPz (including strings)
814             #
815             sub _star2mpz {
816             my ($x) = @_;
817              
818             $x =
819             ref($x) eq __PACKAGE__ ? $$x
820             : ref($x) ? _star2obj($x)
821             : _str2obj($x);
822              
823             ref($x) eq 'Math::GMPz' and return $x;
824              
825             (@_) = $x;
826             ref($x) eq 'Math::GMPq' and goto &_mpq2mpz;
827             goto &_any2mpz;
828             }
829              
830             #
831             ## Anything to MPFR or MPC, in this order (including strings)
832             #
833             sub _star2mpfr_mpc {
834             my ($x) = @_;
835              
836             $x =
837             ref($x) eq __PACKAGE__ ? $$x
838             : ref($x) ? _star2obj($x)
839             : _str2obj($x);
840              
841             if ( ref($x) eq 'Math::MPFR'
842             or ref($x) eq 'Math::MPC') {
843             return $x;
844             }
845              
846             (@_) = $x;
847             ref($x) eq 'Math::GMPz' && goto &_mpz2mpfr;
848             ref($x) eq 'Math::GMPq' && goto &_mpq2mpfr;
849             goto &_any2mpfr; # this should not happen
850             }
851              
852             # Anything to a {GMP*, MPFR or MPC} object
853             sub _star2obj {
854             my ($x) = @_;
855              
856             ref($x) || goto &_str2obj;
857              
858             if (ref($x) eq __PACKAGE__) {
859             $$x;
860             }
861             elsif ( ref($x) eq 'Math::GMPz'
862             or ref($x) eq 'Math::GMPq'
863             or ref($x) eq 'Math::MPFR'
864             or ref($x) eq 'Math::MPC') {
865             $x;
866             }
867             else {
868             (@_) = "$x";
869             goto &_str2obj;
870             }
871             }
872              
873             sub new {
874             my ($class, $num, $base) = @_;
875              
876             my $ref = ref($num);
877              
878             # Special string values
879             if (!$ref and (!defined($base) or CORE::int($base) == 10)) {
880             return bless \_str2obj($num), $class;
881             }
882              
883             # Special case
884             if (!defined($base) and $ref eq __PACKAGE__) {
885             return $num;
886             }
887              
888             # Number with base
889             if (defined($base) and CORE::int($base) != 10) {
890              
891             my $int_base = CORE::int($base);
892              
893             if ($int_base < 2 or $int_base > 36) {
894             require Carp;
895             Carp::croak("base must be between 2 and 36, got $base");
896             }
897              
898             $num = defined($num) ? "$num" : '0';
899              
900             if (index($num, '/') != -1) {
901             my $r = Math::GMPq::Rmpq_init();
902             eval { Math::GMPq::Rmpq_set_str($r, $num, $int_base); 1 } // goto &nan;
903              
904             if (Math::GMPq::Rmpq_get_str($r, 10) !~ m{^\s*[-+]?[0-9]+\s*/\s*[-+]?[1-9]+[0-9]*\s*\z}) {
905             goto &nan;
906             }
907              
908             Math::GMPq::Rmpq_canonicalize($r);
909             return bless \$r, $class;
910             }
911             elsif (index($num, '.') != -1) {
912             my $r = Math::MPFR::Rmpfr_init2($PREC);
913             if (Math::MPFR::Rmpfr_set_str($r, $num, $int_base, $ROUND)) {
914             Math::MPFR::Rmpfr_set_nan($r);
915             }
916             return bless \$r, $class;
917             }
918             else {
919             return bless \(eval { Math::GMPz::Rmpz_init_set_str($num, $int_base) } // goto &nan), $class;
920             }
921             }
922              
923             bless \_star2obj($num), $class;
924             }
925              
926             sub new_si {
927             my ($class, $si) = @_;
928             bless \Math::GMPz::Rmpz_init_set_si($si), $class;
929             }
930              
931             sub new_ui {
932             my ($class, $ui) = @_;
933             bless \Math::GMPz::Rmpz_init_set_ui($ui), $class;
934             }
935              
936             sub new_z {
937             my ($class, $str, $base) = @_;
938             bless \Math::GMPz::Rmpz_init_set_str($str, $base // 10), $class;
939             }
940              
941             sub new_q {
942             my ($class, $num, $den, $base) = @_;
943             my $r = Math::GMPq::Rmpq_init();
944              
945             if (defined($den)) {
946             Math::GMPq::Rmpq_set_str($r, "$num/$den", $base // 10);
947             }
948             else {
949             Math::GMPq::Rmpq_set_str($r, "$num", $base // 10);
950             }
951              
952             Math::GMPq::Rmpq_canonicalize($r);
953             bless \$r, $class;
954             }
955              
956             sub new_f {
957             my ($class, $str, $base) = @_;
958             my $r = Math::MPFR::Rmpfr_init2($PREC);
959             Math::MPFR::Rmpfr_set_str($r, $str, $base // 10, $ROUND);
960             bless \$r, $class;
961             }
962              
963             sub new_c {
964             my ($class, $real, $imag, $base) = @_;
965              
966             my $c = Math::MPC::Rmpc_init2($PREC);
967              
968             if (defined($imag)) {
969             my $re = Math::MPFR::Rmpfr_init2($PREC);
970             my $im = Math::MPFR::Rmpfr_init2($PREC);
971              
972             Math::MPFR::Rmpfr_set_str($re, $real, $base // 10, $ROUND);
973             Math::MPFR::Rmpfr_set_str($im, $imag, $base // 10, $ROUND);
974              
975             Math::MPC::Rmpc_set_fr_fr($c, $re, $im, $ROUND);
976             }
977             else {
978             Math::MPC::Rmpc_set_str($c, $real, $base // 10, $ROUND);
979             }
980              
981             bless \$c, $class;
982             }
983              
984             sub _nan {
985             state $nan = do {
986             my $r = Math::MPFR::Rmpfr_init2($PREC);
987             Math::MPFR::Rmpfr_set_nan($r);
988             $r;
989             };
990             }
991              
992             sub nan {
993             state $nan = do {
994             my $r = Math::MPFR::Rmpfr_init2($PREC);
995             Math::MPFR::Rmpfr_set_nan($r);
996             bless \$r;
997             };
998             }
999              
1000             sub _inf {
1001             state $inf = do {
1002             my $r = Math::MPFR::Rmpfr_init2($PREC);
1003             Math::MPFR::Rmpfr_set_inf($r, 1);
1004             $r;
1005             };
1006             }
1007              
1008             sub inf {
1009             state $inf = do {
1010             my $r = Math::MPFR::Rmpfr_init2($PREC);
1011             Math::MPFR::Rmpfr_set_inf($r, 1);
1012             bless \$r;
1013             };
1014             }
1015              
1016             sub _ninf {
1017             state $ninf = do {
1018             my $r = Math::MPFR::Rmpfr_init2($PREC);
1019             Math::MPFR::Rmpfr_set_inf($r, -1);
1020             $r;
1021             };
1022             }
1023              
1024             sub ninf {
1025             state $ninf = do {
1026             my $r = Math::MPFR::Rmpfr_init2($PREC);
1027             Math::MPFR::Rmpfr_set_inf($r, -1);
1028             bless \$r;
1029             };
1030             }
1031              
1032             sub _zero {
1033             state $zero = Math::GMPz::Rmpz_init_set_ui(0);
1034             }
1035              
1036             sub zero {
1037             state $zero = do {
1038             my $r = Math::GMPz::Rmpz_init_set_ui(0);
1039             bless \$r;
1040             };
1041             }
1042              
1043             sub _one {
1044             state $one = Math::GMPz::Rmpz_init_set_ui(1);
1045             }
1046              
1047             sub one {
1048             state $one = do {
1049             my $r = Math::GMPz::Rmpz_init_set_ui(1);
1050             bless \$r;
1051             };
1052             }
1053              
1054             sub _mone {
1055             state $mone = Math::GMPz::Rmpz_init_set_si(-1);
1056             }
1057              
1058             sub mone {
1059             state $mone = do {
1060             my $r = Math::GMPz::Rmpz_init_set_si(-1);
1061             bless \$r;
1062             };
1063             }
1064              
1065             #
1066             ## CONSTANTS
1067             #
1068              
1069             sub pi {
1070             my $pi = Math::MPFR::Rmpfr_init2($PREC);
1071             Math::MPFR::Rmpfr_const_pi($pi, $ROUND);
1072             bless \$pi;
1073             }
1074              
1075             sub tau {
1076             my $tau = Math::MPFR::Rmpfr_init2($PREC);
1077             Math::MPFR::Rmpfr_const_pi($tau, $ROUND);
1078             Math::MPFR::Rmpfr_mul_2ui($tau, $tau, 1, $ROUND);
1079             bless \$tau;
1080             }
1081              
1082             sub ln2 {
1083             my $ln2 = Math::MPFR::Rmpfr_init2($PREC);
1084             Math::MPFR::Rmpfr_const_log2($ln2, $ROUND);
1085             bless \$ln2;
1086             }
1087              
1088             sub euler {
1089             my $euler = Math::MPFR::Rmpfr_init2($PREC);
1090             Math::MPFR::Rmpfr_const_euler($euler, $ROUND);
1091             bless \$euler;
1092             }
1093              
1094             sub catalan {
1095             my $catalan = Math::MPFR::Rmpfr_init2($PREC);
1096             Math::MPFR::Rmpfr_const_catalan($catalan, $ROUND);
1097             bless \$catalan;
1098             }
1099              
1100             sub i {
1101             my $i = Math::MPC::Rmpc_init2($PREC);
1102             Math::MPC::Rmpc_set_ui_ui($i, 0, 1, $ROUND);
1103             bless \$i;
1104             }
1105              
1106             sub e {
1107             state $one_f = (Math::MPFR::Rmpfr_init_set_ui_nobless(1, $ROUND))[0];
1108             my $e = Math::MPFR::Rmpfr_init2($PREC);
1109             Math::MPFR::Rmpfr_exp($e, $one_f, $ROUND);
1110             bless \$e;
1111             }
1112              
1113             sub phi {
1114             state $five4_f = (Math::MPFR::Rmpfr_init_set_d_nobless(1.25, $ROUND))[0];
1115              
1116             my $phi = Math::MPFR::Rmpfr_init2($PREC);
1117             Math::MPFR::Rmpfr_sqrt($phi, $five4_f, $ROUND);
1118             Math::MPFR::Rmpfr_add_d($phi, $phi, 0.5, $ROUND);
1119              
1120             bless \$phi;
1121             }
1122              
1123             #
1124             ## OTHER
1125             #
1126              
1127             sub stringify { # used in overloading
1128             require Math::AnyNum::stringify;
1129             (@_) = (${$_[0]});
1130             goto &__stringify__;
1131             }
1132              
1133             sub numify { # used in overloading
1134             require Math::AnyNum::numify;
1135             (@_) = (${$_[0]});
1136             goto &__numify__;
1137             }
1138              
1139             sub boolify { # used in overloading
1140             require Math::AnyNum::boolify;
1141             (@_) = (${$_[0]});
1142             goto &__boolify__;
1143             }
1144              
1145             #
1146             ## EQUALITY
1147             #
1148              
1149             sub eq { # used in overloading
1150             require Math::AnyNum::eq;
1151             my ($x, $y) = @_;
1152              
1153             if (ref($y) eq __PACKAGE__) {
1154             (@_) = ($$x, $$y);
1155             goto &__eq__;
1156             }
1157              
1158             if (!ref($y)) {
1159             if (CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
1160             (@_) = ($$x, $y);
1161             }
1162             else {
1163             (@_) = ($$x, _str2obj($y));
1164             }
1165             goto &__eq__;
1166             }
1167              
1168             (@_) = ($$x, _star2obj($y));
1169             goto &__eq__;
1170             }
1171              
1172             #
1173             ## INEQUALITY
1174             #
1175              
1176             sub ne { # used in overloading
1177             require Math::AnyNum::ne;
1178             my ($x, $y) = @_;
1179              
1180             if (ref($y) eq __PACKAGE__) {
1181             (@_) = ($$x, $$y);
1182             goto &__ne__;
1183             }
1184              
1185             if (!ref($y)) {
1186             if (CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
1187             (@_) = ($$x, $y);
1188             }
1189             else {
1190             (@_) = ($$x, _str2obj($y));
1191             }
1192             goto &__ne__;
1193             }
1194              
1195             (@_) = ($$x, _star2obj($y));
1196             goto &__ne__;
1197             }
1198              
1199             #
1200             ## COMPARISON
1201             #
1202              
1203             sub cmp ($$) {
1204             require Math::AnyNum::cmp;
1205             my ($x, $y) = @_;
1206              
1207             if (ref($y) eq __PACKAGE__) {
1208             (@_) = ($$x, $$y);
1209             goto &__cmp__;
1210             }
1211              
1212             if (!ref($y)) {
1213             if (CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
1214             (@_) = ($$x, $y);
1215             }
1216             else {
1217             (@_) = ($$x, _str2obj($y));
1218             }
1219             goto &__cmp__;
1220             }
1221              
1222             (@_) = ($$x, _star2obj($y));
1223             goto &__cmp__;
1224             }
1225              
1226             sub acmp ($$) {
1227             require Math::AnyNum::abs;
1228             require Math::AnyNum::cmp;
1229             my ($x, $y) = @_;
1230              
1231             if (!ref($y) and CORE::int($y) eq $y and $y >= 0 and $y < ULONG_MAX) {
1232             ## `y` is a native unsigned integer
1233             }
1234             else {
1235             $y = __abs__(ref($y) eq __PACKAGE__ ? $$y : _star2obj($y));
1236             }
1237              
1238             __cmp__(__abs__(ref($x) eq __PACKAGE__ ? $$x : _star2obj($x)), $y);
1239             }
1240              
1241             #
1242             ## GREATER THAN
1243             #
1244              
1245             sub gt { # used in overloading
1246             require Math::AnyNum::cmp;
1247             my ($x, $y) = @_;
1248              
1249             if (ref($y) eq __PACKAGE__) {
1250             return ((__cmp__($$x, $$y) // return undef) > 0);
1251             }
1252              
1253             if (!ref($y)) {
1254             if (CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
1255             return ((__cmp__($$x, $y) // return undef) > 0);
1256             }
1257             return ((__cmp__($$x, _str2obj($y)) // return undef) > 0);
1258             }
1259              
1260             (__cmp__($$x, _star2obj($y)) // return undef) > 0;
1261             }
1262              
1263             #
1264             ## EQUAL OR GREATER THAN
1265             #
1266              
1267             sub ge { # used in overloading
1268             require Math::AnyNum::cmp;
1269             my ($x, $y) = @_;
1270              
1271             if (ref($y) eq __PACKAGE__) {
1272             return ((__cmp__($$x, $$y) // return undef) >= 0);
1273             }
1274              
1275             if (!ref($y)) {
1276             if (CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
1277             return ((__cmp__($$x, $y) // return undef) >= 0);
1278             }
1279             return ((__cmp__($$x, _str2obj($y)) // return undef) >= 0);
1280             }
1281              
1282             (__cmp__($$x, _star2obj($y)) // return undef) >= 0;
1283             }
1284              
1285             #
1286             ## LESS THAN
1287             #
1288              
1289             sub lt { # used in overloading
1290             require Math::AnyNum::cmp;
1291             my ($x, $y) = @_;
1292              
1293             if (ref($y) eq __PACKAGE__) {
1294             return ((__cmp__($$x, $$y) // return undef) < 0);
1295             }
1296              
1297             if (!ref($y)) {
1298             if (CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
1299             return ((__cmp__($$x, $y) // return undef) < 0);
1300             }
1301             return ((__cmp__($$x, _str2obj($y)) // return undef) < 0);
1302             }
1303              
1304             (__cmp__($$x, _star2obj($y)) // return undef) < 0;
1305             }
1306              
1307             #
1308             ## EQUAL OR LESS THAN
1309             #
1310              
1311             sub le { # used in overloading
1312             require Math::AnyNum::cmp;
1313             my ($x, $y) = @_;
1314              
1315             if (ref($y) eq __PACKAGE__) {
1316             return ((__cmp__($$x, $$y) // return undef) <= 0);
1317             }
1318              
1319             if (!ref($y)) {
1320             if (CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
1321             return ((__cmp__($$x, $y) // return undef) <= 0);
1322             }
1323             return ((__cmp__($$x, _str2obj($y)) // return undef) <= 0);
1324             }
1325              
1326             (__cmp__($$x, _star2obj($y)) // return undef) <= 0;
1327             }
1328              
1329             #
1330             ## COPY
1331             #
1332              
1333             sub _copy {
1334             my ($x) = @_;
1335             my $ref = ref($x);
1336              
1337             if ($ref eq 'Math::GMPz') {
1338             Math::GMPz::Rmpz_init_set($x);
1339             }
1340             elsif ($ref eq 'Math::MPFR') {
1341             my $r = Math::MPFR::Rmpfr_init2($PREC);
1342             Math::MPFR::Rmpfr_set($r, $x, $ROUND);
1343             $r;
1344             }
1345             elsif ($ref eq 'Math::GMPq') {
1346             my $r = Math::GMPq::Rmpq_init();
1347             Math::GMPq::Rmpq_set($r, $x);
1348             $r;
1349             }
1350             elsif ($ref eq 'Math::MPC') {
1351             my $r = Math::MPC::Rmpc_init2($PREC);
1352             Math::MPC::Rmpc_set($r, $x, $ROUND);
1353             $r;
1354             }
1355             else {
1356             _str2obj("$x"); # this should not happen
1357             }
1358             }
1359              
1360             sub copy ($) {
1361             my ($x) = @_;
1362             bless \_copy($$x);
1363             }
1364              
1365             #
1366             ## CONVERSION TO INTEGER
1367             #
1368              
1369             sub int { # used in overloading
1370             my ($x) = @_;
1371              
1372             bless \(
1373             (
1374             ref($x) eq __PACKAGE__
1375             ? ref($$x) eq 'Math::GMPz'
1376             ? (return $x)
1377             : _any2mpz($$x)
1378             : _star2mpz($x)
1379             ) // goto &nan
1380             );
1381             }
1382              
1383             #
1384             ## CONVERSION TO RATIONAL
1385             #
1386              
1387             sub rat ($) {
1388             my ($x) = @_;
1389             if (ref($x) eq __PACKAGE__) {
1390             ref($$x) eq 'Math::GMPq' && return $x;
1391             bless \(_any2mpq($$x) // (goto &nan));
1392             }
1393             else {
1394              
1395             # Parse a decimal number as an exact fraction
1396             if ("$x" =~ /^([+-]?+(?=\.?[0-9])[0-9_]*+(?:\.[0-9_]++)?(?:[Ee](?:[+-]?+[0-9_]+))?)\z/) {
1397             my $frac = _str2frac(lc($1));
1398             my $q = Math::GMPq::Rmpq_init();
1399             Math::GMPq::Rmpq_set_str($q, $frac, 10);
1400             Math::GMPq::Rmpq_canonicalize($q) if (index($frac, '/') != -1);
1401             return bless \$q;
1402             }
1403              
1404             my $r = _star2obj($x);
1405             ref($r) eq 'Math::GMPq' && return bless \$r;
1406             bless(\_any2mpq($r) // goto &nan);
1407             }
1408             }
1409              
1410             #
1411             ## CONVERSION TO FLOATING-POINT
1412             #
1413              
1414             sub float ($) {
1415             my ($x) = @_;
1416              
1417             bless \(
1418             ref($x) eq __PACKAGE__
1419             ? ref($$x) eq 'Math::MPFR'
1420             ? (return $x)
1421             : _any2mpfr($$x)
1422             : _star2mpfr($x)
1423             );
1424             }
1425              
1426             #
1427             ## CONVERSION TO COMPLEX
1428             #
1429              
1430             sub complex ($) {
1431             my ($x) = @_;
1432             bless \(
1433             ref($x) eq __PACKAGE__
1434             ? ref($$x) eq 'Math::MPC'
1435             ? (return $x)
1436             : _any2mpc($$x)
1437             : _any2mpc(_star2obj($x))
1438             );
1439             }
1440              
1441             #
1442             ## NEGATION
1443             #
1444              
1445             sub neg { # used in overloading
1446             require Math::AnyNum::neg;
1447             my ($x) = @_;
1448             bless \__neg__(ref($x) eq __PACKAGE__ ? $$x : _star2obj($x));
1449             }
1450              
1451             #
1452             ## ABSOLUTE VALUE
1453             #
1454              
1455             sub abs { # used in overloading
1456             require Math::AnyNum::abs;
1457             my ($x) = @_;
1458             bless \__abs__(ref($x) eq __PACKAGE__ ? $$x : _star2obj($x));
1459             }
1460              
1461             #
1462             ## MULTIPLICATIVE INVERSE
1463             #
1464              
1465             sub inv ($) {
1466             require Math::AnyNum::inv;
1467             my ($x) = @_;
1468             bless \__inv__(ref($x) eq __PACKAGE__ ? $$x : _star2obj($x));
1469             }
1470              
1471             #
1472             ## INCREMENTATION BY ONE
1473             #
1474              
1475             sub inc ($) {
1476             require Math::AnyNum::inc;
1477             my ($x) = @_;
1478             bless \__inc__($$x);
1479             }
1480              
1481             #
1482             ## DECREMENTATION BY ONE
1483             #
1484              
1485             sub dec ($) {
1486             require Math::AnyNum::dec;
1487             my ($x) = @_;
1488             bless \__dec__($$x);
1489             }
1490              
1491             sub conj ($) {
1492             my ($x) = @_;
1493              
1494             if (ref($x) ne __PACKAGE__) {
1495             $x = __PACKAGE__->new($x);
1496             }
1497              
1498             if (ref($$x) eq 'Math::MPC') {
1499             my $r = Math::MPC::Rmpc_init2($PREC);
1500             Math::MPC::Rmpc_conj($r, $$x, $ROUND);
1501             bless \$r;
1502             }
1503             else {
1504             $x;
1505             }
1506             }
1507              
1508             sub real ($) {
1509             my ($x) = @_;
1510              
1511             if (ref($x) ne __PACKAGE__) {
1512             $x = __PACKAGE__->new($x);
1513             }
1514              
1515             if (ref($$x) eq 'Math::MPC') {
1516             my $r = Math::MPFR::Rmpfr_init2($PREC);
1517             Math::MPC::RMPC_RE($r, $$x);
1518             bless \$r;
1519             }
1520             else {
1521             $x;
1522             }
1523             }
1524              
1525             sub imag ($) {
1526             my ($x) = @_;
1527              
1528             if (ref($x) ne __PACKAGE__) {
1529             $x = __PACKAGE__->new($x);
1530             }
1531              
1532             if (ref($$x) eq 'Math::MPC') {
1533             my $r = Math::MPFR::Rmpfr_init2($PREC);
1534             Math::MPC::RMPC_IM($r, $$x);
1535             bless \$r;
1536             }
1537             else {
1538             goto &zero;
1539             }
1540             }
1541              
1542             sub reals ($) {
1543             my ($x) = @_;
1544              
1545             if (ref($x) ne __PACKAGE__) {
1546             $x = __PACKAGE__->new($x);
1547             }
1548              
1549             ($x->real, $x->imag);
1550             }
1551              
1552             #
1553             ## ADDITION
1554             #
1555              
1556             sub add { # used in overloading
1557             require Math::AnyNum::add;
1558             my ($x, $y) = @_;
1559              
1560             if (ref($y) eq __PACKAGE__) {
1561             return bless \__add__($$x, $$y);
1562             }
1563              
1564             $x = $$x;
1565              
1566             if (!ref($y)) {
1567             if (CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
1568             if (ref($x) eq 'Math::GMPq') {
1569             my $r = Math::GMPq::Rmpq_init();
1570             $y < 0
1571             ? Math::GMPq::Rmpq_set_si($r, $y, 1)
1572             : Math::GMPq::Rmpq_set_ui($r, $y, 1);
1573             Math::GMPq::Rmpq_add($r, $r, $x);
1574             return bless \$r;
1575             }
1576              
1577             return bless \__add__($x, $y);
1578             }
1579              
1580             return bless \__add__($x, _str2obj($y));
1581             }
1582              
1583             bless \__add__($x, _star2obj($y));
1584             }
1585              
1586             #
1587             ## SUBTRACTION
1588             #
1589              
1590             sub sub { # used in overloading
1591             require Math::AnyNum::sub;
1592             my ($x, $y) = @_;
1593              
1594             $x =
1595             ref($x) eq __PACKAGE__ ? $$x
1596             : ref($x) ? _star2obj($x)
1597             : _str2obj($x);
1598              
1599             if (ref($y) eq __PACKAGE__) {
1600             return bless \__sub__($x, $$y);
1601             }
1602              
1603             if (!ref($y)) {
1604             if (CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
1605             if (ref($x) eq 'Math::GMPq') {
1606             my $r = Math::GMPq::Rmpq_init();
1607             $y < 0
1608             ? Math::GMPq::Rmpq_set_si($r, $y, 1)
1609             : Math::GMPq::Rmpq_set_ui($r, $y, 1);
1610             Math::GMPq::Rmpq_sub($r, $x, $r);
1611             return bless \$r;
1612             }
1613              
1614             return bless \__sub__($x, $y);
1615             }
1616              
1617             return bless \__sub__($x, _str2obj($y));
1618             }
1619              
1620             bless \__sub__($x, _star2obj($y));
1621             }
1622              
1623             #
1624             ## MULTIPLICATION
1625             #
1626              
1627             sub mul { # used in overloading
1628             require Math::AnyNum::mul;
1629             my ($x, $y) = @_;
1630              
1631             if (ref($y) eq __PACKAGE__) {
1632             return bless \__mul__($$x, $$y);
1633             }
1634              
1635             $x = $$x;
1636              
1637             if (!ref($y)) {
1638             if (CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
1639             if (ref($x) eq 'Math::GMPq') {
1640             my $r = Math::GMPq::Rmpq_init();
1641             $y < 0
1642             ? Math::GMPq::Rmpq_set_si($r, $y, 1)
1643             : Math::GMPq::Rmpq_set_ui($r, $y, 1);
1644             Math::GMPq::Rmpq_mul($r, $r, $x);
1645             return bless \$r;
1646             }
1647              
1648             return bless \__mul__($x, $y);
1649             }
1650              
1651             return bless \__mul__($x, _str2obj($y));
1652             }
1653              
1654             bless \__mul__($x, _star2obj($y));
1655             }
1656              
1657             #
1658             ## DIVISION
1659             #
1660              
1661             sub div { # used in overloading
1662             require Math::AnyNum::div;
1663             my ($x, $y) = @_;
1664              
1665             $x =
1666             ref($x) eq __PACKAGE__ ? $$x
1667             : ref($x) ? _star2obj($x)
1668             : _str2obj($x);
1669              
1670             if (ref($y) eq __PACKAGE__) {
1671             return bless \__div__($x, $$y);
1672             }
1673              
1674             if (!ref($y)) {
1675             if (CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN and CORE::int($y)) {
1676             if (ref($x) eq 'Math::GMPq') {
1677             my $r = Math::GMPq::Rmpq_init();
1678             $y < 0
1679             ? Math::GMPq::Rmpq_set_si($r, -1, -$y)
1680             : Math::GMPq::Rmpq_set_ui($r, 1, $y);
1681             Math::GMPq::Rmpq_mul($r, $r, $x);
1682             return bless \$r;
1683             }
1684              
1685             return bless \__div__($x, $y);
1686             }
1687              
1688             return bless \__div__($x, _str2obj($y));
1689             }
1690              
1691             bless \__div__($x, _star2obj($y));
1692             }
1693              
1694             #
1695             ## INTEGER ADDITION
1696             #
1697              
1698             sub iadd ($$) {
1699             my ($x, $y) = @_;
1700              
1701             if (!ref($x) and ref($y)) {
1702             ($x, $y) = ($y, $x);
1703             }
1704              
1705             $x = _star2mpz($x) // goto &nan;
1706              
1707             if (!ref($y) and CORE::int($y) eq $y and CORE::abs($y) < ULONG_MAX) {
1708             my $r = Math::GMPz::Rmpz_init();
1709             $y < 0
1710             ? Math::GMPz::Rmpz_sub_ui($r, $x, -$y)
1711             : Math::GMPz::Rmpz_add_ui($r, $x, $y);
1712             return bless \$r;
1713             }
1714              
1715             $y = _star2mpz($y) // goto &nan;
1716              
1717             my $r = Math::GMPz::Rmpz_init();
1718             Math::GMPz::Rmpz_add($r, $x, $y);
1719             bless \$r;
1720             }
1721              
1722             #
1723             ## INTEGER SUBTRACTION
1724             #
1725              
1726             sub isub ($$) {
1727             my ($x, $y) = @_;
1728              
1729             $x = _star2mpz($x) // goto &nan;
1730              
1731             if (!ref($y) and CORE::int($y) eq $y and CORE::abs($y) < ULONG_MAX) {
1732             my $r = Math::GMPz::Rmpz_init();
1733             $y < 0
1734             ? Math::GMPz::Rmpz_add_ui($r, $x, -$y)
1735             : Math::GMPz::Rmpz_sub_ui($r, $x, $y);
1736             return bless \$r;
1737             }
1738              
1739             $y = _star2mpz($y) // goto &nan;
1740              
1741             my $r = Math::GMPz::Rmpz_init();
1742             Math::GMPz::Rmpz_sub($r, $x, $y);
1743             bless \$r;
1744             }
1745              
1746             #
1747             ## INTEGER MULTIPLICATION
1748             #
1749              
1750             sub imul ($$) {
1751             my ($x, $y) = @_;
1752              
1753             if (!ref($x) and ref($y)) {
1754             ($x, $y) = ($y, $x);
1755             }
1756              
1757             $x = _star2mpz($x) // goto &nan;
1758              
1759             if (!ref($y) and CORE::int($y) eq $y and CORE::abs($y) < ULONG_MAX) {
1760             my $r = Math::GMPz::Rmpz_init();
1761             Math::GMPz::Rmpz_mul_ui($r, $x, CORE::abs($y));
1762             Math::GMPz::Rmpz_neg($r, $r) if $y < 0;
1763             return bless \$r;
1764             }
1765              
1766             $y = _star2mpz($y) // goto &nan;
1767              
1768             my $r = Math::GMPz::Rmpz_init();
1769             Math::GMPz::Rmpz_mul($r, $x, $y);
1770             bless \$r;
1771             }
1772              
1773             #
1774             ## INTEGER DIVISION
1775             #
1776              
1777             sub idiv ($$) {
1778             my ($x, $y) = @_;
1779              
1780             $x = _star2mpz($x) // goto &nan;
1781              
1782             if (!ref($y) and CORE::int($y) eq $y and CORE::int($y) and CORE::abs($y) < ULONG_MAX) {
1783             my $r = Math::GMPz::Rmpz_init();
1784             Math::GMPz::Rmpz_tdiv_q_ui($r, $x, CORE::abs($y));
1785             Math::GMPz::Rmpz_neg($r, $r) if $y < 0;
1786             return bless \$r;
1787             }
1788              
1789             $y = _star2mpz($y) // goto &nan;
1790              
1791             # Detect division by zero
1792             Math::GMPz::Rmpz_sgn($y) || do {
1793             my $sign = Math::GMPz::Rmpz_sgn($x);
1794              
1795             if ($sign == 0) { # 0/0
1796             goto &nan;
1797             }
1798             elsif ($sign > 0) { # x/0 where: x > 0
1799             goto &inf;
1800             }
1801             else { # x/0 where: x < 0
1802             goto &ninf;
1803             }
1804             };
1805              
1806             my $r = Math::GMPz::Rmpz_init();
1807             Math::GMPz::Rmpz_tdiv_q($r, $x, $y);
1808             bless \$r;
1809             }
1810              
1811             #
1812             ## POWER
1813             #
1814              
1815             sub pow ($$) {
1816             require Math::AnyNum::pow;
1817             my ($x, $y) = @_;
1818              
1819             $x =
1820             ref($x) eq __PACKAGE__ ? $$x
1821             : ref($x) ? _star2obj($x)
1822             : _str2obj($x);
1823              
1824             if (ref($y) eq __PACKAGE__) {
1825             return bless \__pow__($x, $$y);
1826             }
1827              
1828             if (!ref($y)) {
1829             if (CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
1830             return bless \__pow__($x, $y);
1831             }
1832              
1833             return bless \__pow__($x, _str2obj($y));
1834             }
1835              
1836             bless \__pow__($x, _star2obj($y));
1837             }
1838              
1839             #
1840             ## INTEGER POWER
1841             #
1842              
1843             sub ipow ($$) {
1844             my ($x, $y) = @_;
1845              
1846             # Both `x` and `y` are unsigned native integers
1847             if ( !ref($x)
1848             and !ref($y)
1849             and CORE::int($x) eq $x
1850             and $x >= 0
1851             and $x < ULONG_MAX
1852             and CORE::int($y) eq $y
1853             and $y >= 0
1854             and $y < ULONG_MAX) {
1855              
1856             my $r = Math::GMPz::Rmpz_init();
1857             Math::GMPz::Rmpz_ui_pow_ui($r, $x, $y);
1858             return bless \$r;
1859             }
1860              
1861             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // (goto &nan);
1862              
1863             if (!ref($y) and CORE::int($y) eq $y and CORE::abs($y) < ULONG_MAX) {
1864             ## `y` is already a native integer
1865             }
1866             else {
1867             $y = _any2si(ref($y) eq __PACKAGE__ ? $$y : _star2obj($y)) // (goto &nan);
1868             }
1869              
1870             my $r = Math::GMPz::Rmpz_init();
1871             Math::GMPz::Rmpz_pow_ui($r, $x, CORE::abs($y));
1872              
1873             if ($y < 0) {
1874             Math::GMPz::Rmpz_sgn($r) || goto &inf; # 0^(-y) = Inf
1875             state $ONE_Z = Math::GMPz::Rmpz_init_set_ui_nobless(1);
1876             Math::GMPz::Rmpz_tdiv_q($r, $ONE_Z, $r);
1877             }
1878              
1879             bless \$r;
1880             }
1881              
1882             #
1883             ## IPOW2
1884             #
1885              
1886             sub ipow2 ($) {
1887             my ($n) = @_;
1888              
1889             if (ref($n) eq __PACKAGE__) {
1890             $n = _any2si($$n) // goto &nan;
1891             }
1892             elsif ( !ref($n)
1893             and CORE::int($n) eq $n
1894             and $n > LONG_MIN
1895             and $n < ULONG_MAX) {
1896             ## `n` is already a native integer
1897             }
1898             else {
1899             $n = _any2si(_star2obj($n)) // goto &nan;
1900             }
1901              
1902             goto &zero if $n < 0;
1903             state $one = Math::GMPz::Rmpz_init_set_ui_nobless(1);
1904              
1905             my $r = Math::GMPz::Rmpz_init();
1906             Math::GMPz::Rmpz_mul_2exp($r, $one, $n);
1907             bless \$r;
1908             }
1909              
1910             #
1911             ## IPOW10
1912             #
1913              
1914             sub ipow10 ($) {
1915             my ($n) = @_;
1916              
1917             if (ref($n) eq __PACKAGE__) {
1918             $n = _any2si($$n) // goto &nan;
1919             }
1920             elsif ( !ref($n)
1921             and CORE::int($n) eq $n
1922             and $n > LONG_MIN
1923             and $n < ULONG_MAX) {
1924             ## $n is a native integer
1925             }
1926             else {
1927             $n = _any2si(_star2obj($n)) // goto &nan;
1928             }
1929              
1930             goto &zero if $n < 0;
1931              
1932             my $r = Math::GMPz::Rmpz_init();
1933             Math::GMPz::Rmpz_ui_pow_ui($r, 10, $n);
1934             bless \$r;
1935             }
1936              
1937             #
1938             ## ROOT
1939             #
1940              
1941             sub root ($$) {
1942             require Math::AnyNum::pow;
1943             require Math::AnyNum::inv;
1944             my ($x, $y) = @_;
1945              
1946             $x =
1947             ref($x) eq __PACKAGE__ ? $$x
1948             : ref($x) ? _star2obj($x)
1949             : _str2obj($x);
1950              
1951             $y =
1952             ref($y) eq __PACKAGE__ ? $$y
1953             : ref($y) ? _star2obj($y)
1954             : _str2obj($y);
1955              
1956             bless \__pow__($x, __inv__($y));
1957             }
1958              
1959             #
1960             ## Polygonal root
1961             #
1962              
1963             sub polygonal_root ($$) {
1964             require Math::AnyNum::polygonal_root;
1965             bless \__polygonal_root__(_star2mpfr_mpc($_[0]), _star2mpfr_mpc($_[1]));
1966             }
1967              
1968             #
1969             ## Second polygonal root
1970             #
1971              
1972             sub polygonal_root2 ($$) {
1973             require Math::AnyNum::polygonal_root;
1974             bless \__polygonal_root__(_star2mpfr_mpc($_[0]), _star2mpfr_mpc($_[1]), 1);
1975             }
1976              
1977             #
1978             ## isqrt
1979             #
1980              
1981             sub isqrt ($) {
1982             my ($x) = @_;
1983              
1984             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // goto &nan;
1985              
1986             Math::GMPz::Rmpz_sgn($x) < 0 and goto &nan;
1987             my $r = Math::GMPz::Rmpz_init();
1988             Math::GMPz::Rmpz_sqrt($r, $x);
1989             bless \$r;
1990             }
1991              
1992             #
1993             ## icbrt
1994             #
1995              
1996             sub icbrt ($) {
1997             my ($x) = @_;
1998             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // goto &nan;
1999             my $r = Math::GMPz::Rmpz_init();
2000             Math::GMPz::Rmpz_root($r, $x, 3);
2001             bless \$r;
2002             }
2003              
2004             #
2005             ## IROOT
2006             #
2007              
2008             sub iroot ($$) {
2009             my ($x, $y) = @_;
2010              
2011             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // goto &nan;
2012              
2013             if (!ref($y) and CORE::int($y) eq $y and CORE::abs($y) < ULONG_MAX) {
2014             ## `y`is native integer
2015             }
2016             elsif (ref($y) eq __PACKAGE__) {
2017             $y = _any2si($$y) // goto &nan;
2018             }
2019             else {
2020             $y = _any2si(_star2obj($y)) // goto &nan;
2021             }
2022              
2023             if ($y == 0) {
2024             Math::GMPz::Rmpz_sgn($x) || goto &zero; # 0^Inf = 0
2025              
2026             # 1^Inf = 1 ; (-1)^Inf = 1
2027             if (Math::GMPz::Rmpz_cmpabs_ui($x, 1) == 0) {
2028             goto &one;
2029             }
2030              
2031             goto &inf;
2032             }
2033              
2034             if ($y < 0) {
2035             my $sign = Math::GMPz::Rmpz_sgn($x)
2036             || goto &inf; # 1 / 0^k = Inf
2037              
2038             if ($sign < 0) {
2039             goto &nan;
2040             }
2041              
2042             if (Math::GMPz::Rmpz_cmp_ui($x, 1) == 0) { # 1 / 1^k = 1
2043             goto &one;
2044             }
2045              
2046             goto &zero;
2047             }
2048              
2049             if ($y % 2 == 0 and Math::GMPz::Rmpz_sgn($x) < 0) {
2050             goto &nan;
2051             }
2052              
2053             my $r = Math::GMPz::Rmpz_init();
2054             $y == 2
2055             ? Math::GMPz::Rmpz_sqrt($r, $x)
2056             : Math::GMPz::Rmpz_root($r, $x, $y);
2057             bless \$r;
2058             }
2059              
2060             #
2061             ## ISQRTREM
2062             #
2063              
2064             sub isqrtrem ($) {
2065             my ($x) = @_;
2066              
2067             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // return (nan(), nan());
2068              
2069             Math::GMPz::Rmpz_sgn($x) < 0
2070             and return (nan(), nan());
2071              
2072             my $r = Math::GMPz::Rmpz_init();
2073             my $s = Math::GMPz::Rmpz_init();
2074              
2075             Math::GMPz::Rmpz_sqrtrem($r, $s, $x);
2076              
2077             ((bless \$r), (bless \$s));
2078             }
2079              
2080             #
2081             ## IROOTREM
2082             #
2083              
2084             sub irootrem ($$) {
2085             my ($x, $y) = @_;
2086              
2087             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // return (nan(), nan());
2088              
2089             if (!ref($y) and CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
2090             ## `y` is a native integer
2091             }
2092             else {
2093             $y = _any2si(ref($y) eq __PACKAGE__ ? $$y : _star2obj($y)) // (return (nan(), nan()));
2094             }
2095              
2096             if ($y == 0) {
2097              
2098             # 0^Inf = 0
2099             if (Math::GMPz::Rmpz_sgn($x) == 0) {
2100             return (zero(), mone());
2101             }
2102              
2103             my $r = Math::GMPz::Rmpz_init();
2104             Math::GMPz::Rmpz_sub_ui($r, $x, 1);
2105              
2106             # 1^Inf = 1 ; (-1)^Inf = 1
2107             if (Math::GMPz::Rmpz_cmpabs_ui($x, 1) == 0) {
2108             return (one(), (bless \$r));
2109             }
2110              
2111             return (inf(), (bless \$r));
2112             }
2113              
2114             if ($y < 0) {
2115             my $sgn = Math::GMPz::Rmpz_sgn($x);
2116              
2117             # 1 / 0^k = Inf
2118             if ($sgn == 0) {
2119             return (inf(), zero());
2120             }
2121              
2122             # 1 / 1^k = 1
2123             if (Math::GMPz::Rmpz_cmp_ui($x, 1) == 0) {
2124             return (one(), zero());
2125             }
2126              
2127             # x is negative
2128             if ($sgn < 0) {
2129             return (nan(), nan());
2130             }
2131              
2132             return (zero(), ninf());
2133             }
2134              
2135             if ($y % 2 == 0 and Math::GMPz::Rmpz_sgn($x) < 0) {
2136             return (nan(), nan());
2137             }
2138              
2139             my $r = Math::GMPz::Rmpz_init();
2140             my $s = Math::GMPz::Rmpz_init();
2141              
2142             $y == 2
2143             ? Math::GMPz::Rmpz_sqrtrem($r, $s, $x)
2144             : Math::GMPz::Rmpz_rootrem($r, $s, $x, $y);
2145              
2146             ((bless \$r), (bless \$s));
2147             }
2148              
2149             #
2150             ## MOD
2151             #
2152              
2153             sub mod ($$) {
2154             require Math::AnyNum::mod;
2155             my ($x, $y) = @_;
2156              
2157             $x =
2158             ref($x) eq __PACKAGE__ ? $$x
2159             : ref($x) ? _star2obj($x)
2160             : _str2obj($x);
2161              
2162             if (ref($y) eq __PACKAGE__) {
2163             return bless \__mod__($x, $$y);
2164             }
2165              
2166             if (!ref($y)) {
2167              
2168             if ( ref($x) ne 'Math::GMPq'
2169             and CORE::int($y) eq $y
2170             and $y > 0
2171             and $y < ULONG_MAX) {
2172             return bless \__mod__($x, $y);
2173             }
2174              
2175             return bless \__mod__($x, _str2obj($y));
2176             }
2177              
2178             bless \__mod__($x, _star2obj($y));
2179             }
2180              
2181             #
2182             ## IMOD
2183             #
2184              
2185             sub imod ($$) {
2186             my ($x, $y) = @_;
2187              
2188             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // (goto &nan);
2189              
2190             if (!ref($y) and CORE::int($y) eq $y and CORE::abs($y) < ULONG_MAX) {
2191              
2192             CORE::int($y) || goto &nan;
2193              
2194             my $neg_y = $y < 0;
2195             $y = -$y if $neg_y;
2196              
2197             my $r = Math::GMPz::Rmpz_init();
2198             Math::GMPz::Rmpz_mod_ui($r, $x, $y);
2199              
2200             if (!Math::GMPz::Rmpz_sgn($r)) {
2201             ## OK
2202             }
2203             elsif ($neg_y) {
2204             Math::GMPz::Rmpz_sub_ui($r, $r, $y);
2205             }
2206              
2207             return bless \$r;
2208             }
2209              
2210             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // goto &nan;
2211              
2212             my $sign_y = Math::GMPz::Rmpz_sgn($y) || goto &nan;
2213              
2214             my $r = Math::GMPz::Rmpz_init();
2215             Math::GMPz::Rmpz_mod($r, $x, $y);
2216              
2217             if (!Math::GMPz::Rmpz_sgn($r)) {
2218             ## OK
2219             }
2220             elsif ($sign_y < 0) {
2221             Math::GMPz::Rmpz_add($r, $r, $y);
2222             }
2223              
2224             bless \$r;
2225             }
2226              
2227             #
2228             ## DIVMOD
2229             #
2230              
2231             sub divmod ($$) {
2232             my ($x, $y) = @_;
2233              
2234             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // return (nan(), nan());
2235             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // return (nan(), nan());
2236              
2237             Math::GMPz::Rmpz_sgn($y)
2238             || return (nan(), nan());
2239              
2240             my $r = Math::GMPz::Rmpz_init();
2241             my $s = Math::GMPz::Rmpz_init();
2242              
2243             Math::GMPz::Rmpz_divmod($r, $s, $x, $y);
2244              
2245             ((bless \$r), (bless \$s));
2246             }
2247              
2248             #
2249             ## is_div
2250             #
2251              
2252             sub is_div ($$) {
2253             require Math::AnyNum::eq;
2254             my ($x, $y) = @_;
2255              
2256             if (ref($x) eq __PACKAGE__ and ref($$x) eq 'Math::GMPz') {
2257             if (ref($y)) {
2258             if (ref($y) eq __PACKAGE__ and ref($$y) eq 'Math::GMPz') {
2259             return (Math::GMPz::Rmpz_divisible_p($$x, $$y) && Math::GMPz::Rmpz_sgn($$y));
2260             }
2261             }
2262             elsif (CORE::int($y) eq $y and $y and CORE::abs($y) < ULONG_MAX) {
2263             return Math::GMPz::Rmpz_divisible_ui_p($$x, CORE::abs($y));
2264             }
2265             }
2266              
2267             (@_) = (${mod($x, $y)}, 0);
2268             goto &__eq__;
2269             }
2270              
2271             #
2272             ## SPECIAL
2273             #
2274              
2275             sub ln { # used in overloading
2276             require Math::AnyNum::log;
2277             bless \__log__(_star2mpfr_mpc($_[0]));
2278             }
2279              
2280             sub log2 ($) {
2281             require Math::AnyNum::log;
2282             bless \__log2__(_star2mpfr_mpc($_[0]));
2283             }
2284              
2285             sub log10 ($) {
2286             require Math::AnyNum::log;
2287             bless \__log10__(_star2mpfr_mpc($_[0]));
2288             }
2289              
2290             sub length ($) {
2291             my ($z) = _star2mpz($_[0]) // return -1;
2292             CORE::length(Math::GMPz::Rmpz_get_str($z, 10)) - (Math::GMPz::Rmpz_sgn($z) < 0 ? 1 : 0);
2293             }
2294              
2295             sub log (_;$) {
2296             require Math::AnyNum::log;
2297             my ($x, $y) = @_;
2298              
2299             if (!defined($y)) {
2300             return bless \__log__(_star2mpfr_mpc($x));
2301             }
2302              
2303             require Math::AnyNum::div;
2304             bless \__div__(__log__(_star2mpfr_mpc($x)), __log__(_star2mpfr_mpc($y)));
2305             }
2306              
2307             #
2308             ## ILOG
2309             #
2310              
2311             sub ilog2 ($) {
2312             require Math::AnyNum::ilog;
2313             state $two = Math::GMPz::Rmpz_init_set_ui(2);
2314             bless \__ilog__((_star2mpz($_[0]) // goto &nan), $two);
2315             }
2316              
2317             sub ilog10 ($) {
2318             require Math::AnyNum::ilog;
2319             state $ten = Math::GMPz::Rmpz_init_set_ui(10);
2320             bless \__ilog__((_star2mpz($_[0]) // goto &nan), $ten);
2321             }
2322              
2323             sub ilog ($;$) {
2324             my ($x, $y) = @_;
2325              
2326             if (!defined($y)) {
2327             require Math::AnyNum::log;
2328             return bless \(_any2mpz(__log__(_star2mpfr_mpc($x))) // goto &nan);
2329             }
2330              
2331             require Math::AnyNum::ilog;
2332             bless \__ilog__((_star2mpz($x) // goto &nan), (_star2mpz($y) // goto &nan));
2333             }
2334              
2335             #
2336             ## SQRT
2337             #
2338              
2339             sub sqrt { # used in overloading
2340             require Math::AnyNum::sqrt;
2341             bless \__sqrt__(_star2mpfr_mpc($_[0]));
2342             }
2343              
2344             sub cbrt ($) {
2345             require Math::AnyNum::cbrt;
2346             bless \__cbrt__(_star2mpfr_mpc($_[0]));
2347             }
2348              
2349             sub sqr ($) {
2350             require Math::AnyNum::mul;
2351             my ($x) = @_;
2352              
2353             $x =
2354             ref($x) eq __PACKAGE__
2355             ? $$x
2356             : _star2obj($x);
2357              
2358             bless \__mul__($x, $x);
2359             }
2360              
2361             sub norm ($) {
2362             require Math::AnyNum::norm;
2363             my ($x) = @_;
2364              
2365             $x =
2366             ref($x) eq __PACKAGE__
2367             ? $$x
2368             : _star2obj($x);
2369              
2370             bless \__norm__($x);
2371             }
2372              
2373             sub exp { # used in overloading
2374             require Math::AnyNum::exp;
2375             bless \__exp__(_star2mpfr_mpc($_[0]));
2376             }
2377              
2378             sub exp2 ($) {
2379             require Math::AnyNum::pow;
2380             my ($x) = @_;
2381              
2382             state $base = Math::GMPz::Rmpz_init_set_ui(2);
2383              
2384             if (ref($x) eq __PACKAGE__) {
2385             bless \__pow__($base, $$x);
2386             }
2387             elsif (!ref($x) and CORE::int($x) eq $x and $x > LONG_MIN and $x < ULONG_MAX) {
2388             bless \__pow__($base, $x);
2389             }
2390             else {
2391             bless \__pow__($base, _star2obj($x));
2392             }
2393             }
2394              
2395             sub exp10 ($) {
2396             require Math::AnyNum::pow;
2397             my ($x) = @_;
2398              
2399             state $base = Math::GMPz::Rmpz_init_set_ui(10);
2400              
2401             if (ref($x) eq __PACKAGE__) {
2402             bless \__pow__($base, $$x);
2403             }
2404             elsif (!ref($x) and CORE::int($x) eq $x and $x > LONG_MIN and $x < ULONG_MAX) {
2405             bless \__pow__($base, $x);
2406             }
2407             else {
2408             bless \__pow__($base, _star2obj($x));
2409             }
2410             }
2411              
2412             sub floor ($) {
2413             require Math::AnyNum::floor;
2414             my ($x) = @_;
2415              
2416             if (ref($x) ne __PACKAGE__) {
2417             $x = __PACKAGE__->new($x);
2418             }
2419              
2420             ref($$x) eq 'Math::GMPz' and return $x; # already an integer
2421             bless \__floor__($$x);
2422             }
2423              
2424             sub ceil ($) {
2425             require Math::AnyNum::ceil;
2426             my ($x) = @_;
2427              
2428             if (ref($x) ne __PACKAGE__) {
2429             $x = __PACKAGE__->new($x);
2430             }
2431              
2432             ref($$x) eq 'Math::GMPz' and return $x; # already an integer
2433             bless \__ceil__($$x);
2434             }
2435              
2436             #
2437             ## sin / sinh / asin / asinh
2438             #
2439              
2440             sub sin { # used in overloading
2441             require Math::AnyNum::sin;
2442             bless \__sin__(_star2mpfr_mpc($_[0]));
2443             }
2444              
2445             sub sinh ($) {
2446             require Math::AnyNum::sinh;
2447             bless \__sinh__(_star2mpfr_mpc($_[0]));
2448             }
2449              
2450             sub asin ($) {
2451             require Math::AnyNum::asin;
2452             bless \__asin__(_star2mpfr_mpc($_[0]));
2453             }
2454              
2455             sub asinh ($) {
2456             require Math::AnyNum::asinh;
2457             bless \__asinh__(_star2mpfr_mpc($_[0]));
2458             }
2459              
2460             #
2461             ## cos / cosh / acos / acosh
2462             #
2463              
2464             sub cos { # used in overloading
2465             require Math::AnyNum::cos;
2466             bless \__cos__(_star2mpfr_mpc($_[0]));
2467             }
2468              
2469             sub cosh ($) {
2470             require Math::AnyNum::cosh;
2471             bless \__cosh__(_star2mpfr_mpc($_[0]));
2472             }
2473              
2474             sub acos ($) {
2475             require Math::AnyNum::acos;
2476             bless \__acos__(_star2mpfr_mpc($_[0]));
2477             }
2478              
2479             sub acosh ($) {
2480             require Math::AnyNum::acosh;
2481             bless \__acosh__(_star2mpfr_mpc($_[0]));
2482             }
2483              
2484             #
2485             ## tan / tanh / atan / atanh
2486             #
2487              
2488             sub tan ($) {
2489             require Math::AnyNum::tan;
2490             bless \__tan__(_star2mpfr_mpc($_[0]));
2491             }
2492              
2493             sub tanh ($) {
2494             require Math::AnyNum::tanh;
2495             bless \__tanh__(_star2mpfr_mpc($_[0]));
2496             }
2497              
2498             sub atan ($) {
2499             require Math::AnyNum::atan;
2500             bless \__atan__(_star2mpfr_mpc($_[0]));
2501             }
2502              
2503             sub atanh ($) {
2504             require Math::AnyNum::atanh;
2505             bless \__atanh__(_star2mpfr_mpc($_[0]));
2506             }
2507              
2508             sub atan2 ($$) {
2509             require Math::AnyNum::atan2;
2510             bless \__atan2__(_star2mpfr_mpc($_[0]), _star2mpfr_mpc($_[1]));
2511             }
2512              
2513             #
2514             ## sec / sech / asec / asech
2515             #
2516              
2517             sub sec ($) {
2518             require Math::AnyNum::sec;
2519             bless \__sec__(_star2mpfr_mpc($_[0]));
2520             }
2521              
2522             sub sech ($) {
2523             require Math::AnyNum::sech;
2524             bless \__sech__(_star2mpfr_mpc($_[0]));
2525             }
2526              
2527             sub asec ($) {
2528             require Math::AnyNum::asec;
2529             bless \__asec__(_star2mpfr_mpc($_[0]));
2530             }
2531              
2532             sub asech ($) {
2533             require Math::AnyNum::asech;
2534             bless \__asech__(_star2mpfr_mpc($_[0]));
2535             }
2536              
2537             #
2538             ## csc / csch / acsc / acsch
2539             #
2540              
2541             sub csc ($) {
2542             require Math::AnyNum::csc;
2543             bless \__csc__(_star2mpfr_mpc($_[0]));
2544             }
2545              
2546             sub csch ($) {
2547             require Math::AnyNum::csch;
2548             bless \__csch__(_star2mpfr_mpc($_[0]));
2549             }
2550              
2551             sub acsc ($) {
2552             require Math::AnyNum::acsc;
2553             bless \__acsc__(_star2mpfr_mpc($_[0]));
2554             }
2555              
2556             sub acsch ($) {
2557             require Math::AnyNum::acsch;
2558             bless \__acsch__(_star2mpfr_mpc($_[0]));
2559             }
2560              
2561             #
2562             ## cot / coth / acot / acoth
2563             #
2564              
2565             sub cot ($) {
2566             require Math::AnyNum::cot;
2567             bless \__cot__(_star2mpfr_mpc($_[0]));
2568             }
2569              
2570             sub coth ($) {
2571             require Math::AnyNum::coth;
2572             bless \__coth__(_star2mpfr_mpc($_[0]));
2573             }
2574              
2575             sub acot ($) {
2576             require Math::AnyNum::acot;
2577             bless \__acot__(_star2mpfr_mpc($_[0]));
2578             }
2579              
2580             sub acoth ($) {
2581             require Math::AnyNum::acoth;
2582             bless \__acoth__(_star2mpfr_mpc($_[0]));
2583             }
2584              
2585             sub deg2rad ($) {
2586             require Math::AnyNum::mul;
2587             my ($x) = @_;
2588             my $f = Math::MPFR::Rmpfr_init2($PREC);
2589             Math::MPFR::Rmpfr_const_pi($f, $ROUND);
2590             Math::MPFR::Rmpfr_div_ui($f, $f, 180, $ROUND);
2591             bless \__mul__(_star2mpfr_mpc($x), $f);
2592             }
2593              
2594             sub rad2deg ($) {
2595             require Math::AnyNum::mul;
2596             my ($x) = @_;
2597             my $f = Math::MPFR::Rmpfr_init2($PREC);
2598             Math::MPFR::Rmpfr_const_pi($f, $ROUND);
2599             Math::MPFR::Rmpfr_ui_div($f, 180, $f, $ROUND);
2600             bless \__mul__(_star2mpfr_mpc($x), $f);
2601             }
2602              
2603             #
2604             ## gamma
2605             #
2606              
2607             sub gamma ($) {
2608             my $r = Math::MPFR::Rmpfr_init2($PREC);
2609             Math::MPFR::Rmpfr_gamma($r, _star2mpfr($_[0]), $ROUND);
2610             bless \$r;
2611             }
2612              
2613             #
2614             ## lgamma
2615             #
2616              
2617             sub lgamma ($) {
2618             my $r = Math::MPFR::Rmpfr_init2($PREC);
2619             Math::MPFR::Rmpfr_lgamma($r, _star2mpfr($_[0]), $ROUND);
2620             bless \$r;
2621             }
2622              
2623             #
2624             ## lngamma
2625             #
2626              
2627             sub lngamma ($) {
2628             my $r = Math::MPFR::Rmpfr_init2($PREC);
2629             Math::MPFR::Rmpfr_lngamma($r, _star2mpfr($_[0]), $ROUND);
2630             bless \$r;
2631             }
2632              
2633             #
2634             ## digamma
2635             #
2636              
2637             sub digamma ($) {
2638             my $r = Math::MPFR::Rmpfr_init2($PREC);
2639             Math::MPFR::Rmpfr_digamma($r, _star2mpfr($_[0]), $ROUND);
2640             bless \$r;
2641             }
2642              
2643             #
2644             ## zeta
2645             #
2646              
2647             sub zeta ($) {
2648             my ($x) = @_;
2649              
2650             if (!ref($x) and CORE::int($x) eq $x and $x >= 0 and $x < ULONG_MAX) {
2651             ## $x is an unsigned integer
2652             }
2653             else {
2654             $x = _star2mpfr($x);
2655              
2656             # If $x fits inside an unsigned integer, then unpack it.
2657             if ( Math::MPFR::Rmpfr_integer_p($x)
2658             and Math::MPFR::Rmpfr_fits_ulong_p($x, $ROUND)) {
2659             $x = Math::MPFR::Rmpfr_get_ui($x, $ROUND);
2660             }
2661             }
2662              
2663             my $r = Math::MPFR::Rmpfr_init2($PREC);
2664              
2665             ref($x)
2666             ? Math::MPFR::Rmpfr_zeta($r, $x, $ROUND)
2667             : Math::MPFR::Rmpfr_zeta_ui($r, $x, $ROUND);
2668              
2669             bless \$r;
2670             }
2671              
2672             #
2673             ## eta
2674             #
2675              
2676             sub eta ($) {
2677             require Math::AnyNum::eta;
2678             bless \__eta__(_star2mpfr($_[0]));
2679             }
2680              
2681             #
2682             ## beta
2683             #
2684             sub beta ($$) {
2685             require Math::AnyNum::beta;
2686             bless \__beta__(_star2mpfr($_[0]), _star2mpfr($_[1]));
2687             }
2688              
2689             #
2690             ## Airy function (Ai)
2691             #
2692              
2693             sub Ai ($) {
2694             my $r = Math::MPFR::Rmpfr_init2($PREC);
2695             Math::MPFR::Rmpfr_ai($r, _star2mpfr($_[0]), $ROUND);
2696             bless \$r;
2697             }
2698              
2699             #
2700             ## Exponential integral (Ei)
2701             #
2702              
2703             sub Ei ($) {
2704             my $r = Math::MPFR::Rmpfr_init2($PREC);
2705             Math::MPFR::Rmpfr_eint($r, _star2mpfr($_[0]), $ROUND);
2706             bless \$r;
2707             }
2708              
2709             #
2710             ## Logarithmic integral (Li)
2711             #
2712             sub Li ($) {
2713             my $r = Math::MPFR::Rmpfr_init2($PREC);
2714             Math::MPFR::Rmpfr_log($r, _star2mpfr($_[0]), $ROUND);
2715             Math::MPFR::Rmpfr_eint($r, $r, $ROUND);
2716             bless \$r;
2717             }
2718              
2719             #
2720             ## Dilogarithm function (Li_2)
2721             #
2722             sub Li2 ($) {
2723             my $r = Math::MPFR::Rmpfr_init2($PREC);
2724             Math::MPFR::Rmpfr_li2($r, _star2mpfr($_[0]), $ROUND);
2725             bless \$r;
2726             }
2727              
2728             #
2729             ## Error function
2730             #
2731             sub erf ($) {
2732             my $r = Math::MPFR::Rmpfr_init2($PREC);
2733             Math::MPFR::Rmpfr_erf($r, _star2mpfr($_[0]), $ROUND);
2734             bless \$r;
2735             }
2736              
2737             #
2738             ## Complementary error function
2739             #
2740             sub erfc ($) {
2741             my $r = Math::MPFR::Rmpfr_init2($PREC);
2742             Math::MPFR::Rmpfr_erfc($r, _star2mpfr($_[0]), $ROUND);
2743             bless \$r;
2744             }
2745              
2746             #
2747             ## Lambert W
2748             #
2749              
2750             sub LambertW ($) {
2751             require Math::AnyNum::LambertW;
2752             bless \__LambertW__(_star2mpfr_mpc($_[0]));
2753             }
2754              
2755             #
2756             ## lgrt -- logarithmic root
2757             #
2758              
2759             sub lgrt ($) {
2760             require Math::AnyNum::lgrt;
2761             bless \__lgrt__(_star2mpfr_mpc($_[0]));
2762             }
2763              
2764             #
2765             ## agm
2766             #
2767             sub agm ($$) {
2768             require Math::AnyNum::agm;
2769             bless \__agm__(_star2mpfr_mpc($_[0]), _star2mpfr_mpc($_[1]));
2770             }
2771              
2772             #
2773             ## hypot
2774             #
2775              
2776             sub hypot ($$) {
2777             require Math::AnyNum::hypot;
2778             bless \__hypot__(_star2mpfr_mpc($_[0]), _star2mpfr_mpc($_[1]));
2779             }
2780              
2781             #
2782             ## BesselJ
2783             #
2784              
2785             sub BesselJ ($$) {
2786             require Math::AnyNum::BesselJ;
2787             my ($x, $y) = @_;
2788              
2789             $x = ref($x) eq __PACKAGE__ ? _any2mpfr($$x) : _star2mpfr($x);
2790              
2791             if (!ref($y) and CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
2792             return bless \__BesselJ__($x, $y);
2793             }
2794              
2795             bless \__BesselJ__($x, _star2mpz($y) // (goto &nan));
2796             }
2797              
2798             #
2799             ## BesselY
2800             #
2801              
2802             sub BesselY ($$) {
2803             require Math::AnyNum::BesselY;
2804             my ($x, $y) = @_;
2805              
2806             $x = ref($x) eq __PACKAGE__ ? _any2mpfr($$x) : _star2mpfr($x);
2807              
2808             if (!ref($y) and CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
2809             return bless \__BesselY__($x, $y);
2810             }
2811              
2812             bless \__BesselY__($x, _star2mpz($y) // (goto &nan));
2813             }
2814              
2815             #
2816             ## ROUND
2817             #
2818              
2819             sub round ($;$) {
2820             require Math::AnyNum::round;
2821             my ($x, $y) = @_;
2822              
2823             $x = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
2824              
2825             if (!defined($y)) {
2826             return bless \__round__($x, 0);
2827             }
2828              
2829             if (!ref($y)) {
2830             if (CORE::int($y) eq $y and $y > LONG_MIN and $y < ULONG_MAX) {
2831             ## `y` is a native integer
2832             }
2833             else {
2834             $y = _any2si(_str2obj($y)) // (goto &nan);
2835             }
2836             }
2837             elsif (ref($y) eq __PACKAGE__) {
2838             $y = _any2si($$y) // (goto &nan);
2839             }
2840             else {
2841             $y = _any2si(_star2obj($y)) // (goto &nan);
2842             }
2843              
2844             bless \__round__($x, $y);
2845             }
2846              
2847             #
2848             ## RAND / IRAND
2849             #
2850              
2851             {
2852             my $srand = srand();
2853              
2854             {
2855             state $state = Math::MPFR::Rmpfr_randinit_mt_nobless();
2856             Math::MPFR::Rmpfr_randseed_ui($state, $srand);
2857              
2858             sub rand (;$;$) {
2859             require Math::AnyNum::mul;
2860             my ($x, $y) = @_;
2861              
2862             if (@_ == 0) {
2863             $x = one();
2864             }
2865              
2866             $x = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
2867              
2868             if (!defined($y)) {
2869             my $rand = Math::MPFR::Rmpfr_init2($PREC);
2870             Math::MPFR::Rmpfr_urandom($rand, $state, $ROUND);
2871             return bless \__mul__($rand, $x);
2872             }
2873              
2874             require Math::AnyNum::sub;
2875             require Math::AnyNum::add;
2876              
2877             $y = ref($y) eq __PACKAGE__ ? $$y : _star2obj($y);
2878              
2879             my $rand = Math::MPFR::Rmpfr_init2($PREC);
2880             Math::MPFR::Rmpfr_urandom($rand, $state, $ROUND);
2881             $rand = __mul__($rand, __sub__($y, $x));
2882             bless \__add__($rand, $x);
2883             }
2884              
2885             sub seed ($) {
2886             my $z = _star2mpz($_[0]) // do {
2887             require Carp;
2888             Carp::croak("seed(): invalid seed value <<$_[0]>> (expected an integer)");
2889             };
2890             Math::MPFR::Rmpfr_randseed($state, $z);
2891             bless \$z;
2892             }
2893             }
2894              
2895             {
2896             state $state = Math::GMPz::zgmp_randinit_mt_nobless();
2897             Math::GMPz::zgmp_randseed_ui($state, $srand);
2898              
2899             sub irand ($;$) {
2900             require Math::AnyNum::irand;
2901             my ($x, $y) = @_;
2902              
2903             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // (goto &nan);
2904              
2905             if (!defined($y)) {
2906             return bless \__irand__($x, undef, $state);
2907             }
2908              
2909             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // (goto &nan);
2910             bless \__irand__($x, $y, $state);
2911             }
2912              
2913             sub iseed ($) {
2914             my $z = _star2mpz($_[0]) // do {
2915             require Carp;
2916             Carp::croak("iseed(): invalid seed value <<$_[0]>> (expected an integer)");
2917             };
2918             Math::GMPz::zgmp_randseed($state, $z);
2919             bless \$z;
2920             }
2921             }
2922             }
2923              
2924             #
2925             ## Fibonacci
2926             #
2927             sub fibonacci ($) {
2928             my ($x) = @_;
2929              
2930             if (!ref($x) and CORE::int($x) eq $x and $x >= 0 and $x < ULONG_MAX) {
2931             ## `x` is a native unsigned integer
2932             }
2933             elsif (ref($x) eq __PACKAGE__) {
2934             $x = _any2ui($$x) // goto &nan;
2935             }
2936             else {
2937             $x = _any2ui(_star2obj($x)) // goto &nan;
2938             }
2939              
2940             my $r = Math::GMPz::Rmpz_init();
2941             Math::GMPz::Rmpz_fib_ui($r, $x);
2942             bless \$r;
2943             }
2944              
2945             #
2946             ## Lucas
2947             #
2948             sub lucas ($) {
2949             my ($x) = @_;
2950              
2951             if (!ref($x) and CORE::int($x) eq $x and $x >= 0 and $x < ULONG_MAX) {
2952             ## `x` is a native unsigned integer
2953             }
2954             elsif (ref($x) eq __PACKAGE__) {
2955             $x = _any2ui($$x) // goto &nan;
2956             }
2957             else {
2958             $x = _any2ui(_star2obj($x)) // goto &nan;
2959             }
2960              
2961             my $r = Math::GMPz::Rmpz_init();
2962             Math::GMPz::Rmpz_lucnum_ui($r, $x);
2963             bless \$r;
2964             }
2965              
2966             #
2967             ## Primorial
2968             #
2969             sub primorial ($) {
2970             my ($x) = @_;
2971              
2972             if (!ref($x) and CORE::int($x) eq $x and $x >= 0 and $x < ULONG_MAX) {
2973             ## `x` is a native unsigned integer
2974             }
2975             elsif (ref($x) eq __PACKAGE__) {
2976             $x = _any2ui($$x) // goto &nan;
2977             }
2978             else {
2979             $x = _any2ui(_star2obj($x)) // goto &nan;
2980             }
2981              
2982             my $r = Math::GMPz::Rmpz_init();
2983             Math::GMPz::Rmpz_primorial_ui($r, $x);
2984             bless \$r;
2985             }
2986              
2987             #
2988             ## bernfrac
2989             #
2990              
2991             sub bernfrac ($) {
2992             require Math::AnyNum::bernfrac;
2993             my ($x) = @_;
2994              
2995             if (!ref($x) and CORE::int($x) eq $x and $x >= 0 and $x < ULONG_MAX) {
2996             ## `x` is a native unsigned integer
2997             }
2998             elsif (ref($x) eq __PACKAGE__) {
2999             $x = _any2ui($$x) // goto &nan;
3000             }
3001             else {
3002             $x = _any2ui(_star2obj($x)) // goto &nan;
3003             }
3004              
3005             bless \__bernfrac__($x);
3006             }
3007              
3008             #
3009             ## harmfrac
3010             #
3011              
3012             sub harmfrac ($) {
3013             require Math::AnyNum::harmfrac;
3014             my ($x) = @_;
3015              
3016             if (!ref($x) and CORE::int($x) eq $x and $x >= 0 and $x < ULONG_MAX) {
3017             ## `x` is a native unsigned integer
3018             }
3019             elsif (ref($x) eq __PACKAGE__) {
3020             $x = _any2ui($$x) // goto &nan;
3021             }
3022             else {
3023             $x = _any2ui(_star2obj($x)) // goto &nan;
3024             }
3025              
3026             bless \__harmfrac__($x);
3027             }
3028              
3029             #
3030             ## bernreal
3031             #
3032              
3033             sub bernreal ($) {
3034             require Math::AnyNum::bernreal;
3035             my ($x) = @_;
3036              
3037             if (!ref($x) and CORE::int($x) eq $x and $x >= 0 and $x < ULONG_MAX) {
3038             ## `x` is a native unsigned integer
3039             }
3040             elsif (ref($x) eq __PACKAGE__) {
3041             $x = _any2ui($$x) // goto &nan;
3042             }
3043             else {
3044             $x = _any2ui(_star2obj($x)) // goto &nan;
3045             }
3046              
3047             bless \__bernreal__($x);
3048             }
3049              
3050             #
3051             ## harmreal
3052             #
3053              
3054             sub harmreal ($) {
3055             require Math::AnyNum::harmreal;
3056             bless \__harmreal__(_star2mpfr($_[0]) // (goto &nan));
3057             }
3058              
3059             #
3060             ## Factorial
3061             #
3062             sub factorial ($) {
3063             my ($x) = @_;
3064              
3065             if (!ref($x) and CORE::int($x) eq $x and $x >= 0 and $x < ULONG_MAX) {
3066             ## `x` is a native unsigned integer
3067             }
3068             elsif (ref($x) eq __PACKAGE__) {
3069             $x = _any2ui($$x) // goto &nan;
3070             }
3071             else {
3072             $x = _any2ui(_star2obj($x)) // goto &nan;
3073             }
3074              
3075             my $r = Math::GMPz::Rmpz_init();
3076             Math::GMPz::Rmpz_fac_ui($r, $x);
3077             bless \$r;
3078             }
3079              
3080             #
3081             ## Double-factorial
3082             #
3083              
3084             sub dfactorial ($) {
3085             my ($x) = @_;
3086              
3087             if (!ref($x) and CORE::int($x) eq $x and $x >= 0 and $x < ULONG_MAX) {
3088             ## `x` is a native unsigned integer
3089             }
3090             elsif (ref($x) eq __PACKAGE__) {
3091             $x = _any2ui($$x) // goto &nan;
3092             }
3093             else {
3094             $x = _any2ui(_star2obj($x)) // goto &nan;
3095             }
3096              
3097             my $r = Math::GMPz::Rmpz_init();
3098             Math::GMPz::Rmpz_2fac_ui($r, $x);
3099             bless \$r;
3100             }
3101              
3102             #
3103             ## M-factorial
3104             #
3105              
3106             sub mfactorial ($$) {
3107             my ($x, $y) = @_;
3108              
3109             if (!ref($x) and CORE::int($x) eq $x and $x >= 0 and $x < ULONG_MAX) {
3110             ## `x` is an unsigned native integer
3111             }
3112             elsif (ref($x) eq __PACKAGE__) {
3113             $x = _any2ui($$x) // goto &nan;
3114             }
3115             else {
3116             $x = _any2ui(_star2obj($x)) // goto &nan;
3117             }
3118              
3119             if (!ref($y) and CORE::int($y) eq $y and $y >= 0 and $y < ULONG_MAX) {
3120             ## `y` is an unsigned native integer
3121             }
3122             elsif (ref($y) eq __PACKAGE__) {
3123             $y = _any2ui($$y) // goto &nan;
3124             }
3125             else {
3126             $y = _any2ui(_star2obj($y)) // goto &nan;
3127             }
3128              
3129             my $r = Math::GMPz::Rmpz_init();
3130             Math::GMPz::Rmpz_mfac_uiui($r, $x, $y);
3131             bless \$r;
3132             }
3133              
3134             #
3135             ## falling_factorial(x, +y) = binomial(x, y) * y!
3136             ## falling_factorial(x, -y) = 1/falling_factorial(x + y, y)
3137             #
3138             sub falling_factorial ($$) {
3139             my ($x, $y) = @_;
3140              
3141             $x = _star2mpz($x) // goto &nan;
3142              
3143             if (ref($y) eq __PACKAGE__) {
3144             $y = _any2si($$y) // goto &nan;
3145             }
3146             elsif (!ref($y) and CORE::int($y) eq $y and $y > LONG_MIN and $y < ULONG_MAX) {
3147             ## `y` is a native integer
3148             }
3149             else {
3150             $y = _any2si(_star2obj($y)) // goto &nan;
3151             }
3152              
3153             my $r = Math::GMPz::Rmpz_init_set($x);
3154              
3155             if ($y < 0) {
3156             Math::GMPz::Rmpz_add_ui($r, $r, CORE::abs($y));
3157             }
3158              
3159             Math::GMPz::Rmpz_fits_ulong_p($r)
3160             ? Math::GMPz::Rmpz_bin_uiui($r, Math::GMPz::Rmpz_get_ui($r), CORE::abs($y))
3161             : Math::GMPz::Rmpz_bin_ui($r, $r, CORE::abs($y));
3162              
3163             Math::GMPz::Rmpz_sgn($r) || do {
3164             $y < 0
3165             ? (goto &nan)
3166             : (goto &zero);
3167             };
3168              
3169             state $t = Math::GMPz::Rmpz_init_nobless();
3170             Math::GMPz::Rmpz_fac_ui($t, CORE::abs($y));
3171             Math::GMPz::Rmpz_mul($r, $r, $t);
3172              
3173             if ($y < 0) {
3174             my $q = Math::GMPq::Rmpq_init();
3175             Math::GMPq::Rmpq_set_z($q, $r);
3176             Math::GMPq::Rmpq_inv($q, $q);
3177             return bless \$q;
3178             }
3179              
3180             bless \$r;
3181             }
3182              
3183             #
3184             ## rising_factorial(x, +y) = binomial(x + y - 1, y) * y!
3185             ## rising_factorial(x, -y) = 1/rising_factorial(x - y, y)
3186             #
3187             sub rising_factorial ($$) {
3188             my ($x, $y) = @_;
3189              
3190             $x = _star2mpz($x) // goto &nan;
3191              
3192             if (ref($y) eq __PACKAGE__) {
3193             $y = _any2si($$y) // goto &nan;
3194             }
3195             elsif (!ref($y) and CORE::int($y) eq $y and $y > LONG_MIN and $y < ULONG_MAX) {
3196             ## `y` is a native integer
3197             }
3198             else {
3199             $y = _any2si(_star2obj($y)) // goto &nan;
3200             }
3201              
3202             my $r = Math::GMPz::Rmpz_init_set($x);
3203             Math::GMPz::Rmpz_add_ui($r, $r, CORE::abs($y));
3204             Math::GMPz::Rmpz_sub_ui($r, $r, 1);
3205              
3206             if ($y < 0) {
3207             Math::GMPz::Rmpz_sub_ui($r, $r, CORE::abs($y));
3208             }
3209              
3210             Math::GMPz::Rmpz_fits_ulong_p($r)
3211             ? Math::GMPz::Rmpz_bin_uiui($r, Math::GMPz::Rmpz_get_ui($r), CORE::abs($y))
3212             : Math::GMPz::Rmpz_bin_ui($r, $r, CORE::abs($y));
3213              
3214             Math::GMPz::Rmpz_sgn($r) || do {
3215             $y < 0
3216             ? (goto &nan)
3217             : (goto &zero);
3218             };
3219              
3220             state $t = Math::GMPz::Rmpz_init_nobless();
3221             Math::GMPz::Rmpz_fac_ui($t, CORE::abs($y));
3222             Math::GMPz::Rmpz_mul($r, $r, $t);
3223              
3224             if ($y < 0) {
3225             my $q = Math::GMPq::Rmpq_init();
3226             Math::GMPq::Rmpq_set_z($q, $r);
3227             Math::GMPq::Rmpq_inv($q, $q);
3228             return bless \$q;
3229             }
3230              
3231             bless \$r;
3232             }
3233              
3234             #
3235             ## Greatest common multiple
3236             #
3237              
3238             sub gcd ($$) {
3239             my ($x, $y) = @_;
3240              
3241             if (ref($y) and !ref($x)) {
3242             ($x, $y) = ($y, $x);
3243             }
3244              
3245             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // (goto &nan);
3246              
3247             my $r = Math::GMPz::Rmpz_init();
3248              
3249             if (!ref($y) and CORE::int($y) eq $y and CORE::abs($y) < ULONG_MAX) {
3250             Math::GMPz::Rmpz_gcd_ui($r, $x, CORE::abs($y));
3251             }
3252             else {
3253             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // (goto &nan);
3254             Math::GMPz::Rmpz_gcd($r, $x, $y);
3255             }
3256              
3257             bless \$r;
3258             }
3259              
3260             #
3261             ## Least common multiple
3262             #
3263              
3264             sub lcm ($$) {
3265             my ($x, $y) = @_;
3266              
3267             if (ref($y) and !ref($x)) {
3268             ($x, $y) = ($y, $x);
3269             }
3270              
3271             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // (goto &nan);
3272              
3273             my $r = Math::GMPz::Rmpz_init();
3274              
3275             if (!ref($y) and CORE::int($y) eq $y and CORE::abs($y) < ULONG_MAX) {
3276             Math::GMPz::Rmpz_lcm_ui($r, $x, CORE::abs($y));
3277             }
3278             else {
3279             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // (goto &nan);
3280             Math::GMPz::Rmpz_lcm($r, $x, $y);
3281             }
3282              
3283             bless \$r;
3284             }
3285              
3286             #
3287             ## Next prime after `x`.
3288             #
3289              
3290             sub next_prime ($) {
3291             my ($x) = @_;
3292             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // goto &nan;
3293             my $r = Math::GMPz::Rmpz_init();
3294             Math::GMPz::Rmpz_nextprime($r, $x);
3295             bless \$r;
3296             }
3297              
3298             #
3299             ## Is prime?
3300             #
3301              
3302             sub is_prime ($;$) {
3303             require Math::AnyNum::is_int;
3304             my ($x, $y) = @_;
3305              
3306             $x = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3307              
3308             __is_int__($x) || return 0;
3309              
3310             $y = defined($y) ? (CORE::abs(CORE::int($y)) || 20) : 20;
3311             Math::GMPz::Rmpz_probab_prime_p(_any2mpz($x) // (return 0), $y);
3312             }
3313              
3314             #
3315             ## Is `x` coprime to `y`?
3316             #
3317              
3318             sub is_coprime ($$) {
3319             require Math::AnyNum::is_int;
3320             my ($x, $y) = @_;
3321              
3322             $x = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3323              
3324             __is_int__($x) || return 0;
3325              
3326             $x = _any2mpz($x) // return 0;
3327              
3328             if (!ref($y) and CORE::int($y) eq $y and $y >= 0 and $y < ULONG_MAX) {
3329             ## `y` is a native integer
3330             }
3331             else {
3332             $y = ref($y) eq __PACKAGE__ ? $$y : _star2obj($y);
3333             __is_int__($y) || return 0;
3334             $y = _any2mpz($y) // return 0;
3335             }
3336              
3337             state $t = Math::GMPz::Rmpz_init_nobless();
3338              
3339             ref($y)
3340             ? Math::GMPz::Rmpz_gcd($t, $x, $y)
3341             : Math::GMPz::Rmpz_gcd_ui($t, $x, $y);
3342              
3343             Math::GMPz::Rmpz_cmp_ui($t, 1) == 0;
3344             }
3345              
3346             #
3347             ## Is integer?
3348             #
3349              
3350             sub is_int ($) {
3351             require Math::AnyNum::is_int;
3352             my ($x) = @_;
3353             __is_int__(ref($x) eq __PACKAGE__ ? $$x : _star2obj($x));
3354             }
3355              
3356             #
3357             ## Is rational?
3358             #
3359              
3360             sub is_rat ($) {
3361             my ($x) = @_;
3362             my $ref = ref(ref($x) eq __PACKAGE__ ? $$x : _star2obj($x));
3363             $ref eq 'Math::GMPz' or $ref eq 'Math::GMPq';
3364             }
3365              
3366             #
3367             ## Numerator of a number
3368             #
3369              
3370             sub numerator ($) {
3371             my ($x) = @_;
3372              
3373             my $r = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3374              
3375             while (1) {
3376              
3377             if (ref($r) eq 'Math::GMPq') {
3378             my $z = Math::GMPz::Rmpz_init();
3379             Math::GMPq::Rmpq_get_num($z, $r);
3380             return bless \$z;
3381             }
3382              
3383             ref($r) eq 'Math::GMPz' and return $x; # is an integer
3384              
3385             $r = _any2mpq($r) // goto &nan;
3386             }
3387             }
3388              
3389             #
3390             ## Denominator of a number
3391             #
3392              
3393             sub denominator ($) {
3394             my ($x) = @_;
3395              
3396             my $r = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3397              
3398             while (1) {
3399              
3400             if (ref($r) eq 'Math::GMPq') {
3401             my $z = Math::GMPz::Rmpz_init();
3402             Math::GMPq::Rmpq_get_den($z, $r);
3403             return bless \$z;
3404             }
3405              
3406             ref($r) eq 'Math::GMPz' and goto &one; # is an integer
3407              
3408             $r = _any2mpq($r) // goto &nan;
3409             }
3410             }
3411              
3412             #
3413             ## (numerator, denominator)
3414             #
3415              
3416             sub nude ($) {
3417             my ($x) = @_;
3418              
3419             if (ref($x) ne __PACKAGE__) {
3420             $x = __PACKAGE__->new($x);
3421             }
3422              
3423             ($x->numerator, $x->denominator);
3424             }
3425              
3426             #
3427             ## Sign of a number
3428             #
3429              
3430             sub sgn ($) {
3431             require Math::AnyNum::sgn;
3432             my ($x) = @_;
3433             my $r = __sgn__(ref($x) eq __PACKAGE__ ? $$x : _star2obj($x));
3434             ref($r) ? (bless \$r) : $r;
3435             }
3436              
3437             #
3438             ## Is a real number?
3439             #
3440              
3441             sub is_real ($) {
3442             my ($x) = @_;
3443              
3444             my $r = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3445              
3446             while (1) {
3447             my $ref = ref($r);
3448              
3449             $ref eq 'Math::GMPz' && return 1;
3450             $ref eq 'Math::GMPq' && return 1;
3451             $ref eq 'Math::MPFR' && return Math::MPFR::Rmpfr_number_p($r);
3452              
3453             $r = _any2mpfr($r);
3454             }
3455             }
3456              
3457             #
3458             ## Is an imaginary number?
3459             #
3460              
3461             sub is_imag ($) {
3462             my ($x) = @_;
3463              
3464             my $r = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3465             ref($r) eq 'Math::MPC' or return 0;
3466              
3467             my $f = Math::MPFR::Rmpfr_init2($PREC);
3468             Math::MPC::RMPC_RE($f, $r);
3469             Math::MPFR::Rmpfr_zero_p($f) || return 0; # is complex
3470             Math::MPC::RMPC_IM($f, $r);
3471             !Math::MPFR::Rmpfr_zero_p($f);
3472             }
3473              
3474             #
3475             ## Is a complex number?
3476             #
3477              
3478             sub is_complex ($) {
3479             my ($x) = @_;
3480              
3481             my $r = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3482             ref($r) eq 'Math::MPC' or return 0;
3483              
3484             my $f = Math::MPFR::Rmpfr_init2($PREC);
3485             Math::MPC::RMPC_IM($f, $r);
3486             Math::MPFR::Rmpfr_zero_p($f) && return 0; # is real
3487             Math::MPC::RMPC_RE($f, $r);
3488             !Math::MPFR::Rmpfr_zero_p($f);
3489             }
3490              
3491             #
3492             ## Is positive infinity?
3493             #
3494              
3495             sub is_inf ($) {
3496             my ($x) = @_;
3497              
3498             my $r = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3499              
3500             while (1) {
3501             my $ref = ref($r);
3502              
3503             $ref eq 'Math::GMPz' && return 0;
3504             $ref eq 'Math::GMPq' && return 0;
3505             $ref eq 'Math::MPFR' && return (Math::MPFR::Rmpfr_inf_p($r) and Math::MPFR::Rmpfr_sgn($r) > 0);
3506              
3507             $r = _any2mpfr($r);
3508             }
3509             }
3510              
3511             #
3512             ## Is negative infinity?
3513             #
3514              
3515             sub is_ninf ($) {
3516             my ($x) = @_;
3517              
3518             my $r = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3519              
3520             while (1) {
3521             my $ref = ref($r);
3522              
3523             $ref eq 'Math::GMPz' && return 0;
3524             $ref eq 'Math::GMPq' && return 0;
3525             $ref eq 'Math::MPFR' && return (Math::MPFR::Rmpfr_inf_p($r) and Math::MPFR::Rmpfr_sgn($r) < 0);
3526              
3527             $r = _any2mpfr($r);
3528             }
3529             }
3530              
3531             #
3532             ## Is Not-A-Number?
3533             #
3534              
3535             sub is_nan ($) {
3536             my ($x) = @_;
3537              
3538             $x = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3539              
3540             ref($x) eq 'Math::GMPz' && return 0;
3541             ref($x) eq 'Math::GMPq' && return 0;
3542             ref($x) eq 'Math::MPFR' && return Math::MPFR::Rmpfr_nan_p($x);
3543              
3544             my $t = Math::MPFR::Rmpfr_init2($PREC);
3545              
3546             Math::MPC::RMPC_RE($t, $x);
3547             Math::MPFR::Rmpfr_nan_p($t) && return 1;
3548              
3549             Math::MPC::RMPC_IM($t, $x);
3550             Math::MPFR::Rmpfr_nan_p($t) && return 1;
3551              
3552             return 0;
3553             }
3554              
3555             #
3556             ## Is an even integer?
3557             #
3558              
3559             sub is_even ($) {
3560             require Math::AnyNum::is_int;
3561             my ($x) = @_;
3562              
3563             $x = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3564              
3565             __is_int__($x)
3566             && Math::GMPz::Rmpz_even_p(_any2mpz($x) // (return 0));
3567             }
3568              
3569             #
3570             ## Is an odd integer?
3571             #
3572              
3573             sub is_odd ($) {
3574             require Math::AnyNum::is_int;
3575             my ($x) = @_;
3576              
3577             $x = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3578              
3579             __is_int__($x)
3580             && Math::GMPz::Rmpz_odd_p(_any2mpz($x) // (return 0));
3581             }
3582              
3583             #
3584             ## Is zero?
3585             #
3586              
3587             sub is_zero ($) {
3588             require Math::AnyNum::eq;
3589             my ($x) = @_;
3590             (@_) = ((ref($x) eq __PACKAGE__ ? $$x : _star2obj($x)), 0);
3591             goto &__eq__;
3592             }
3593              
3594             #
3595             ## Is one?
3596             #
3597              
3598             sub is_one ($) {
3599             require Math::AnyNum::eq;
3600             my ($x) = @_;
3601             (@_) = ((ref($x) eq __PACKAGE__ ? $$x : _star2obj($x)), 1);
3602             goto &__eq__;
3603             }
3604              
3605             #
3606             ## Is minus one?
3607             #
3608              
3609             sub is_mone ($) {
3610             require Math::AnyNum::eq;
3611             my ($x) = @_;
3612             (@_) = ((ref($x) eq __PACKAGE__ ? $$x : _star2obj($x)), -1);
3613             goto &__eq__;
3614             }
3615              
3616             #
3617             ## Is positive?
3618             #
3619              
3620             sub is_pos ($) {
3621             require Math::AnyNum::cmp;
3622             my ($x) = @_;
3623             (__cmp__((ref($x) eq __PACKAGE__ ? $$x : _star2obj($x)), 0) // return undef) > 0;
3624             }
3625              
3626             #
3627             ## Is negative?
3628             #
3629              
3630             sub is_neg ($) {
3631             require Math::AnyNum::cmp;
3632             my ($x) = @_;
3633             (__cmp__((ref($x) eq __PACKAGE__ ? $$x : _star2obj($x)), 0) // return undef) < 0;
3634             }
3635              
3636             #
3637             ## Is square?
3638             #
3639              
3640             sub is_square ($) {
3641             require Math::AnyNum::is_int;
3642             my ($x, $y) = @_;
3643              
3644             $x = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3645              
3646             __is_int__($x)
3647             && Math::GMPz::Rmpz_perfect_square_p(_any2mpz($x) // (return 0));
3648             }
3649              
3650             #
3651             ## Is a polygonal number?
3652             #
3653              
3654             sub is_polygonal ($$) {
3655             require Math::AnyNum::is_int;
3656             require Math::AnyNum::is_polygonal;
3657             my ($n, $k) = @_;
3658              
3659             $n = ref($n) eq __PACKAGE__ ? $$n : _star2obj($n);
3660              
3661             $n = (__is_int__($n) ? _any2mpz($n) : return 0) // return 0;
3662             $k = (ref($k) eq __PACKAGE__ ? _any2mpz($$k) : _star2mpz($k)) // return 0;
3663              
3664             __is_polygonal__($n, $k);
3665             }
3666              
3667             #
3668             ## Is a second polygonal number?
3669             #
3670              
3671             sub is_polygonal2 ($$) {
3672             require Math::AnyNum::is_int;
3673             require Math::AnyNum::is_polygonal;
3674             my ($n, $k) = @_;
3675              
3676             $n = ref($n) eq __PACKAGE__ ? $$n : _star2obj($n);
3677              
3678             $n = (__is_int__($n) ? _any2mpz($n) : return 0) // return 0;
3679             $k = (ref($k) eq __PACKAGE__ ? _any2mpz($$k) : _star2mpz($k)) // return 0;
3680              
3681             __is_polygonal__($n, $k, 1);
3682             }
3683              
3684             #
3685             ## Integer polygonal root
3686             #
3687              
3688             sub ipolygonal_root ($$) {
3689             require Math::AnyNum::ipolygonal_root;
3690             my ($n, $k) = @_;
3691              
3692             $n = (ref($n) eq __PACKAGE__ ? _any2mpz($$n) : _star2mpz($n)) // goto &nan;
3693             $k = (ref($k) eq __PACKAGE__ ? _any2mpz($$k) : _star2mpz($k)) // goto &nan;
3694              
3695             bless \__ipolygonal_root__($n, $k);
3696             }
3697              
3698             #
3699             ## Second integer polygonal root
3700             #
3701              
3702             sub ipolygonal_root2 ($$) {
3703             require Math::AnyNum::ipolygonal_root;
3704             my ($n, $k) = @_;
3705              
3706             $n = (ref($n) eq __PACKAGE__ ? _any2mpz($$n) : _star2mpz($n)) // goto &nan;
3707             $k = (ref($k) eq __PACKAGE__ ? _any2mpz($$k) : _star2mpz($k)) // goto &nan;
3708              
3709             bless \__ipolygonal_root__($n, $k, 1);
3710             }
3711              
3712             #
3713             ## n-th k-gonal number
3714             #
3715              
3716             sub polygonal ($$) {
3717             my ($n, $k) = @_;
3718              
3719             $n = (ref($n) eq __PACKAGE__ ? _any2mpz($$n) : _star2mpz($n)) // goto &nan;
3720              
3721             if (!ref($k) and CORE::int($k) eq $k and $k >= 0 and $k < ULONG_MAX) {
3722             ## `k` is a native unsigned integer
3723             }
3724             else {
3725             $k = (ref($k) eq __PACKAGE__ ? _any2mpz($$k) : _star2mpz($k)) // goto &nan;
3726             }
3727              
3728             #
3729             ## polygonal(n, k) = n * (k*n - k - 2*n + 4) / 2
3730             #
3731              
3732             my $r = Math::GMPz::Rmpz_init();
3733              
3734             if (!ref($k)) { # `k` is a native unsigned integer
3735             Math::GMPz::Rmpz_mul_ui($r, $n, $k); # r = n*k
3736             Math::GMPz::Rmpz_sub_ui($r, $r, $k); # r = r-k
3737             }
3738             else {
3739             Math::GMPz::Rmpz_mul($r, $n, $k); # r = n*k
3740             Math::GMPz::Rmpz_sub($r, $r, $k); # r = r-k
3741             }
3742              
3743             Math::GMPz::Rmpz_submul_ui($r, $n, 2); # r = r-2*n
3744             Math::GMPz::Rmpz_add_ui($r, $r, 4); # r = r+4
3745             Math::GMPz::Rmpz_mul($r, $r, $n); # r = r*n
3746             Math::GMPz::Rmpz_div_2exp($r, $r, 1); # r = r/2
3747              
3748             bless \$r;
3749             }
3750              
3751             #
3752             ## is_power
3753             #
3754              
3755             sub is_power ($;$) {
3756             require Math::AnyNum::is_power;
3757             require Math::AnyNum::is_int;
3758             my ($x, $y) = @_;
3759              
3760             $x = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
3761              
3762             __is_int__($x) || return 0;
3763             $x = _any2mpz($x) // goto &nan;
3764              
3765             if (!defined($y)) {
3766             return Math::GMPz::Rmpz_perfect_power_p($x);
3767             }
3768              
3769             if (!ref($y) and CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
3770             ## `y` is a native integer
3771             }
3772             else {
3773             $y = _any2si(ref($y) eq __PACKAGE__ ? $$y : _star2obj($y)) // return 0;
3774             }
3775              
3776             __is_power__($x, $y);
3777             }
3778              
3779             #
3780             ## kronecker
3781             #
3782              
3783             sub kronecker ($$) {
3784             my ($x, $y) = @_;
3785              
3786             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // goto &nan;
3787              
3788             if (!ref($y) and CORE::int($y) eq $y and $y < ULONG_MAX and $y > LONG_MIN) {
3789             return (
3790             $y < 0
3791             ? Math::GMPz::Rmpz_kronecker_si($x, $y)
3792             : Math::GMPz::Rmpz_kronecker_ui($x, $y)
3793             );
3794             }
3795              
3796             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // goto &nan;
3797              
3798             Math::GMPz::Rmpz_kronecker($x, $y);
3799             }
3800              
3801             #
3802             ## valuation
3803             #
3804              
3805             sub valuation ($$) {
3806             require Math::AnyNum::valuation;
3807             my ($x, $y) = @_;
3808              
3809             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // goto &nan;
3810             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // goto &nan;
3811              
3812             (__valuation__($x, $y))[0];
3813             }
3814              
3815             #
3816             ## remdiv
3817             #
3818              
3819             sub remdiv ($$) {
3820             require Math::AnyNum::valuation;
3821             my ($x, $y) = @_;
3822              
3823             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // goto &nan;
3824             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // goto &nan;
3825              
3826             bless \((__valuation__($x, $y))[1]);
3827             }
3828              
3829             #
3830             ## Invmod
3831             #
3832              
3833             sub invmod ($$) {
3834             my ($x, $y) = @_;
3835              
3836             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // goto &nan;
3837             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // goto &nan;
3838              
3839             my $r = Math::GMPz::Rmpz_init();
3840             Math::GMPz::Rmpz_invert($r, $x, $y) || (goto &nan);
3841             bless \$r;
3842             }
3843              
3844             #
3845             ## Powmod
3846             #
3847              
3848             sub powmod ($$$) {
3849             my ($x, $y, $z) = @_;
3850              
3851             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // goto &nan;
3852             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // goto &nan;
3853             $z = (ref($z) eq __PACKAGE__ ? _any2mpz($$z) : _star2mpz($z)) // goto &nan;
3854              
3855             Math::GMPz::Rmpz_sgn($z) || goto &nan;
3856              
3857             if (Math::GMPz::Rmpz_sgn($y) < 0) {
3858             my $t = Math::GMPz::Rmpz_init();
3859             Math::GMPz::Rmpz_gcd($t, $x, $z);
3860             Math::GMPz::Rmpz_cmp_ui($t, 1) == 0 or goto &nan;
3861             }
3862              
3863             my $r = Math::GMPz::Rmpz_init();
3864             Math::GMPz::Rmpz_powm($r, $x, $y, $z);
3865             bless \$r;
3866             }
3867              
3868             #
3869             ## Faulhaber summation formula
3870             #
3871              
3872             sub faulhaber_sum ($$) {
3873             require Math::AnyNum::bernfrac;
3874             my ($n, $p) = @_;
3875              
3876             my $native_n = 0; # true when `n` is a native integer
3877              
3878             if (!ref($n) and CORE::int($n) eq $n and $n >= 0 and $n < ULONG_MAX) {
3879             ## `n` is a native unsigned integer
3880             $native_n = 1;
3881             }
3882             else {
3883             $n = (ref($n) eq __PACKAGE__ ? _any2mpz($$n) : _star2mpz($n)) // goto &nan;
3884              
3885             # Try to unbox `n` when it fits inside a native unsigned integer
3886             if (Math::GMPz::Rmpz_fits_ulong_p($n)) {
3887             $native_n = 1;
3888             $n = Math::GMPz::Rmpz_get_ui($n);
3889             }
3890             }
3891              
3892             if (!ref($p) and CORE::int($p) eq $p and $p >= 0 and $p < ULONG_MAX) {
3893             ## `p` is already a native unsigned integer
3894             }
3895             else {
3896             $p = (ref($p) eq __PACKAGE__ ? _any2ui($$p) : _any2ui(_star2obj($p))) // goto &nan;
3897             }
3898              
3899             state @cache; # cache for Bernoulli numbers
3900              
3901             my $t = Math::GMPz::Rmpz_init();
3902             my $u = Math::GMPz::Rmpz_init();
3903              
3904             my $numerator = Math::GMPz::Rmpz_init();
3905             my $denominator = Math::GMPz::Rmpz_init_set_ui(1);
3906              
3907             #<<<
3908             $native_n
3909             ? Math::GMPz::Rmpz_ui_pow_ui($numerator, $n, $p + 1) # numerator = n^(p + 1)
3910             : Math::GMPz::Rmpz_pow_ui( $numerator, $n, $p + 1); # ==//==
3911             #>>>
3912              
3913             foreach my $j (1 .. $p) {
3914              
3915             # When `j` is odd and greater than 1, we can skip it.
3916             $j % 2 == 0 or $j == 1 or next;
3917              
3918             Math::GMPz::Rmpz_bin_uiui($t, $p + 1, $j); # t = binomial(p+1, j)
3919              
3920             #<<<
3921             $native_n
3922             ? Math::GMPz::Rmpz_ui_pow_ui($u, $n, $p + 1 - $j) # u = n^(p + 1 - j)
3923             : Math::GMPz::Rmpz_pow_ui( $u, $n, $p + 1 - $j); # ==//==
3924             #>>>
3925              
3926             # Compute Bernouli(j)
3927             my $bern = ($j <= 100 ? ($cache[$j] //= __bernfrac__($j)) : __bernfrac__($j));
3928              
3929             #<<<
3930             Math::GMPz::Rmpz_mul($t, $t, $u); # t = t * u
3931             Math::GMPq::Rmpq_get_num($u, $bern); # u = numerator(bern)
3932             Math::GMPz::Rmpz_mul($t, $t, $u); # t = t * u
3933             Math::GMPq::Rmpq_get_den($u, $bern); # u = denominator(bern)
3934              
3935             Math::GMPz::Rmpz_mul( $numerator, $numerator, $u); # numerator = numerator * u
3936             Math::GMPz::Rmpz_addmul($numerator, $denominator, $t); # numerator += denominator * t
3937             Math::GMPz::Rmpz_mul( $denominator, $denominator, $u); # denominator = denominator * u
3938             #>>>
3939             }
3940              
3941             #<<<
3942             Math::GMPz::Rmpz_mul_ui($denominator, $denominator, $p + 1); # denominator = denominator * (p+1)
3943             Math::GMPz::Rmpz_divexact($numerator, $numerator, $denominator); # numerator = numerator / denominator
3944             #>>>
3945              
3946             bless \$numerator;
3947             }
3948              
3949             #
3950             ## Binomial
3951             #
3952              
3953             sub binomial ($$) {
3954             my ($x, $y) = @_;
3955              
3956             # `x` and `y` are native unsigned integers
3957             if ( !ref($x)
3958             and !ref($y)
3959             and CORE::int($x) eq $x
3960             and CORE::int($y) eq $y
3961             and $x >= 0
3962             and $y >= 0
3963             and $x < ULONG_MAX
3964             and $y < ULONG_MAX) {
3965             my $r = Math::GMPz::Rmpz_init();
3966             Math::GMPz::Rmpz_bin_uiui($r, $x, $y);
3967             return bless \$r;
3968             }
3969              
3970             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // goto &nan;
3971              
3972             if (!ref($y) and CORE::int($y) eq $y and $y > LONG_MIN and $y < ULONG_MAX) {
3973             ## `y` is a native integer
3974             }
3975             else {
3976             $y = _any2si(ref($y) eq __PACKAGE__ ? $$y : _star2obj($y)) // goto &nan;
3977             }
3978              
3979             my $r = Math::GMPz::Rmpz_init();
3980              
3981             if ($y >= 0 and Math::GMPz::Rmpz_fits_ulong_p($x)) {
3982             Math::GMPz::Rmpz_bin_uiui($r, Math::GMPz::Rmpz_get_ui($x), $y);
3983             }
3984             else {
3985             $y < 0
3986             ? Math::GMPz::Rmpz_bin_si($r, $x, $y)
3987             : Math::GMPz::Rmpz_bin_ui($r, $x, $y);
3988             }
3989              
3990             bless \$r;
3991             }
3992              
3993             #
3994             ## AND
3995             #
3996              
3997             sub and { # used in overloading
3998             my ($x, $y) = @_;
3999              
4000             $x = _any2mpz($$x) // (goto &nan);
4001             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // (goto &nan);
4002              
4003             my $r = Math::GMPz::Rmpz_init();
4004             Math::GMPz::Rmpz_and($r, $x, $y);
4005             bless \$r;
4006             }
4007              
4008             #
4009             ## OR
4010             #
4011              
4012             sub or { # used in overloading
4013             my ($x, $y) = @_;
4014              
4015             $x = _any2mpz($$x) // (goto &nan);
4016             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // (goto &nan);
4017              
4018             my $r = Math::GMPz::Rmpz_init();
4019             Math::GMPz::Rmpz_ior($r, $x, $y);
4020             bless \$r;
4021             }
4022              
4023             #
4024             ## XOR
4025             #
4026              
4027             sub xor { # used in overloading
4028             my ($x, $y) = @_;
4029              
4030             $x = _any2mpz($$x) // (goto &nan);
4031             $y = (ref($y) eq __PACKAGE__ ? _any2mpz($$y) : _star2mpz($y)) // (goto &nan);
4032              
4033             my $r = Math::GMPz::Rmpz_init();
4034             Math::GMPz::Rmpz_xor($r, $x, $y);
4035             bless \$r;
4036             }
4037              
4038             #
4039             ## NOT
4040             #
4041              
4042             sub not { # used in overloading
4043             my ($x) = @_;
4044             $x = _any2mpz($$x) // (goto &nan);
4045             my $r = Math::GMPz::Rmpz_init();
4046             Math::GMPz::Rmpz_com($r, $x);
4047             bless \$r;
4048             }
4049              
4050             #
4051             ## LEFT SHIFT
4052             #
4053              
4054             sub lsft { # used in overloading
4055             my ($x, $y) = @_;
4056              
4057             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // goto &nan;
4058              
4059             if (!ref($y) and CORE::int($y) eq $y and $y > LONG_MIN and $y < ULONG_MAX) {
4060             ## `y` is a native integer
4061             }
4062             else {
4063             $y = (ref($y) eq __PACKAGE__ ? _any2si($$y) : _any2si(_star2obj($y))) // goto &nan;
4064             }
4065              
4066             my $r = Math::GMPz::Rmpz_init();
4067              
4068             $y < 0
4069             ? Math::GMPz::Rmpz_div_2exp($r, $x, -$y)
4070             : Math::GMPz::Rmpz_mul_2exp($r, $x, $y);
4071              
4072             bless \$r;
4073             }
4074              
4075             #
4076             ## RIGHT SHIFT
4077             #
4078              
4079             sub rsft { # used in overloading
4080             my ($x, $y) = @_;
4081              
4082             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _star2mpz($x)) // goto &nan;
4083              
4084             if (!ref($y) and CORE::int($y) eq $y and $y > LONG_MIN and $y < ULONG_MAX) {
4085             ## `y` is a native integer
4086             }
4087             else {
4088             $y = (ref($y) eq __PACKAGE__ ? _any2si($$y) : _any2si(_star2obj($y))) // goto &nan;
4089             }
4090              
4091             my $r = Math::GMPz::Rmpz_init();
4092              
4093             $y < 0
4094             ? Math::GMPz::Rmpz_mul_2exp($r, $x, -$y)
4095             : Math::GMPz::Rmpz_div_2exp($r, $x, $y);
4096              
4097             bless \$r;
4098             }
4099              
4100             #
4101             ## POPCOUNT
4102             #
4103              
4104             sub popcount ($) {
4105             my ($x) = @_;
4106              
4107             $x = (ref($x) eq __PACKAGE__ ? _any2mpz($$x) : _any2mpz(_star2obj($x))) // return -1;
4108              
4109             if (Math::GMPz::Rmpz_sgn($x) < 0) {
4110             my $t = Math::GMPz::Rmpz_init();
4111             Math::GMPz::Rmpz_neg($t, $x);
4112             $x = $t;
4113             }
4114              
4115             Math::GMPz::Rmpz_popcount($x);
4116             }
4117              
4118             #
4119             ## Conversions
4120             #
4121              
4122             sub as_bin ($) {
4123             Math::GMPz::Rmpz_get_str((_star2mpz($_[0]) // return undef), 2);
4124             }
4125              
4126             sub as_oct ($) {
4127             Math::GMPz::Rmpz_get_str((_star2mpz($_[0]) // return undef), 8);
4128             }
4129              
4130             sub as_hex ($) {
4131             Math::GMPz::Rmpz_get_str((_star2mpz($_[0]) // return undef), 16);
4132             }
4133              
4134             sub as_int ($;$) {
4135             my ($x, $y) = @_;
4136              
4137             my $base = 10;
4138             if (defined($y)) {
4139              
4140             if (!ref($y) and CORE::int($y) eq $y) {
4141             $base = $y;
4142             }
4143             elsif (ref($y) eq __PACKAGE__) {
4144             $base = _any2ui($$y) // 0;
4145             }
4146             else {
4147             $base = _any2ui(_star2mpz($y) // return undef) // 0;
4148             }
4149              
4150             if ($base < 2 or $base > 36) {
4151             require Carp;
4152             Carp::croak("base must be between 2 and 36, got $y");
4153             }
4154             }
4155              
4156             Math::GMPz::Rmpz_get_str((_star2mpz($x) // return undef), $base);
4157             }
4158              
4159             sub as_frac ($;$) {
4160             my ($x, $y) = @_;
4161              
4162             my $base = 10;
4163             if (defined($y)) {
4164              
4165             if (!ref($y) and CORE::int($y) eq $y) {
4166             $base = $y;
4167             }
4168             elsif (ref($y) eq __PACKAGE__) {
4169             $base = _any2ui($$y) // 0;
4170             }
4171             else {
4172             $base = _any2ui(_star2mpz($y) // return undef) // 0;
4173             }
4174              
4175             if ($base < 2 or $base > 36) {
4176             require Carp;
4177             Carp::croak("base must be between 2 and 36, got $y");
4178             }
4179             }
4180              
4181             $x = ref($x) eq __PACKAGE__ ? $$x : _star2obj($x);
4182              
4183             my $ref = ref($x);
4184             if ( $ref eq 'Math::GMPq'
4185             or $ref eq 'Math::GMPz') {
4186             my $frac = (
4187             $ref eq 'Math::GMPq'
4188             ? Math::GMPq::Rmpq_get_str($x, $base)
4189             : Math::GMPz::Rmpz_get_str($x, $base)
4190             );
4191             $frac .= '/1' if (index($frac, '/') == -1);
4192             return $frac;
4193             }
4194              
4195             $x = _any2mpq($x) // return undef;
4196              
4197             my $frac = Math::GMPq::Rmpq_get_str($x, $base);
4198             $frac .= '/1' if (index($frac, '/') == -1);
4199             $frac;
4200             }
4201              
4202             sub as_dec ($;$) {
4203             my ($x, $y) = @_;
4204             require Math::AnyNum::stringify;
4205              
4206             my $prec = $PREC;
4207             if (defined($y)) {
4208             if (!ref($y) and CORE::int($y) eq $y) {
4209             $prec = $y;
4210             }
4211             elsif (ref($y) eq __PACKAGE__) {
4212             $prec = _any2ui($$y) // 0;
4213             }
4214             else {
4215             $prec = _any2ui(_star2mpz($y) // return undef) // 0;
4216             }
4217              
4218             $prec <<= 2;
4219              
4220             state $min_prec = Math::MPFR::RMPFR_PREC_MIN();
4221             state $max_prec = Math::MPFR::RMPFR_PREC_MAX();
4222              
4223             if ($prec < $min_prec or $prec > $max_prec) {
4224             require Carp;
4225             Carp::croak("precision must be between $min_prec and $max_prec, got ", $prec >> 2);
4226             }
4227             }
4228              
4229             local $PREC = $prec;
4230             __stringify__(_star2mpfr_mpc($x));
4231             }
4232              
4233             sub rat_approx ($) {
4234             require Math::AnyNum::stringify;
4235             my ($x) = @_;
4236              
4237             $x = _star2mpfr($x);
4238              
4239             Math::MPFR::Rmpfr_number_p($x) || goto &nan;
4240              
4241             my $t = Math::MPFR::Rmpfr_init2($PREC); # temporary variable
4242             my $r = Math::MPFR::Rmpfr_init2($PREC);
4243              
4244             Math::MPFR::Rmpfr_set($r, $x, $ROUND);
4245              
4246             my $num2cfrac = sub {
4247             my ($callback, $n) = @_;
4248              
4249             while (1) {
4250             Math::MPFR::Rmpfr_floor($t, $r);
4251              
4252             my $z = Math::GMPz::Rmpz_init();
4253             Math::MPFR::Rmpfr_get_z($z, $t, Math::MPFR::MPFR_RNDZ);
4254              
4255             $callback->($z) && return 1;
4256              
4257             Math::MPFR::Rmpfr_sub($r, $r, $t, $ROUND);
4258             Math::MPFR::Rmpfr_zero_p($r) && last;
4259             Math::MPFR::Rmpfr_ui_div($r, 1, $r, $ROUND);
4260             }
4261             };
4262              
4263             my $q = Math::GMPq::Rmpq_init();
4264              
4265             my $cfrac2num = sub {
4266             my (@f) = @_;
4267              
4268             Math::GMPq::Rmpq_set_ui($q, 0, 1);
4269              
4270             for (1 .. $#f) {
4271             Math::GMPq::Rmpq_add_z($q, $q, CORE::pop(@f));
4272             Math::GMPq::Rmpq_inv($q, $q);
4273             }
4274              
4275             Math::GMPq::Rmpq_add_z($q, $q, $f[0]);
4276             };
4277              
4278             my @cfrac;
4279             my $s = __stringify__($x);
4280             my $u = Math::MPFR::Rmpfr_init2($PREC); # temporary variable
4281              
4282             #<<<
4283             $num2cfrac->(
4284             sub {
4285             my ($n) = @_;
4286             CORE::push(@cfrac, $n);
4287             $cfrac2num->(@cfrac);
4288             Math::MPFR::Rmpfr_set_q($u, $q, $ROUND);
4289             CORE::index(__stringify__($u), $s) == 0;
4290             }, $x
4291             );
4292             #>>>
4293              
4294             bless \$q;
4295             }
4296              
4297             sub digits ($;$) {
4298             my ($x, $y) = @_;
4299             my $str = as_int($x, $y) // return ();
4300             my @digits = split(//, $str);
4301             shift(@digits) if $digits[0] eq '-';
4302             (@digits);
4303             }
4304              
4305             1; # End of Math::AnyNum