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