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