This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update bignum, Math::BigInt, Math::BigInt::FastCalc, and Math::BigRat
[perl5.git] / cpan / Math-BigRat / lib / Math / BigRat.pm
CommitLineData
a4e2b1c6 1#
7d341013 2# "Tax the rat farms." - Lord Vetinari
a4e2b1c6 3#
184f15d5
JH
4
5# The following hash values are used:
6# sign : +,-,NaN,+inf,-inf
7# _d : denominator
c4a6f826 8# _n : numerator (value = _n/_d)
184f15d5
JH
9# _a : accuracy
10# _p : precision
7afd7a91 11# You should not look at the innards of a BigRat - use the methods for this.
184f15d5
JH
12
13package Math::BigRat;
14
08a3f4a9 15use 5.006;
184f15d5 16use strict;
11c955be
SH
17use warnings;
18
6853e8af
RL
19use Carp qw< carp croak >;
20use Scalar::Util qw< blessed >;
184f15d5 21
6853e8af 22use Math::BigFloat ();
11c955be 23
6853e8af 24our $VERSION = '0.2620';
184f15d5 25
6320cdc0
SH
26our @ISA = qw(Math::BigFloat);
27
28our ($accuracy, $precision, $round_mode, $div_scale,
29 $upgrade, $downgrade, $_trap_nan, $_trap_inf);
9aa0b648
FR
30
31use overload
6320cdc0
SH
32
33 # overload key: with_assign
34
35 '+' => sub { $_[0] -> copy() -> badd($_[1]); },
36
37 '-' => sub { my $c = $_[0] -> copy;
38 $_[2] ? $c -> bneg() -> badd( $_[1])
39 : $c -> bsub($_[1]); },
40
41 '*' => sub { $_[0] -> copy() -> bmul($_[1]); },
42
43 '/' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bdiv($_[0])
44 : $_[0] -> copy() -> bdiv($_[1]); },
45
6320cdc0
SH
46 '%' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bmod($_[0])
47 : $_[0] -> copy() -> bmod($_[1]); },
48
49 '**' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bpow($_[0])
50 : $_[0] -> copy() -> bpow($_[1]); },
51
52 '<<' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> blsft($_[0])
53 : $_[0] -> copy() -> blsft($_[1]); },
54
55 '>>' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> brsft($_[0])
56 : $_[0] -> copy() -> brsft($_[1]); },
57
58 # overload key: assign
59
60 '+=' => sub { $_[0]->badd($_[1]); },
61
62 '-=' => sub { $_[0]->bsub($_[1]); },
63
64 '*=' => sub { $_[0]->bmul($_[1]); },
65
66 '/=' => sub { scalar $_[0]->bdiv($_[1]); },
67
68 '%=' => sub { $_[0]->bmod($_[1]); },
69
70 '**=' => sub { $_[0]->bpow($_[1]); },
71
6320cdc0
SH
72 '<<=' => sub { $_[0]->blsft($_[1]); },
73
74 '>>=' => sub { $_[0]->brsft($_[1]); },
75
76# 'x=' => sub { },
77
78# '.=' => sub { },
79
80 # overload key: num_comparison
81
82 '<' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> blt($_[0])
83 : $_[0] -> blt($_[1]); },
84
85 '<=' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> ble($_[0])
86 : $_[0] -> ble($_[1]); },
87
88 '>' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bgt($_[0])
89 : $_[0] -> bgt($_[1]); },
90
91 '>=' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bge($_[0])
92 : $_[0] -> bge($_[1]); },
93
94 '==' => sub { $_[0] -> beq($_[1]); },
95
96 '!=' => sub { $_[0] -> bne($_[1]); },
97
98 # overload key: 3way_comparison
99
100 '<=>' => sub { my $cmp = $_[0] -> bcmp($_[1]);
101 defined($cmp) && $_[2] ? -$cmp : $cmp; },
102
103 'cmp' => sub { $_[2] ? "$_[1]" cmp $_[0] -> bstr()
104 : $_[0] -> bstr() cmp "$_[1]"; },
105
106 # overload key: str_comparison
107
108# 'lt' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bstrlt($_[0])
109# : $_[0] -> bstrlt($_[1]); },
110#
111# 'le' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bstrle($_[0])
112# : $_[0] -> bstrle($_[1]); },
113#
114# 'gt' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bstrgt($_[0])
115# : $_[0] -> bstrgt($_[1]); },
116#
117# 'ge' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bstrge($_[0])
118# : $_[0] -> bstrge($_[1]); },
119#
120# 'eq' => sub { $_[0] -> bstreq($_[1]); },
121#
122# 'ne' => sub { $_[0] -> bstrne($_[1]); },
123
124 # overload key: binary
125
126 '&' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> band($_[0])
127 : $_[0] -> copy() -> band($_[1]); },
128
129 '&=' => sub { $_[0] -> band($_[1]); },
130
131 '|' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bior($_[0])
132 : $_[0] -> copy() -> bior($_[1]); },
133
134 '|=' => sub { $_[0] -> bior($_[1]); },
135
136 '^' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> bxor($_[0])
137 : $_[0] -> copy() -> bxor($_[1]); },
138
139 '^=' => sub { $_[0] -> bxor($_[1]); },
140
141# '&.' => sub { },
142
143# '&.=' => sub { },
144
145# '|.' => sub { },
146
147# '|.=' => sub { },
148
149# '^.' => sub { },
150
151# '^.=' => sub { },
152
153 # overload key: unary
154
155 'neg' => sub { $_[0] -> copy() -> bneg(); },
156
157# '!' => sub { },
158
159 '~' => sub { $_[0] -> copy() -> bnot(); },
160
161# '~.' => sub { },
162
163 # overload key: mutators
164
165 '++' => sub { $_[0] -> binc() },
166
167 '--' => sub { $_[0] -> bdec() },
168
169 # overload key: func
170
171 'atan2' => sub { $_[2] ? ref($_[0]) -> new($_[1]) -> batan2($_[0])
172 : $_[0] -> copy() -> batan2($_[1]); },
173
174 'cos' => sub { $_[0] -> copy() -> bcos(); },
175
176 'sin' => sub { $_[0] -> copy() -> bsin(); },
177
178 'exp' => sub { $_[0] -> copy() -> bexp($_[1]); },
179
180 'abs' => sub { $_[0] -> copy() -> babs(); },
181
182 'log' => sub { $_[0] -> copy() -> blog(); },
183
184 'sqrt' => sub { $_[0] -> copy() -> bsqrt(); },
185
186 'int' => sub { $_[0] -> copy() -> bint(); },
187
188 # overload key: conversion
189
190 'bool' => sub { $_[0] -> is_zero() ? '' : 1; },
191
192 '""' => sub { $_[0] -> bstr(); },
193
194 '0+' => sub { $_[0] -> numify(); },
195
196 '=' => sub { $_[0]->copy(); },
197
198 ;
11c955be
SH
199
200BEGIN {
201 *objectify = \&Math::BigInt::objectify; # inherit this from BigInt
202 *AUTOLOAD = \&Math::BigFloat::AUTOLOAD; # can't inherit AUTOLOAD
0c2fbbe3
CBW
203 # We inherit these from BigFloat because currently it is not possible that
204 # Math::BigFloat has a different $LIB variable than we, because
205 # Math::BigFloat also uses Math::BigInt::config->('lib') (there is always
206 # only one library loaded)
11c955be
SH
207 *_e_add = \&Math::BigFloat::_e_add;
208 *_e_sub = \&Math::BigFloat::_e_sub;
3cc1ad36 209 *as_number = \&as_int;
11c955be
SH
210 *is_pos = \&is_positive;
211 *is_neg = \&is_negative;
212}
9b924220 213
184f15d5 214##############################################################################
12fc2493 215# Global constants and flags. Access these only via the accessor methods!
184f15d5 216
6320cdc0 217$accuracy = $precision = undef;
184f15d5 218$round_mode = 'even';
6320cdc0
SH
219$div_scale = 40;
220$upgrade = undef;
221$downgrade = undef;
184f15d5 222
12fc2493 223# These are internally, and not to be used from the outside at all!
990fb837
RGS
224
225$_trap_nan = 0; # are NaNs ok? set w/ config()
226$_trap_inf = 0; # are infs ok? set w/ config()
227
3cc1ad36 228# the math backend library
6320cdc0 229
0c2fbbe3 230my $LIB = 'Math::BigInt::Calc';
12fc2493 231
11c955be 232my $nan = 'NaN';
6320cdc0 233#my $class = 'Math::BigRat';
184f15d5 234
11c955be 235sub isa {
6320cdc0 236 return 0 if $_[1] =~ /^Math::Big(Int|Float)/; # we aren't
11c955be
SH
237 UNIVERSAL::isa(@_);
238}
8f675a64 239
12fc2493 240##############################################################################
9b924220 241
6320cdc0
SH
242sub new {
243 my $proto = shift;
244 my $protoref = ref $proto;
245 my $class = $protoref || $proto;
184f15d5 246
6320cdc0 247 # Check the way we are called.
184f15d5 248
6320cdc0 249 if ($protoref) {
3cc1ad36 250 croak("new() is a class method, not an instance method");
184f15d5 251 }
6320cdc0
SH
252
253 if (@_ < 1) {
3cc1ad36 254 #carp("Using new() with no argument is deprecated;",
6320cdc0
SH
255 # " use bzero() or new(0) instead");
256 return $class -> bzero();
184f15d5 257 }
184f15d5 258
6320cdc0 259 if (@_ > 2) {
3cc1ad36 260 carp("Superfluous arguments to new() ignored.");
6320cdc0 261 }
184f15d5 262
6320cdc0
SH
263 # Get numerator and denominator. If any of the arguments is undefined,
264 # return zero.
184f15d5 265
6320cdc0 266 my ($n, $d) = @_;
ccbfef19 267
6320cdc0
SH
268 if (@_ == 1 && !defined $n ||
269 @_ == 2 && (!defined $n || !defined $d))
270 {
3cc1ad36 271 #carp("Use of uninitialized value in new()");
6320cdc0
SH
272 return $class -> bzero();
273 }
b68b7ab1 274
6320cdc0 275 # Initialize a new object.
184f15d5 276
6320cdc0 277 my $self = bless {}, $class;
11c955be 278
6320cdc0 279 # One or two input arguments may be given. First handle the numerator $n.
11c955be 280
6320cdc0
SH
281 if (ref($n)) {
282 $n = Math::BigFloat -> new($n, undef, undef)
283 unless ($n -> isa('Math::BigRat') ||
284 $n -> isa('Math::BigInt') ||
285 $n -> isa('Math::BigFloat'));
286 } else {
287 if (defined $d) {
288 # If the denominator is defined, the numerator is not a string
289 # fraction, e.g., "355/113".
290 $n = Math::BigFloat -> new($n, undef, undef);
291 } else {
292 # If the denominator is undefined, the numerator might be a string
293 # fraction, e.g., "355/113".
294 if ($n =~ m| ^ \s* (\S+) \s* / \s* (\S+) \s* $ |x) {
295 $n = Math::BigFloat -> new($1, undef, undef);
296 $d = Math::BigFloat -> new($2, undef, undef);
297 } else {
298 $n = Math::BigFloat -> new($n, undef, undef);
299 }
300 }
301 }
11c955be 302
6320cdc0
SH
303 # At this point $n is an object and $d is either an object or undefined. An
304 # undefined $d means that $d was not specified by the caller (not that $d
305 # was specified as an undefined value).
11c955be 306
6320cdc0
SH
307 unless (defined $d) {
308 #return $n -> copy($n) if $n -> isa('Math::BigRat');
309 return $class -> copy($n) if $n -> isa('Math::BigRat');
310 return $class -> bnan() if $n -> is_nan();
311 return $class -> binf($n -> sign()) if $n -> is_inf();
11c955be 312
6320cdc0 313 if ($n -> isa('Math::BigInt')) {
0c2fbbe3
CBW
314 $self -> {_n} = $LIB -> _new($n -> copy() -> babs() -> bstr());
315 $self -> {_d} = $LIB -> _one();
6320cdc0
SH
316 $self -> {sign} = $n -> sign();
317 return $self;
11c955be 318 }
6320cdc0
SH
319
320 if ($n -> isa('Math::BigFloat')) {
321 my $m = $n -> mantissa() -> babs();
322 my $e = $n -> exponent();
0c2fbbe3
CBW
323 $self -> {_n} = $LIB -> _new($m -> bstr());
324 $self -> {_d} = $LIB -> _one();
6320cdc0
SH
325
326 if ($e > 0) {
0c2fbbe3
CBW
327 $self -> {_n} = $LIB -> _lsft($self -> {_n},
328 $LIB -> _new($e -> bstr()), 10);
6320cdc0 329 } elsif ($e < 0) {
0c2fbbe3
CBW
330 $self -> {_d} = $LIB -> _lsft($self -> {_d},
331 $LIB -> _new(-$e -> bstr()), 10);
6320cdc0 332
0c2fbbe3
CBW
333 my $gcd = $LIB -> _gcd($LIB -> _copy($self -> {_n}), $self -> {_d});
334 if (!$LIB -> _is_one($gcd)) {
335 $self -> {_n} = $LIB -> _div($self->{_n}, $gcd);
336 $self -> {_d} = $LIB -> _div($self->{_d}, $gcd);
6320cdc0
SH
337 }
338 }
339
340 $self -> {sign} = $n -> sign();
341 return $self;
11c955be 342 }
6320cdc0
SH
343
344 die "I don't know how to handle this"; # should never get here
184f15d5 345 }
12fc2493 346
6320cdc0
SH
347 # At the point we know that both $n and $d are defined. We know that $n is
348 # an object, but $d might still be a scalar. Now handle $d.
11c955be 349
6320cdc0
SH
350 $d = Math::BigFloat -> new($d, undef, undef)
351 unless ref($d) && ($d -> isa('Math::BigRat') ||
352 $d -> isa('Math::BigInt') ||
353 $d -> isa('Math::BigFloat'));
12fc2493 354
6320cdc0
SH
355 # At this point both $n and $d are objects.
356
357 return $class -> bnan() if $n -> is_nan() || $d -> is_nan();
358
359 # At this point neither $n nor $d is a NaN.
12fc2493 360
6320cdc0
SH
361 if ($n -> is_zero()) {
362 return $class -> bnan() if $d -> is_zero(); # 0/0 = NaN
363 return $class -> bzero();
11c955be
SH
364 }
365
6320cdc0 366 return $class -> binf($d -> sign()) if $d -> is_zero();
11c955be 367
6320cdc0
SH
368 # At this point, neither $n nor $d is a NaN or a zero.
369
7deec013
NB
370 # Copy them now before manipulating them.
371
372 $n = $n -> copy();
373 $d = $d -> copy();
374
6320cdc0
SH
375 if ($d < 0) { # make sure denominator is positive
376 $n -> bneg();
377 $d -> bneg();
11c955be
SH
378 }
379
6320cdc0
SH
380 if ($n -> is_inf()) {
381 return $class -> bnan() if $d -> is_inf(); # Inf/Inf = NaN
382 return $class -> binf($n -> sign());
383 }
11c955be 384
6320cdc0 385 # At this point $n is finite.
11c955be 386
6320cdc0
SH
387 return $class -> bzero() if $d -> is_inf();
388 return $class -> binf($d -> sign()) if $d -> is_zero();
11c955be 389
6320cdc0 390 # At this point both $n and $d are finite and non-zero.
990fb837 391
6320cdc0
SH
392 if ($n < 0) {
393 $n -> bneg();
394 $self -> {sign} = '-';
395 } else {
396 $self -> {sign} = '+';
11c955be
SH
397 }
398
6320cdc0
SH
399 if ($n -> isa('Math::BigRat')) {
400
401 if ($d -> isa('Math::BigRat')) {
402
403 # At this point both $n and $d is a Math::BigRat.
404
405 # p r p * s (p / gcd(p, r)) * (s / gcd(s, q))
406 # - / - = ----- = ---------------------------------
407 # q s q * r (q / gcd(s, q)) * (r / gcd(p, r))
408
409 my $p = $n -> {_n};
410 my $q = $n -> {_d};
411 my $r = $d -> {_n};
412 my $s = $d -> {_d};
0c2fbbe3
CBW
413 my $gcd_pr = $LIB -> _gcd($LIB -> _copy($p), $r);
414 my $gcd_sq = $LIB -> _gcd($LIB -> _copy($s), $q);
415 $self -> {_n} = $LIB -> _mul($LIB -> _div($LIB -> _copy($p), $gcd_pr),
416 $LIB -> _div($LIB -> _copy($s), $gcd_sq));
417 $self -> {_d} = $LIB -> _mul($LIB -> _div($LIB -> _copy($q), $gcd_sq),
418 $LIB -> _div($LIB -> _copy($r), $gcd_pr));
6320cdc0
SH
419
420 return $self; # no need for $self -> bnorm() here
11c955be 421 }
6320cdc0
SH
422
423 # At this point, $n is a Math::BigRat and $d is a Math::Big(Int|Float).
424
425 my $p = $n -> {_n};
426 my $q = $n -> {_d};
427 my $m = $d -> mantissa();
428 my $e = $d -> exponent();
429
430 # / p
431 # | ------------ if e > 0
432 # | q * m * 10^e
433 # |
434 # p | p
435 # - / (m * 10^e) = | ----- if e == 0
436 # q | q * m
437 # |
438 # | p * 10^-e
439 # | -------- if e < 0
440 # \ q * m
441
0c2fbbe3
CBW
442 $self -> {_n} = $LIB -> _copy($p);
443 $self -> {_d} = $LIB -> _mul($LIB -> _copy($q), $m);
6320cdc0 444 if ($e > 0) {
0c2fbbe3 445 $self -> {_d} = $LIB -> _lsft($self -> {_d}, $e, 10);
6320cdc0 446 } elsif ($e < 0) {
0c2fbbe3 447 $self -> {_n} = $LIB -> _lsft($self -> {_n}, -$e, 10);
11c955be 448 }
184f15d5 449
6320cdc0
SH
450 return $self -> bnorm();
451
452 } else {
453
454 if ($d -> isa('Math::BigRat')) {
455
456 # At this point $n is a Math::Big(Int|Float) and $d is a
457 # Math::BigRat.
458
459 my $m = $n -> mantissa();
460 my $e = $n -> exponent();
461 my $p = $d -> {_n};
462 my $q = $d -> {_d};
463
464 # / q * m * 10^e
465 # | ------------ if e > 0
466 # | p
467 # |
468 # p | m * q
469 # (m * 10^e) / - = | ----- if e == 0
470 # q | p
471 # |
472 # | q * m
473 # | --------- if e < 0
474 # \ p * 10^-e
475
0c2fbbe3
CBW
476 $self -> {_n} = $LIB -> _mul($LIB -> _copy($q), $m);
477 $self -> {_d} = $LIB -> _copy($p);
6320cdc0 478 if ($e > 0) {
0c2fbbe3 479 $self -> {_n} = $LIB -> _lsft($self -> {_n}, $e, 10);
6320cdc0 480 } elsif ($e < 0) {
0c2fbbe3 481 $self -> {_d} = $LIB -> _lsft($self -> {_d}, -$e, 10);
6320cdc0
SH
482 }
483 return $self -> bnorm();
484
485 } else {
486
487 # At this point $n and $d are both a Math::Big(Int|Float)
488
489 my $m1 = $n -> mantissa();
490 my $e1 = $n -> exponent();
491 my $m2 = $d -> mantissa();
492 my $e2 = $d -> exponent();
493
494 # /
495 # | m1 * 10^(e1 - e2)
496 # | ----------------- if e1 > e2
497 # | m2
498 # |
499 # m1 * 10^e1 | m1
500 # ---------- = | -- if e1 = e2
501 # m2 * 10^e2 | m2
502 # |
503 # | m1
504 # | ----------------- if e1 < e2
505 # | m2 * 10^(e2 - e1)
506 # \
507
0c2fbbe3
CBW
508 $self -> {_n} = $LIB -> _new($m1 -> bstr());
509 $self -> {_d} = $LIB -> _new($m2 -> bstr());
6320cdc0
SH
510 my $ediff = $e1 - $e2;
511 if ($ediff > 0) {
0c2fbbe3
CBW
512 $self -> {_n} = $LIB -> _lsft($self -> {_n},
513 $LIB -> _new($ediff -> bstr()),
6320cdc0
SH
514 10);
515 } elsif ($ediff < 0) {
0c2fbbe3
CBW
516 $self -> {_d} = $LIB -> _lsft($self -> {_d},
517 $LIB -> _new(-$ediff -> bstr()),
6320cdc0
SH
518 10);
519 }
520
521 return $self -> bnorm();
11c955be 522 }
184f15d5 523 }
184f15d5 524
6320cdc0 525 return $self;
11c955be 526}
b68b7ab1 527
11c955be
SH
528sub copy {
529 my $self = shift;
530 my $selfref = ref $self;
531 my $class = $selfref || $self;
9b924220 532
11c955be 533 # If called as a class method, the object to copy is the next argument.
9b924220 534
11c955be
SH
535 $self = shift() unless $selfref;
536
537 my $copy = bless {}, $class;
538
539 $copy->{sign} = $self->{sign};
0c2fbbe3
CBW
540 $copy->{_d} = $LIB->_copy($self->{_d});
541 $copy->{_n} = $LIB->_copy($self->{_n});
11c955be
SH
542 $copy->{_a} = $self->{_a} if defined $self->{_a};
543 $copy->{_p} = $self->{_p} if defined $self->{_p};
544
6320cdc0
SH
545 #($copy, $copy->{_a}, $copy->{_p})
546 # = $copy->_find_round_parameters(@_);
547
548 return $copy;
549}
550
551sub bnan {
552 my $self = shift;
553 my $selfref = ref $self;
554 my $class = $selfref || $self;
555
556 $self = bless {}, $class unless $selfref;
557
558 if ($_trap_nan) {
3cc1ad36 559 croak ("Tried to set a variable to NaN in $class->bnan()");
6320cdc0
SH
560 }
561
562 $self -> {sign} = $nan;
0c2fbbe3
CBW
563 $self -> {_n} = $LIB -> _zero();
564 $self -> {_d} = $LIB -> _one();
6320cdc0
SH
565
566 ($self, $self->{_a}, $self->{_p})
567 = $self->_find_round_parameters(@_);
568
569 return $self;
570}
571
572sub binf {
573 my $self = shift;
574 my $selfref = ref $self;
575 my $class = $selfref || $self;
576
577 $self = bless {}, $class unless $selfref;
578
579 my $sign = shift();
580 $sign = defined($sign) && substr($sign, 0, 1) eq '-' ? '-inf' : '+inf';
581
582 if ($_trap_inf) {
3cc1ad36 583 croak ("Tried to set a variable to +-inf in $class->binf()");
6320cdc0
SH
584 }
585
586 $self -> {sign} = $sign;
0c2fbbe3
CBW
587 $self -> {_n} = $LIB -> _zero();
588 $self -> {_d} = $LIB -> _one();
6320cdc0
SH
589
590 ($self, $self->{_a}, $self->{_p})
591 = $self->_find_round_parameters(@_);
592
593 return $self;
594}
595
596sub bone {
597 my $self = shift;
598 my $selfref = ref $self;
599 my $class = $selfref || $self;
600
601 $self = bless {}, $class unless $selfref;
602
603 my $sign = shift();
604 $sign = '+' unless defined($sign) && $sign eq '-';
605
606 $self -> {sign} = $sign;
0c2fbbe3
CBW
607 $self -> {_n} = $LIB -> _one();
608 $self -> {_d} = $LIB -> _one();
6320cdc0
SH
609
610 ($self, $self->{_a}, $self->{_p})
611 = $self->_find_round_parameters(@_);
612
613 return $self;
614}
615
616sub bzero {
617 my $self = shift;
618 my $selfref = ref $self;
619 my $class = $selfref || $self;
620
621 $self = bless {}, $class unless $selfref;
622
623 $self -> {sign} = '+';
0c2fbbe3
CBW
624 $self -> {_n} = $LIB -> _zero();
625 $self -> {_d} = $LIB -> _one();
6320cdc0
SH
626
627 ($self, $self->{_a}, $self->{_p})
628 = $self->_find_round_parameters(@_);
629
630 return $self;
11c955be 631}
9b924220 632
990fb837
RGS
633##############################################################################
634
6320cdc0
SH
635sub config {
636 # return (later set?) configuration data as hash ref
637 my $class = shift() || 'Math::BigRat';
990fb837 638
6320cdc0
SH
639 if (@_ == 1 && ref($_[0]) ne 'HASH') {
640 my $cfg = $class->SUPER::config();
641 return $cfg->{$_[0]};
116a1b2f
SP
642 }
643
6320cdc0 644 my $cfg = $class->SUPER::config(@_);
990fb837 645
6320cdc0
SH
646 # now we need only to override the ones that are different from our parent
647 $cfg->{class} = $class;
0c2fbbe3 648 $cfg->{with} = $LIB;
6320cdc0
SH
649
650 $cfg;
651}
990fb837
RGS
652
653##############################################################################
8f675a64 654
6320cdc0
SH
655sub bstr {
656 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
184f15d5 657
6320cdc0
SH
658 if ($x->{sign} !~ /^[+-]$/) { # inf, NaN etc
659 my $s = $x->{sign};
660 $s =~ s/^\+//; # +inf => inf
661 return $s;
184f15d5
JH
662 }
663
6320cdc0
SH
664 my $s = '';
665 $s = $x->{sign} if $x->{sign} ne '+'; # '+3/2' => '3/2'
184f15d5 666
0c2fbbe3
CBW
667 return $s . $LIB->_str($x->{_n}) if $LIB->_is_one($x->{_d});
668 $s . $LIB->_str($x->{_n}) . '/' . $LIB->_str($x->{_d});
6320cdc0 669}
184f15d5 670
6320cdc0
SH
671sub bsstr {
672 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
184f15d5 673
6320cdc0 674 if ($x->{sign} !~ /^[+-]$/) { # inf, NaN etc
15f1cdaa 675 my $s = $x->{sign};
6320cdc0
SH
676 $s =~ s/^\+//; # +inf => inf
677 return $s;
184f15d5 678 }
ccbfef19 679
6320cdc0
SH
680 my $s = '';
681 $s = $x->{sign} if $x->{sign} ne '+'; # +3 vs 3
0c2fbbe3 682 $s . $LIB->_str($x->{_n}) . '/' . $LIB->_str($x->{_d});
6320cdc0 683}
184f15d5 684
6320cdc0
SH
685sub bnorm {
686 # reduce the number to the shortest form
687 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
184f15d5 688
6320cdc0 689 # Both parts must be objects of whatever we are using today.
0c2fbbe3 690 if (my $c = $LIB->_check($x->{_n})) {
3cc1ad36 691 croak("n did not pass the self-check ($c) in bnorm()");
990fb837 692 }
0c2fbbe3 693 if (my $c = $LIB->_check($x->{_d})) {
3cc1ad36 694 croak("d did not pass the self-check ($c) in bnorm()");
990fb837 695 }
6de7f0cc 696
6320cdc0
SH
697 # no normalize for NaN, inf etc.
698 return $x if $x->{sign} !~ /^[+-]$/;
6de7f0cc 699
6320cdc0 700 # normalize zeros to 0/1
0c2fbbe3 701 if ($LIB->_is_zero($x->{_n})) {
6320cdc0 702 $x->{sign} = '+'; # never leave a -0
0c2fbbe3 703 $x->{_d} = $LIB->_one() unless $LIB->_is_one($x->{_d});
6320cdc0 704 return $x;
184f15d5
JH
705 }
706
0c2fbbe3 707 return $x if $LIB->_is_one($x->{_d}); # no need to reduce
6de7f0cc 708
6320cdc0 709 # Compute the GCD.
0c2fbbe3
CBW
710 my $gcd = $LIB->_gcd($LIB->_copy($x->{_n}), $x->{_d});
711 if (!$LIB->_is_one($gcd)) {
712 $x->{_n} = $LIB->_div($x->{_n}, $gcd);
713 $x->{_d} = $LIB->_div($x->{_d}, $gcd);
184f15d5 714 }
6320cdc0
SH
715
716 $x;
717}
184f15d5
JH
718
719##############################################################################
b68b7ab1
T
720# sign manipulation
721
6320cdc0
SH
722sub bneg {
723 # (BRAT or num_str) return BRAT
724 # negate number or make a negated number from string
725 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
b68b7ab1 726
6320cdc0 727 return $x if $x->modify('bneg');
b68b7ab1 728
6320cdc0
SH
729 # for +0 do not negate (to have always normalized +0). Does nothing for 'NaN'
730 $x->{sign} =~ tr/+-/-+/
0c2fbbe3 731 unless ($x->{sign} eq '+' && $LIB->_is_zero($x->{_n}));
6320cdc0
SH
732 $x;
733}
b68b7ab1
T
734
735##############################################################################
184f15d5
JH
736# special values
737
6320cdc0
SH
738sub _bnan {
739 # used by parent class bnan() to initialize number to NaN
740 my $self = shift;
990fb837 741
6320cdc0
SH
742 if ($_trap_nan) {
743 my $class = ref($self);
744 # "$self" below will stringify the object, this blows up if $self is a
745 # partial object (happens under trap_nan), so fix it beforehand
0c2fbbe3
CBW
746 $self->{_d} = $LIB->_zero() unless defined $self->{_d};
747 $self->{_n} = $LIB->_zero() unless defined $self->{_n};
3cc1ad36 748 croak ("Tried to set $self to NaN in $class\::_bnan()");
990fb837 749 }
0c2fbbe3
CBW
750 $self->{_n} = $LIB->_zero();
751 $self->{_d} = $LIB->_zero();
6320cdc0 752}
184f15d5 753
6320cdc0
SH
754sub _binf {
755 # used by parent class bone() to initialize number to +inf/-inf
756 my $self = shift;
990fb837 757
6320cdc0
SH
758 if ($_trap_inf) {
759 my $class = ref($self);
760 # "$self" below will stringify the object, this blows up if $self is a
761 # partial object (happens under trap_nan), so fix it beforehand
0c2fbbe3
CBW
762 $self->{_d} = $LIB->_zero() unless defined $self->{_d};
763 $self->{_n} = $LIB->_zero() unless defined $self->{_n};
3cc1ad36 764 croak ("Tried to set $self to inf in $class\::_binf()");
990fb837 765 }
0c2fbbe3
CBW
766 $self->{_n} = $LIB->_zero();
767 $self->{_d} = $LIB->_zero();
6320cdc0
SH
768}
769
770sub _bone {
771 # used by parent class bone() to initialize number to +1/-1
772 my $self = shift;
0c2fbbe3
CBW
773 $self->{_n} = $LIB->_one();
774 $self->{_d} = $LIB->_one();
6320cdc0
SH
775}
776
777sub _bzero {
778 # used by parent class bzero() to initialize number to 0
779 my $self = shift;
0c2fbbe3
CBW
780 $self->{_n} = $LIB->_zero();
781 $self->{_d} = $LIB->_one();
6320cdc0 782}
184f15d5
JH
783
784##############################################################################
785# mul/add/div etc
786
6320cdc0
SH
787sub badd {
788 # add two rational numbers
7d341013 789
6320cdc0
SH
790 # set up parameters
791 my ($class, $x, $y, @r) = (ref($_[0]), @_);
792 # objectify is costly, so avoid it
793 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
794 ($class, $x, $y, @r) = objectify(2, @_);
7d341013 795 }
184f15d5 796
6853e8af
RL
797 unless ($x -> is_finite() && $y -> is_finite()) {
798 if ($x -> is_nan() || $y -> is_nan()) {
799 return $x -> bnan(@r);
800 } elsif ($x -> is_inf("+")) {
801 return $x -> bnan(@r) if $y -> is_inf("-");
802 return $x -> binf("+", @r);
803 } elsif ($x -> is_inf("-")) {
804 return $x -> bnan(@r) if $y -> is_inf("+");
805 return $x -> binf("-", @r);
806 } elsif ($y -> is_inf("+")) {
807 return $x -> binf("+", @r);
808 } elsif ($y -> is_inf("-")) {
809 return $x -> binf("-", @r);
810 }
811 }
184f15d5 812
6320cdc0
SH
813 # 1 1 gcd(3, 4) = 1 1*3 + 1*4 7
814 # - + - = --------- = --
815 # 4 3 4*3 12
184f15d5 816
6320cdc0
SH
817 # we do not compute the gcd() here, but simple do:
818 # 5 7 5*3 + 7*4 43
819 # - + - = --------- = --
820 # 4 3 4*3 12
ccbfef19 821
6320cdc0 822 # and bnorm() will then take care of the rest
184f15d5 823
6320cdc0 824 # 5 * 3
0c2fbbe3 825 $x->{_n} = $LIB->_mul($x->{_n}, $y->{_d});
7d341013 826
6320cdc0 827 # 7 * 4
0c2fbbe3 828 my $m = $LIB->_mul($LIB->_copy($y->{_n}), $x->{_d});
184f15d5 829
6320cdc0
SH
830 # 5 * 3 + 7 * 4
831 ($x->{_n}, $x->{sign}) = _e_add($x->{_n}, $m, $x->{sign}, $y->{sign});
184f15d5 832
6320cdc0 833 # 4 * 3
0c2fbbe3 834 $x->{_d} = $LIB->_mul($x->{_d}, $y->{_d});
184f15d5 835
6320cdc0
SH
836 # normalize result, and possible round
837 $x->bnorm()->round(@r);
838}
184f15d5 839
6320cdc0
SH
840sub bsub {
841 # subtract two rational numbers
7d341013 842
6320cdc0
SH
843 # set up parameters
844 my ($class, $x, $y, @r) = (ref($_[0]), @_);
845 # objectify is costly, so avoid it
846 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
847 ($class, $x, $y, @r) = objectify(2, @_);
7d341013 848 }
184f15d5 849
6320cdc0
SH
850 # flip sign of $x, call badd(), then flip sign of result
851 $x->{sign} =~ tr/+-/-+/
0c2fbbe3 852 unless $x->{sign} eq '+' && $LIB->_is_zero($x->{_n}); # not -0
6320cdc0
SH
853 $x->badd($y, @r); # does norm and round
854 $x->{sign} =~ tr/+-/-+/
0c2fbbe3 855 unless $x->{sign} eq '+' && $LIB->_is_zero($x->{_n}); # not -0
6320cdc0
SH
856
857 $x;
858}
859
860sub bmul {
861 # multiply two rational numbers
862
863 # set up parameters
864 my ($class, $x, $y, @r) = (ref($_[0]), @_);
865 # objectify is costly, so avoid it
866 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
867 ($class, $x, $y, @r) = objectify(2, @_);
7d341013 868 }
184f15d5 869
0c2fbbe3 870 return $x->bnan() if $x->{sign} eq 'NaN' || $y->{sign} eq 'NaN';
184f15d5 871
6320cdc0 872 # inf handling
0c2fbbe3 873 if ($x->{sign} =~ /^[+-]inf$/ || $y->{sign} =~ /^[+-]inf$/) {
6320cdc0
SH
874 return $x->bnan() if $x->is_zero() || $y->is_zero();
875 # result will always be +-inf:
876 # +inf * +/+inf => +inf, -inf * -/-inf => +inf
877 # +inf * -/-inf => -inf, -inf * +/+inf => -inf
878 return $x->binf() if ($x->{sign} =~ /^\+/ && $y->{sign} =~ /^\+/);
879 return $x->binf() if ($x->{sign} =~ /^-/ && $y->{sign} =~ /^-/);
880 return $x->binf('-');
184f15d5
JH
881 }
882
0c2fbbe3
CBW
883 # x == 0 # also: or y == 1 or y == -1
884 return wantarray ? ($x, $class->bzero()) : $x if $x -> is_zero();
184f15d5 885
0c2fbbe3
CBW
886 if ($y -> is_zero()) {
887 $x -> bzero();
888 return wantarray ? ($x, $class->bzero()) : $x;
889 }
184f15d5 890
0c2fbbe3
CBW
891 # According to Knuth, this can be optimized by doing gcd twice (for d
892 # and n) and reducing in one step. This saves us a bnorm() at the end.
893 #
894 # p s p * s (p / gcd(p, r)) * (s / gcd(s, q))
895 # - * - = ----- = ---------------------------------
896 # q r q * r (q / gcd(s, q)) * (r / gcd(p, r))
ccbfef19 897
0c2fbbe3
CBW
898 my $gcd_pr = $LIB -> _gcd($LIB -> _copy($x->{_n}), $y->{_d});
899 my $gcd_sq = $LIB -> _gcd($LIB -> _copy($y->{_n}), $x->{_d});
900
901 $x->{_n} = $LIB -> _mul(scalar $LIB -> _div($x->{_n}, $gcd_pr),
92c15a49
EH
902 scalar $LIB -> _div($LIB -> _copy($y->{_n}),
903 $gcd_sq));
0c2fbbe3 904 $x->{_d} = $LIB -> _mul(scalar $LIB -> _div($x->{_d}, $gcd_sq),
92c15a49
EH
905 scalar $LIB -> _div($LIB -> _copy($y->{_d}),
906 $gcd_pr));
184f15d5 907
6320cdc0
SH
908 # compute new sign
909 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
184f15d5 910
0c2fbbe3 911 $x->round(@r);
6320cdc0 912}
184f15d5 913
6320cdc0
SH
914sub bdiv {
915 # (dividend: BRAT or num_str, divisor: BRAT or num_str) return
916 # (BRAT, BRAT) (quo, rem) or BRAT (only rem)
7d341013 917
6320cdc0
SH
918 # set up parameters
919 my ($class, $x, $y, @r) = (ref($_[0]), @_);
920 # objectify is costly, so avoid it
921 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
922 ($class, $x, $y, @r) = objectify(2, @_);
7d341013 923 }
184f15d5 924
6320cdc0 925 return $x if $x->modify('bdiv');
184f15d5 926
6320cdc0 927 my $wantarray = wantarray; # call only once
3f185657
PJA
928
929 # At least one argument is NaN. This is handled the same way as in
930 # Math::BigInt -> bdiv(). See the comments in the code implementing that
931 # method.
932
933 if ($x -> is_nan() || $y -> is_nan()) {
6320cdc0 934 return $wantarray ? ($x -> bnan(), $class -> bnan()) : $x -> bnan();
3f185657
PJA
935 }
936
937 # Divide by zero and modulo zero. This is handled the same way as in
938 # Math::BigInt -> bdiv(). See the comments in the code implementing that
939 # method.
940
941 if ($y -> is_zero()) {
942 my ($quo, $rem);
943 if ($wantarray) {
944 $rem = $x -> copy();
945 }
946 if ($x -> is_zero()) {
947 $quo = $x -> bnan();
948 } else {
949 $quo = $x -> binf($x -> {sign});
950 }
951 return $wantarray ? ($quo, $rem) : $quo;
952 }
953
954 # Numerator (dividend) is +/-inf. This is handled the same way as in
955 # Math::BigInt -> bdiv(). See the comments in the code implementing that
956 # method.
957
958 if ($x -> is_inf()) {
959 my ($quo, $rem);
6320cdc0 960 $rem = $class -> bnan() if $wantarray;
3f185657
PJA
961 if ($y -> is_inf()) {
962 $quo = $x -> bnan();
963 } else {
964 my $sign = $x -> bcmp(0) == $y -> bcmp(0) ? '+' : '-';
965 $quo = $x -> binf($sign);
966 }
6320cdc0
SH
967 return $wantarray ? ($quo, $rem) : $quo;
968 }
969
970 # Denominator (divisor) is +/-inf. This is handled the same way as in
971 # Math::BigFloat -> bdiv(). See the comments in the code implementing that
972 # method.
973
974 if ($y -> is_inf()) {
975 my ($quo, $rem);
976 if ($wantarray) {
977 if ($x -> is_zero() || $x -> bcmp(0) == $y -> bcmp(0)) {
978 $rem = $x -> copy();
979 $quo = $x -> bzero();
980 } else {
981 $rem = $class -> binf($y -> {sign});
982 $quo = $x -> bone('-');
983 }
984 return ($quo, $rem);
985 } else {
986 if ($y -> is_inf()) {
987 if ($x -> is_nan() || $x -> is_inf()) {
988 return $x -> bnan();
989 } else {
990 return $x -> bzero();
991 }
992 }
993 }
994 }
995
996 # At this point, both the numerator and denominator are finite numbers, and
997 # the denominator (divisor) is non-zero.
998
999 # x == 0?
1000 return wantarray ? ($x, $class->bzero()) : $x if $x->is_zero();
1001
1002 # XXX TODO: list context, upgrade
1003 # According to Knuth, this can be optimized by doing gcd twice (for d and n)
1004 # and reducing in one step. This would save us the bnorm() at the end.
0c2fbbe3
CBW
1005 #
1006 # p r p * s (p / gcd(p, r)) * (s / gcd(s, q))
1007 # - / - = ----- = ---------------------------------
1008 # q s q * r (q / gcd(s, q)) * (r / gcd(p, r))
6320cdc0 1009
0c2fbbe3
CBW
1010 $x->{_n} = $LIB->_mul($x->{_n}, $y->{_d});
1011 $x->{_d} = $LIB->_mul($x->{_d}, $y->{_n});
6320cdc0
SH
1012
1013 # compute new sign
1014 $x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
1015
1016 $x -> bnorm();
1017 if (wantarray) {
1018 my $rem = $x -> copy();
1019 $x -> bfloor();
1020 $x -> round(@r);
1021 $rem -> bsub($x -> copy()) -> bmul($y);
1022 return $x, $rem;
1023 } else {
1024 $x -> round(@r);
1025 return $x;
1026 }
1027}
1028
1029sub bmod {
1030 # compute "remainder" (in Perl way) of $x / $y
1031
1032 # set up parameters
1033 my ($class, $x, $y, @r) = (ref($_[0]), @_);
1034 # objectify is costly, so avoid it
1035 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
1036 ($class, $x, $y, @r) = objectify(2, @_);
1037 }
1038
1039 return $x if $x->modify('bmod');
1040
1041 # At least one argument is NaN. This is handled the same way as in
1042 # Math::BigInt -> bmod().
1043
1044 if ($x -> is_nan() || $y -> is_nan()) {
1045 return $x -> bnan();
1046 }
1047
1048 # Modulo zero. This is handled the same way as in Math::BigInt -> bmod().
1049
1050 if ($y -> is_zero()) {
1051 return $x;
1052 }
1053
1054 # Numerator (dividend) is +/-inf. This is handled the same way as in
1055 # Math::BigInt -> bmod().
1056
1057 if ($x -> is_inf()) {
1058 return $x -> bnan();
1059 }
1060
1061 # Denominator (divisor) is +/-inf. This is handled the same way as in
1062 # Math::BigInt -> bmod().
1063
1064 if ($y -> is_inf()) {
1065 if ($x -> is_zero() || $x -> bcmp(0) == $y -> bcmp(0)) {
1066 return $x;
1067 } else {
1068 return $x -> binf($y -> sign());
1069 }
1070 }
1071
1072 # At this point, both the numerator and denominator are finite numbers, and
1073 # the denominator (divisor) is non-zero.
1074
1075 return $x if $x->is_zero(); # 0 / 7 = 0, mod 0
1076
1077 # Compute $x - $y * floor($x/$y). This can probably be optimized by working
1078 # on a lower level.
1079
1080 $x -> bsub($x -> copy() -> bdiv($y) -> bfloor() -> bmul($y));
1081 return $x -> round(@r);
1082}
1083
1084##############################################################################
1085# bdec/binc
1086
1087sub bdec {
1088 # decrement value (subtract 1)
1089 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1090
1091 return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
1092
1093 if ($x->{sign} eq '-') {
0c2fbbe3 1094 $x->{_n} = $LIB->_add($x->{_n}, $x->{_d}); # -5/2 => -7/2
6320cdc0 1095 } else {
0c2fbbe3 1096 if ($LIB->_acmp($x->{_n}, $x->{_d}) < 0) # n < d?
6320cdc0
SH
1097 {
1098 # 1/3 -- => -2/3
0c2fbbe3 1099 $x->{_n} = $LIB->_sub($LIB->_copy($x->{_d}), $x->{_n});
6320cdc0
SH
1100 $x->{sign} = '-';
1101 } else {
0c2fbbe3 1102 $x->{_n} = $LIB->_sub($x->{_n}, $x->{_d}); # 5/2 => 3/2
6320cdc0
SH
1103 }
1104 }
1105 $x->bnorm()->round(@r);
1106}
1107
1108sub binc {
1109 # increment value (add 1)
1110 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1111
1112 return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
1113
1114 if ($x->{sign} eq '-') {
0c2fbbe3 1115 if ($LIB->_acmp($x->{_n}, $x->{_d}) < 0) {
6320cdc0 1116 # -1/3 ++ => 2/3 (overflow at 0)
0c2fbbe3 1117 $x->{_n} = $LIB->_sub($LIB->_copy($x->{_d}), $x->{_n});
6320cdc0
SH
1118 $x->{sign} = '+';
1119 } else {
0c2fbbe3 1120 $x->{_n} = $LIB->_sub($x->{_n}, $x->{_d}); # -5/2 => -3/2
6320cdc0
SH
1121 }
1122 } else {
0c2fbbe3 1123 $x->{_n} = $LIB->_add($x->{_n}, $x->{_d}); # 5/2 => 7/2
6320cdc0
SH
1124 }
1125 $x->bnorm()->round(@r);
1126}
1127
6853e8af
RL
1128sub binv {
1129 my $x = shift;
1130 my @r = @_;
1131
1132 return $x if $x->modify('binv');
1133
1134 return $x if $x -> is_nan();
1135 return $x -> bzero() if $x -> is_inf();
1136 return $x -> binf("+") if $x -> is_zero();
1137
1138 ($x -> {_n}, $x -> {_d}) = ($x -> {_d}, $x -> {_n});
1139 $x -> round(@r);
1140}
1141
6320cdc0
SH
1142##############################################################################
1143# is_foo methods (the rest is inherited)
1144
1145sub is_int {
1146 # return true if arg (BRAT or num_str) is an integer
1147 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1148
1149 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN and +-inf aren't
0c2fbbe3 1150 $LIB->_is_one($x->{_d}); # x/y && y != 1 => no integer
6320cdc0
SH
1151 0;
1152}
1153
1154sub is_zero {
1155 # return true if arg (BRAT or num_str) is zero
1156 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1157
0c2fbbe3 1158 return 1 if $x->{sign} eq '+' && $LIB->_is_zero($x->{_n});
6320cdc0
SH
1159 0;
1160}
1161
1162sub is_one {
1163 # return true if arg (BRAT or num_str) is +1 or -1 if signis given
1164 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1165
3cc1ad36
SH
1166 croak "too many arguments for is_one()" if @_ > 2;
1167 my $sign = $_[1] || '';
1168 $sign = '+' if $sign ne '-';
1169 return 1 if ($x->{sign} eq $sign &&
1170 $LIB->_is_one($x->{_n}) && $LIB->_is_one($x->{_d}));
6320cdc0
SH
1171 0;
1172}
1173
1174sub is_odd {
1175 # return true if arg (BFLOAT or num_str) is odd or false if even
1176 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1177
1178 return 1 if ($x->{sign} =~ /^[+-]$/) && # NaN & +-inf aren't
0c2fbbe3 1179 ($LIB->_is_one($x->{_d}) && $LIB->_is_odd($x->{_n})); # x/2 is not, but 3/1
6320cdc0
SH
1180 0;
1181}
1182
1183sub is_even {
1184 # return true if arg (BINT or num_str) is even or false if odd
1185 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1186
1187 return 0 if $x->{sign} !~ /^[+-]$/; # NaN & +-inf aren't
0c2fbbe3
CBW
1188 return 1 if ($LIB->_is_one($x->{_d}) # x/3 is never
1189 && $LIB->_is_even($x->{_n})); # but 4/1 is
6320cdc0
SH
1190 0;
1191}
1192
1193##############################################################################
1194# parts() and friends
1195
1196sub numerator {
1197 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1198
1199 # NaN, inf, -inf
1200 return Math::BigInt->new($x->{sign}) if ($x->{sign} !~ /^[+-]$/);
1201
0c2fbbe3 1202 my $n = Math::BigInt->new($LIB->_str($x->{_n}));
6320cdc0
SH
1203 $n->{sign} = $x->{sign};
1204 $n;
1205}
1206
1207sub denominator {
1208 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1209
1210 # NaN
1211 return Math::BigInt->new($x->{sign}) if $x->{sign} eq 'NaN';
1212 # inf, -inf
1213 return Math::BigInt->bone() if $x->{sign} !~ /^[+-]$/;
1214
0c2fbbe3 1215 Math::BigInt->new($LIB->_str($x->{_d}));
6320cdc0
SH
1216}
1217
1218sub parts {
1219 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1220
1221 my $c = 'Math::BigInt';
1222
1223 return ($c->bnan(), $c->bnan()) if $x->{sign} eq 'NaN';
1224 return ($c->binf(), $c->binf()) if $x->{sign} eq '+inf';
1225 return ($c->binf('-'), $c->binf()) if $x->{sign} eq '-inf';
1226
0c2fbbe3 1227 my $n = $c->new($LIB->_str($x->{_n}));
6320cdc0 1228 $n->{sign} = $x->{sign};
0c2fbbe3 1229 my $d = $c->new($LIB->_str($x->{_d}));
6320cdc0
SH
1230 ($n, $d);
1231}
1232
6853e8af
RL
1233sub dparts {
1234 my $x = shift;
1235 my $class = ref $x;
1236
1237 croak("dparts() is an instance method") unless $class;
1238
1239 if ($x -> is_nan()) {
1240 return $class -> bnan(), $class -> bnan() if wantarray;
1241 return $class -> bnan();
1242 }
1243
1244 if ($x -> is_inf()) {
1245 return $class -> binf($x -> sign()), $class -> bzero() if wantarray;
1246 return $class -> binf($x -> sign());
1247 }
1248
1249 # 355/113 => 3 + 16/113
1250
1251 my ($q, $r) = $LIB -> _div($LIB -> _copy($x -> {_n}), $x -> {_d});
1252
1253 my $int = Math::BigRat -> new($x -> {sign} . $LIB -> _str($q));
1254 return $int unless wantarray;
1255
1256 my $frc = Math::BigRat -> new($x -> {sign} . $LIB -> _str($r),
1257 $LIB -> _str($x -> {_d}));
1258
1259 return $int, $frc;
1260}
1261
6320cdc0
SH
1262sub length {
1263 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
1264
1265 return $nan unless $x->is_int();
0c2fbbe3 1266 $LIB->_len($x->{_n}); # length(-123/1) => length(123)
6320cdc0
SH
1267}
1268
1269sub digit {
1270 my ($class, $x, $n) = ref($_[0]) ? (undef, $_[0], $_[1]) : objectify(1, @_);
1271
1272 return $nan unless $x->is_int();
0c2fbbe3 1273 $LIB->_digit($x->{_n}, $n || 0); # digit(-123/1, 2) => digit(123, 2)
6320cdc0
SH
1274}
1275
1276##############################################################################
1277# special calc routines
1278
1279sub bceil {
1280 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1281
1282 return $x if ($x->{sign} !~ /^[+-]$/ || # not for NaN, inf
0c2fbbe3 1283 $LIB->_is_one($x->{_d})); # 22/1 => 22, 0/1 => 0
6320cdc0 1284
0c2fbbe3
CBW
1285 $x->{_n} = $LIB->_div($x->{_n}, $x->{_d}); # 22/7 => 3/1 w/ truncate
1286 $x->{_d} = $LIB->_one(); # d => 1
1287 $x->{_n} = $LIB->_inc($x->{_n}) if $x->{sign} eq '+'; # +22/7 => 4/1
1288 $x->{sign} = '+' if $x->{sign} eq '-' && $LIB->_is_zero($x->{_n}); # -0 => 0
6320cdc0
SH
1289 $x;
1290}
1291
1292sub bfloor {
1293 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
1294
1295 return $x if ($x->{sign} !~ /^[+-]$/ || # not for NaN, inf
0c2fbbe3 1296 $LIB->_is_one($x->{_d})); # 22/1 => 22, 0/1 => 0
6320cdc0 1297
0c2fbbe3
CBW
1298 $x->{_n} = $LIB->_div($x->{_n}, $x->{_d}); # 22/7 => 3/1 w/ truncate
1299 $x->{_d} = $LIB->_one(); # d => 1
1300 $x->{_n} = $LIB->_inc($x->{_n}) if $x->{sign} eq '-'; # -22/7 => -4/1
6320cdc0
SH
1301 $x;
1302}
1303
1304sub bint {
7deec013 1305 my ($class, $x) = ref($_[0]) ? (ref($_[0]), $_[0]) : objectify(1, @_);
6320cdc0
SH
1306
1307 return $x if ($x->{sign} !~ /^[+-]$/ || # +/-inf or NaN
0c2fbbe3 1308 $LIB -> _is_one($x->{_d})); # already an integer
6320cdc0 1309
0c2fbbe3
CBW
1310 $x->{_n} = $LIB->_div($x->{_n}, $x->{_d}); # 22/7 => 3/1 w/ truncate
1311 $x->{_d} = $LIB->_one(); # d => 1
1312 $x->{sign} = '+' if $x->{sign} eq '-' && $LIB -> _is_zero($x->{_n});
6320cdc0
SH
1313 return $x;
1314}
1315
1316sub bfac {
1317 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
1318
1319 # if $x is not an integer
0c2fbbe3 1320 if (($x->{sign} ne '+') || (!$LIB->_is_one($x->{_d}))) {
6320cdc0
SH
1321 return $x->bnan();
1322 }
1323
0c2fbbe3 1324 $x->{_n} = $LIB->_fac($x->{_n});
6320cdc0
SH
1325 # since _d is 1, we don't need to reduce/norm the result
1326 $x->round(@r);
1327}
1328
1329sub bpow {
1330 # power ($x ** $y)
1331
1332 # set up parameters
1333 my ($class, $x, $y, @r) = (ref($_[0]), @_);
1334
1335 # objectify is costly, so avoid it
1336 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
1337 ($class, $x, $y, @r) = objectify(2, @_);
1338 }
1339
3cc1ad36
SH
1340 # $x and/or $y is a NaN
1341 return $x->bnan() if $x->is_nan() || $y->is_nan();
6320cdc0 1342
3cc1ad36
SH
1343 # $x and/or $y is a +/-Inf
1344 if ($x->is_inf("-")) {
1345 return $x->bzero() if $y->is_negative();
1346 return $x->bnan() if $y->is_zero();
1347 return $x if $y->is_odd();
1348 return $x->bneg();
1349 } elsif ($x->is_inf("+")) {
1350 return $x->bzero() if $y->is_negative();
1351 return $x->bnan() if $y->is_zero();
1352 return $x;
1353 } elsif ($y->is_inf("-")) {
1354 return $x->bnan() if $x -> is_one("-");
1355 return $x->binf("+") if $x > -1 && $x < 1;
1356 return $x->bone() if $x -> is_one("+");
1357 return $x->bzero();
1358 } elsif ($y->is_inf("+")) {
1359 return $x->bnan() if $x -> is_one("-");
1360 return $x->bzero() if $x > -1 && $x < 1;
1361 return $x->bone() if $x -> is_one("+");
1362 return $x->binf("+");
1363 }
1364
1365 if ($x->is_zero()) {
1366 return $x->binf() if $y->is_negative();
1367 return $x->bone("+") if $y->is_zero();
1368 return $x;
1369 } elsif ($x->is_one()) {
1370 return $x->round(@r) if $y->is_odd(); # x is -1, y is odd => -1
1371 return $x->babs()->round(@r); # x is -1, y is even => 1
1372 } elsif ($y->is_zero()) {
1373 return $x->bone(@r); # x^0 and x != 0 => 1
1374 } elsif ($y->is_one()) {
1375 return $x->round(@r); # x^1 => x
6320cdc0 1376 }
6320cdc0 1377
3cc1ad36
SH
1378 # we don't support complex numbers, so return NaN
1379 return $x->bnan() if $x->is_negative() && !$y->is_int();
6320cdc0 1380
3cc1ad36
SH
1381 # (a/b)^-(c/d) = (b/a)^(c/d)
1382 ($x->{_n}, $x->{_d}) = ($x->{_d}, $x->{_n}) if $y->is_negative();
6320cdc0 1383
3cc1ad36
SH
1384 unless ($LIB->_is_one($y->{_n})) {
1385 $x->{_n} = $LIB->_pow($x->{_n}, $y->{_n});
0c2fbbe3 1386 $x->{_d} = $LIB->_pow($x->{_d}, $y->{_n});
0c2fbbe3 1387 $x->{sign} = '+' if $x->{sign} eq '-' && $LIB->_is_even($y->{_n});
6320cdc0
SH
1388 }
1389
3cc1ad36
SH
1390 unless ($LIB->_is_one($y->{_d})) {
1391 return $x->bsqrt(@r) if $LIB->_is_two($y->{_d}); # 1/2 => sqrt
1392 return $x->broot($LIB->_str($y->{_d}), @r); # 1/N => root(N)
1393 }
6320cdc0 1394
3cc1ad36 1395 return $x->round(@r);
6320cdc0
SH
1396}
1397
1398sub blog {
1399 # Return the logarithm of the operand. If a second operand is defined, that
1400 # value is used as the base, otherwise the base is assumed to be Euler's
1401 # constant.
1402
92c15a49
EH
1403 my ($class, $x, $base, @r);
1404
6320cdc0
SH
1405 # Don't objectify the base, since an undefined base, as in $x->blog() or
1406 # $x->blog(undef) signals that the base is Euler's number.
1407
92c15a49 1408 if (!ref($_[0]) && $_[0] =~ /^[A-Za-z]|::/) {
6853e8af 1409 # E.g., Math::BigRat->blog(256, 2)
92c15a49
EH
1410 ($class, $x, $base, @r) =
1411 defined $_[2] ? objectify(2, @_) : objectify(1, @_);
1412 } else {
6853e8af 1413 # E.g., Math::BigRat::blog(256, 2) or $x->blog(2)
92c15a49
EH
1414 ($class, $x, $base, @r) =
1415 defined $_[1] ? objectify(2, @_) : objectify(1, @_);
6320cdc0
SH
1416 }
1417
1418 return $x if $x->modify('blog');
1419
1420 # Handle all exception cases and all trivial cases. I have used Wolfram Alpha
1421 # (http://www.wolframalpha.com) as the reference for these cases.
1422
1423 return $x -> bnan() if $x -> is_nan();
1424
1425 if (defined $base) {
1426 $base = $class -> new($base) unless ref $base;
1427 if ($base -> is_nan() || $base -> is_one()) {
1428 return $x -> bnan();
1429 } elsif ($base -> is_inf() || $base -> is_zero()) {
1430 return $x -> bnan() if $x -> is_inf() || $x -> is_zero();
1431 return $x -> bzero();
1432 } elsif ($base -> is_negative()) { # -inf < base < 0
1433 return $x -> bzero() if $x -> is_one(); # x = 1
1434 return $x -> bone() if $x == $base; # x = base
1435 return $x -> bnan(); # otherwise
1436 }
1437 return $x -> bone() if $x == $base; # 0 < base && 0 < x < inf
1438 }
1439
1440 # We now know that the base is either undefined or positive and finite.
1441
1442 if ($x -> is_inf()) { # x = +/-inf
1443 my $sign = defined $base && $base < 1 ? '-' : '+';
1444 return $x -> binf($sign);
1445 } elsif ($x -> is_neg()) { # -inf < x < 0
1446 return $x -> bnan();
1447 } elsif ($x -> is_one()) { # x = 1
1448 return $x -> bzero();
1449 } elsif ($x -> is_zero()) { # x = 0
1450 my $sign = defined $base && $base < 1 ? '+' : '-';
1451 return $x -> binf($sign);
1452 }
1453
6853e8af
RL
1454 # Now take care of the cases where $x and/or $base is 1/N.
1455 #
1456 # log(1/N) / log(B) = -log(N)/log(B)
1457 # log(1/N) / log(1/B) = log(N)/log(B)
1458 # log(N) / log(1/B) = -log(N)/log(B)
1459
1460 my $neg = 0;
1461 if ($x -> numerator() -> is_one()) {
1462 $x -> binv();
1463 $neg = !$neg;
1464 }
1465 if (defined(blessed($base)) && $base -> isa($class)) {
1466 if ($base -> numerator() -> is_one()) {
1467 $base = $base -> copy() -> binv();
1468 $neg = !$neg;
1469 }
1470 }
1471
6320cdc0
SH
1472 # At this point we are done handling all exception cases and trivial cases.
1473
1474 $base = Math::BigFloat -> new($base) if defined $base;
1475
0c2fbbe3
CBW
1476 my $xn = Math::BigFloat -> new($LIB -> _str($x->{_n}));
1477 my $xd = Math::BigFloat -> new($LIB -> _str($x->{_d}));
6320cdc0
SH
1478
1479 my $xtmp = Math::BigRat -> new($xn -> bdiv($xd) -> blog($base, @r) -> bsstr());
1480
1481 $x -> {sign} = $xtmp -> {sign};
1482 $x -> {_n} = $xtmp -> {_n};
1483 $x -> {_d} = $xtmp -> {_d};
1484
6853e8af 1485 return $neg ? $x -> bneg() : $x;
6320cdc0
SH
1486}
1487
1488sub bexp {
1489 # set up parameters
1490 my ($class, $x, $y, @r) = (ref($_[0]), @_);
1491
1492 # objectify is costly, so avoid it
1493 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
92c15a49 1494 ($class, $x, $y, @r) = objectify(1, @_);
6320cdc0
SH
1495 }
1496
1497 return $x->binf(@r) if $x->{sign} eq '+inf';
1498 return $x->bzero(@r) if $x->{sign} eq '-inf';
1499
1500 # we need to limit the accuracy to protect against overflow
1501 my $fallback = 0;
1502 my ($scale, @params);
1503 ($x, @params) = $x->_find_round_parameters(@r);
1504
1505 # also takes care of the "error in _find_round_parameters?" case
1506 return $x if $x->{sign} eq 'NaN';
1507
1508 # no rounding at all, so must use fallback
1509 if (scalar @params == 0) {
1510 # simulate old behaviour
1511 $params[0] = $class->div_scale(); # and round to it as accuracy
1512 $params[1] = undef; # P = undef
1513 $scale = $params[0]+4; # at least four more for proper round
1514 $params[2] = $r[2]; # round mode by caller or undef
1515 $fallback = 1; # to clear a/p afterwards
1516 } else {
1517 # the 4 below is empirical, and there might be cases where it's not enough...
1518 $scale = abs($params[0] || $params[1]) + 4; # take whatever is defined
1519 }
1520
1521 return $x->bone(@params) if $x->is_zero();
1522
1523 # See the comments in Math::BigFloat on how this algorithm works.
1524 # Basically we calculate A and B (where B is faculty(N)) so that A/B = e
1525
1526 my $x_org = $x->copy();
1527 if ($scale <= 75) {
1528 # set $x directly from a cached string form
1529 $x->{_n} =
0c2fbbe3 1530 $LIB->_new("90933395208605785401971970164779391644753259799242");
6320cdc0 1531 $x->{_d} =
0c2fbbe3 1532 $LIB->_new("33452526613163807108170062053440751665152000000000");
6320cdc0
SH
1533 $x->{sign} = '+';
1534 } else {
1535 # compute A and B so that e = A / B.
1536
1537 # After some terms we end up with this, so we use it as a starting point:
0c2fbbe3
CBW
1538 my $A = $LIB->_new("90933395208605785401971970164779391644753259799242");
1539 my $F = $LIB->_new(42); my $step = 42;
6320cdc0
SH
1540
1541 # Compute how many steps we need to take to get $A and $B sufficiently big
1542 my $steps = Math::BigFloat::_len_to_steps($scale - 4);
1543 # print STDERR "# Doing $steps steps for ", $scale-4, " digits\n";
1544 while ($step++ <= $steps) {
1545 # calculate $a * $f + 1
0c2fbbe3
CBW
1546 $A = $LIB->_mul($A, $F);
1547 $A = $LIB->_inc($A);
6320cdc0 1548 # increment f
0c2fbbe3 1549 $F = $LIB->_inc($F);
6320cdc0
SH
1550 }
1551 # compute $B as factorial of $steps (this is faster than doing it manually)
0c2fbbe3 1552 my $B = $LIB->_fac($LIB->_new($steps));
6320cdc0 1553
0c2fbbe3 1554 # print "A ", $LIB->_str($A), "\nB ", $LIB->_str($B), "\n";
6320cdc0
SH
1555
1556 $x->{_n} = $A;
1557 $x->{_d} = $B;
1558 $x->{sign} = '+';
3f185657
PJA
1559 }
1560
6320cdc0
SH
1561 # $x contains now an estimate of e, with some surplus digits, so we can round
1562 if (!$x_org->is_one()) {
1563 # raise $x to the wanted power and round it in one step:
1564 $x->bpow($x_org, @params);
1565 } else {
1566 # else just round the already computed result
1567 delete $x->{_a}; delete $x->{_p};
1568 # shortcut to not run through _find_round_parameters again
1569 if (defined $params[0]) {
1570 $x->bround($params[0], $params[2]); # then round accordingly
1571 } else {
1572 $x->bfround($params[1], $params[2]); # then round accordingly
1573 }
1574 }
1575 if ($fallback) {
1576 # clear a/p after round, since user did not request it
1577 delete $x->{_a}; delete $x->{_p};
990fb837
RGS
1578 }
1579
6320cdc0
SH
1580 $x;
1581}
990fb837 1582
6320cdc0
SH
1583sub bnok {
1584 # set up parameters
1585 my ($class, $x, $y, @r) = (ref($_[0]), @_);
990fb837 1586
6320cdc0
SH
1587 # objectify is costly, so avoid it
1588 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
1589 ($class, $x, $y, @r) = objectify(2, @_);
3f185657 1590 }
990fb837 1591
7deec013
NB
1592 return $x->bnan() if $x->is_nan() || $y->is_nan();
1593 return $x->bnan() if (($x->is_finite() && !$x->is_int()) ||
1594 ($y->is_finite() && !$y->is_int()));
1595
1596 my $xint = Math::BigInt -> new($x -> bstr());
1597 my $yint = Math::BigInt -> new($y -> bstr());
6320cdc0 1598 $xint -> bnok($yint);
7deec013 1599 my $xrat = Math::BigRat -> new($xint);
ccbfef19 1600
7deec013
NB
1601 $x -> {sign} = $xrat -> {sign};
1602 $x -> {_n} = $xrat -> {_n};
1603 $x -> {_d} = $xrat -> {_d};
ccbfef19 1604
6320cdc0
SH
1605 return $x;
1606}
990fb837 1607
6320cdc0
SH
1608sub broot {
1609 # set up parameters
1610 my ($class, $x, $y, @r) = (ref($_[0]), @_);
1611 # objectify is costly, so avoid it
1612 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
1613 ($class, $x, $y, @r) = objectify(2, @_);
3f185657 1614 }
990fb837 1615
6320cdc0 1616 # Convert $x into a Math::BigFloat.
3f185657 1617
0c2fbbe3
CBW
1618 my $xd = Math::BigFloat -> new($LIB -> _str($x->{_d}));
1619 my $xflt = Math::BigFloat -> new($LIB -> _str($x->{_n})) -> bdiv($xd);
6320cdc0 1620 $xflt -> {sign} = $x -> {sign};
3f185657 1621
6320cdc0 1622 # Convert $y into a Math::BigFloat.
3f185657 1623
0c2fbbe3
CBW
1624 my $yd = Math::BigFloat -> new($LIB -> _str($y->{_d}));
1625 my $yflt = Math::BigFloat -> new($LIB -> _str($y->{_n})) -> bdiv($yd);
6320cdc0 1626 $yflt -> {sign} = $y -> {sign};
3f185657 1627
6320cdc0 1628 # Compute the root and convert back to a Math::BigRat.
990fb837 1629
6320cdc0
SH
1630 $xflt -> broot($yflt, @r);
1631 my $xtmp = Math::BigRat -> new($xflt -> bsstr());
a4e2b1c6 1632
6320cdc0
SH
1633 $x -> {sign} = $xtmp -> {sign};
1634 $x -> {_n} = $xtmp -> {_n};
1635 $x -> {_d} = $xtmp -> {_d};
a4e2b1c6 1636
6320cdc0
SH
1637 return $x;
1638}
a4e2b1c6 1639
6320cdc0
SH
1640sub bmodpow {
1641 # set up parameters
1642 my ($class, $x, $y, $m, @r) = (ref($_[0]), @_);
1643 # objectify is costly, so avoid it
1644 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
1645 ($class, $x, $y, $m, @r) = objectify(3, @_);
a4e2b1c6 1646 }
a4e2b1c6 1647
6320cdc0 1648 # Convert $x, $y, and $m into Math::BigInt objects.
ccbfef19 1649
6320cdc0
SH
1650 my $xint = Math::BigInt -> new($x -> copy() -> bint());
1651 my $yint = Math::BigInt -> new($y -> copy() -> bint());
1652 my $mint = Math::BigInt -> new($m -> copy() -> bint());
a4e2b1c6 1653
7deec013 1654 $xint -> bmodpow($yint, $mint, @r);
6320cdc0 1655 my $xtmp = Math::BigRat -> new($xint -> bsstr());
a4e2b1c6 1656
6320cdc0
SH
1657 $x -> {sign} = $xtmp -> {sign};
1658 $x -> {_n} = $xtmp -> {_n};
1659 $x -> {_d} = $xtmp -> {_d};
1660 return $x;
1661}
184f15d5 1662
6320cdc0
SH
1663sub bmodinv {
1664 # set up parameters
1665 my ($class, $x, $y, @r) = (ref($_[0]), @_);
1666 # objectify is costly, so avoid it
1667 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
1668 ($class, $x, $y, @r) = objectify(2, @_);
1669 }
184f15d5 1670
6320cdc0 1671 # Convert $x and $y into Math::BigInt objects.
184f15d5 1672
6320cdc0
SH
1673 my $xint = Math::BigInt -> new($x -> copy() -> bint());
1674 my $yint = Math::BigInt -> new($y -> copy() -> bint());
a4e2b1c6 1675
7deec013 1676 $xint -> bmodinv($yint, @r);
6320cdc0 1677 my $xtmp = Math::BigRat -> new($xint -> bsstr());
a4e2b1c6 1678
6320cdc0
SH
1679 $x -> {sign} = $xtmp -> {sign};
1680 $x -> {_n} = $xtmp -> {_n};
1681 $x -> {_d} = $xtmp -> {_d};
1682 return $x;
1683}
184f15d5 1684
6320cdc0
SH
1685sub bsqrt {
1686 my ($class, $x, @r) = ref($_[0]) ? (ref($_[0]), @_) : objectify(1, @_);
184f15d5 1687
6320cdc0
SH
1688 return $x->bnan() if $x->{sign} !~ /^[+]/; # NaN, -inf or < 0
1689 return $x if $x->{sign} eq '+inf'; # sqrt(inf) == inf
1690 return $x->round(@r) if $x->is_zero() || $x->is_one();
ccbfef19 1691
3cc1ad36
SH
1692 my $n = $x -> {_n};
1693 my $d = $x -> {_d};
1694
1695 # Look for an exact solution. For the numerator and the denominator, take
1696 # the square root and square it and see if we got the original value. If we
1697 # did, for both the numerator and the denominator, we have an exact
1698 # solution.
1699
1700 {
1701 my $nsqrt = $LIB -> _sqrt($LIB -> _copy($n));
1702 my $n2 = $LIB -> _mul($LIB -> _copy($nsqrt), $nsqrt);
1703 if ($LIB -> _acmp($n, $n2) == 0) {
1704 my $dsqrt = $LIB -> _sqrt($LIB -> _copy($d));
1705 my $d2 = $LIB -> _mul($LIB -> _copy($dsqrt), $dsqrt);
1706 if ($LIB -> _acmp($d, $d2) == 0) {
1707 $x -> {_n} = $nsqrt;
1708 $x -> {_d} = $dsqrt;
1709 return $x->round(@r);
1710 }
1711 }
1712 }
1713
1714 local $Math::BigFloat::upgrade = undef;
6320cdc0
SH
1715 local $Math::BigFloat::downgrade = undef;
1716 local $Math::BigFloat::precision = undef;
3cc1ad36
SH
1717 local $Math::BigFloat::accuracy = undef;
1718 local $Math::BigInt::upgrade = undef;
1719 local $Math::BigInt::precision = undef;
1720 local $Math::BigInt::accuracy = undef;
184f15d5 1721
3cc1ad36
SH
1722 my $xn = Math::BigFloat -> new($LIB -> _str($n));
1723 my $xd = Math::BigFloat -> new($LIB -> _str($d));
184f15d5 1724
6320cdc0 1725 my $xtmp = Math::BigRat -> new($xn -> bdiv($xd) -> bsqrt() -> bsstr());
12fc2493 1726
6320cdc0
SH
1727 $x -> {sign} = $xtmp -> {sign};
1728 $x -> {_n} = $xtmp -> {_n};
1729 $x -> {_d} = $xtmp -> {_d};
a4e2b1c6 1730
6320cdc0
SH
1731 $x->round(@r);
1732}
184f15d5 1733
6320cdc0 1734sub blsft {
7deec013 1735 my ($class, $x, $y, $b) = objectify(2, @_);
9b924220 1736
6320cdc0
SH
1737 $b = 2 if !defined $b;
1738 $b = $class -> new($b) unless ref($b) && $b -> isa($class);
184f15d5 1739
6320cdc0 1740 return $x -> bnan() if $x -> is_nan() || $y -> is_nan() || $b -> is_nan();
9b924220 1741
6320cdc0
SH
1742 # shift by a negative amount?
1743 return $x -> brsft($y -> copy() -> babs(), $b) if $y -> {sign} =~ /^-/;
184f15d5 1744
6320cdc0
SH
1745 $x -> bmul($b -> bpow($y));
1746}
184f15d5 1747
6320cdc0 1748sub brsft {
7deec013 1749 my ($class, $x, $y, $b) = objectify(2, @_);
12fc2493 1750
6320cdc0
SH
1751 $b = 2 if !defined $b;
1752 $b = $class -> new($b) unless ref($b) && $b -> isa($class);
184f15d5 1753
6320cdc0 1754 return $x -> bnan() if $x -> is_nan() || $y -> is_nan() || $b -> is_nan();
7d341013 1755
6320cdc0
SH
1756 # shift by a negative amount?
1757 return $x -> blsft($y -> copy() -> babs(), $b) if $y -> {sign} =~ /^-/;
184f15d5 1758
6320cdc0
SH
1759 # the following call to bdiv() will return either quotient (scalar context)
1760 # or quotient and remainder (list context).
1761 $x -> bdiv($b -> bpow($y));
1762}
12fc2493 1763
6320cdc0
SH
1764sub band {
1765 my $x = shift;
1766 my $xref = ref($x);
1767 my $class = $xref || $x;
12fc2493 1768
3cc1ad36
SH
1769 croak 'band() is an instance method, not a class method' unless $xref;
1770 croak 'Not enough arguments for band()' if @_ < 1;
184f15d5 1771
6320cdc0
SH
1772 my $y = shift;
1773 $y = $class -> new($y) unless ref($y);
4de3d162 1774
6320cdc0 1775 my @r = @_;
a4e2b1c6 1776
6320cdc0
SH
1777 my $xtmp = Math::BigInt -> new($x -> bint()); # to Math::BigInt
1778 $xtmp -> band($y);
1779 $xtmp = $class -> new($xtmp); # back to Math::BigRat
12fc2493 1780
6320cdc0
SH
1781 $x -> {sign} = $xtmp -> {sign};
1782 $x -> {_n} = $xtmp -> {_n};
1783 $x -> {_d} = $xtmp -> {_d};
4de3d162 1784
6320cdc0
SH
1785 return $x -> round(@r);
1786}
4de3d162 1787
6320cdc0
SH
1788sub bior {
1789 my $x = shift;
1790 my $xref = ref($x);
1791 my $class = $xref || $x;
4de3d162 1792
3cc1ad36
SH
1793 croak 'bior() is an instance method, not a class method' unless $xref;
1794 croak 'Not enough arguments for bior()' if @_ < 1;
184f15d5 1795
6320cdc0
SH
1796 my $y = shift;
1797 $y = $class -> new($y) unless ref($y);
11c955be 1798
6320cdc0 1799 my @r = @_;
11c955be 1800
6320cdc0
SH
1801 my $xtmp = Math::BigInt -> new($x -> bint()); # to Math::BigInt
1802 $xtmp -> bior($y);
1803 $xtmp = $class -> new($xtmp); # back to Math::BigRat
7afd7a91 1804
6320cdc0
SH
1805 $x -> {sign} = $xtmp -> {sign};
1806 $x -> {_n} = $xtmp -> {_n};
1807 $x -> {_d} = $xtmp -> {_d};
7afd7a91 1808
6320cdc0
SH
1809 return $x -> round(@r);
1810}
116a1b2f 1811
6320cdc0
SH
1812sub bxor {
1813 my $x = shift;
1814 my $xref = ref($x);
1815 my $class = $xref || $x;
116a1b2f 1816
3cc1ad36
SH
1817 croak 'bxor() is an instance method, not a class method' unless $xref;
1818 croak 'Not enough arguments for bxor()' if @_ < 1;
116a1b2f 1819
6320cdc0
SH
1820 my $y = shift;
1821 $y = $class -> new($y) unless ref($y);
116a1b2f 1822
6320cdc0 1823 my @r = @_;
116a1b2f 1824
6320cdc0
SH
1825 my $xtmp = Math::BigInt -> new($x -> bint()); # to Math::BigInt
1826 $xtmp -> bxor($y);
1827 $xtmp = $class -> new($xtmp); # back to Math::BigRat
116a1b2f 1828
6320cdc0
SH
1829 $x -> {sign} = $xtmp -> {sign};
1830 $x -> {_n} = $xtmp -> {_n};
1831 $x -> {_d} = $xtmp -> {_d};
116a1b2f 1832
6320cdc0
SH
1833 return $x -> round(@r);
1834}
116a1b2f 1835
6320cdc0
SH
1836sub bnot {
1837 my $x = shift;
1838 my $xref = ref($x);
1839 my $class = $xref || $x;
116a1b2f 1840
3cc1ad36 1841 croak 'bnot() is an instance method, not a class method' unless $xref;
116a1b2f 1842
6320cdc0 1843 my @r = @_;
116a1b2f 1844
6320cdc0
SH
1845 my $xtmp = Math::BigInt -> new($x -> bint()); # to Math::BigInt
1846 $xtmp -> bnot();
1847 $xtmp = $class -> new($xtmp); # back to Math::BigRat
116a1b2f 1848
6320cdc0
SH
1849 $x -> {sign} = $xtmp -> {sign};
1850 $x -> {_n} = $xtmp -> {_n};
1851 $x -> {_d} = $xtmp -> {_d};
116a1b2f 1852
6320cdc0
SH
1853 return $x -> round(@r);
1854}
12fc2493 1855
6320cdc0
SH
1856##############################################################################
1857# round
12fc2493 1858
6320cdc0
SH
1859sub round {
1860 $_[0];
1861}
12fc2493 1862
6320cdc0
SH
1863sub bround {
1864 $_[0];
1865}
9b924220 1866
6320cdc0
SH
1867sub bfround {
1868 $_[0];
1869}
12fc2493 1870
6320cdc0
SH
1871##############################################################################
1872# comparing
7afd7a91 1873
6320cdc0
SH
1874sub bcmp {
1875 # compare two signed numbers
9b924220 1876
6320cdc0
SH
1877 # set up parameters
1878 my ($class, $x, $y) = (ref($_[0]), @_);
7afd7a91 1879
6320cdc0
SH
1880 # objectify is costly, so avoid it
1881 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
1882 ($class, $x, $y) = objectify(2, @_);
7afd7a91
T
1883 }
1884
6320cdc0
SH
1885 if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/) {
1886 # $x is NaN and/or $y is NaN
6853e8af 1887 return if $x->{sign} eq $nan || $y->{sign} eq $nan;
6320cdc0 1888 # $x and $y are both either +inf or -inf
6853e8af 1889 return 0 if $x->{sign} eq $y->{sign} && $x->{sign} =~ /^[+-]inf$/;
6320cdc0
SH
1890 # $x = +inf and $y < +inf
1891 return +1 if $x->{sign} eq '+inf';
1892 # $x = -inf and $y > -inf
1893 return -1 if $x->{sign} eq '-inf';
1894 # $x < +inf and $y = +inf
1895 return -1 if $y->{sign} eq '+inf';
1896 # $x > -inf and $y = -inf
1897 return +1;
7afd7a91
T
1898 }
1899
6320cdc0
SH
1900 # $x >= 0 and $y < 0
1901 return 1 if $x->{sign} eq '+' && $y->{sign} eq '-';
1902 # $x < 0 and $y >= 0
1903 return -1 if $x->{sign} eq '-' && $y->{sign} eq '+';
7afd7a91 1904
6320cdc0 1905 # At this point, we know that $x and $y have the same sign.
7afd7a91 1906
6320cdc0 1907 # shortcut
0c2fbbe3
CBW
1908 my $xz = $LIB->_is_zero($x->{_n});
1909 my $yz = $LIB->_is_zero($y->{_n});
6320cdc0
SH
1910 return 0 if $xz && $yz; # 0 <=> 0
1911 return -1 if $xz && $y->{sign} eq '+'; # 0 <=> +y
1912 return 1 if $yz && $x->{sign} eq '+'; # +x <=> 0
7afd7a91 1913
0c2fbbe3
CBW
1914 my $t = $LIB->_mul($LIB->_copy($x->{_n}), $y->{_d});
1915 my $u = $LIB->_mul($LIB->_copy($y->{_n}), $x->{_d});
7afd7a91 1916
0c2fbbe3 1917 my $cmp = $LIB->_acmp($t, $u); # signs are equal
6320cdc0
SH
1918 $cmp = -$cmp if $x->{sign} eq '-'; # both are '-' => reverse
1919 $cmp;
1920}
184f15d5 1921
6320cdc0
SH
1922sub bacmp {
1923 # compare two numbers (as unsigned)
990fb837 1924
6320cdc0
SH
1925 # set up parameters
1926 my ($class, $x, $y) = (ref($_[0]), @_);
1927 # objectify is costly, so avoid it
1928 if ((!ref($_[0])) || (ref($_[0]) ne ref($_[1]))) {
1929 ($class, $x, $y) = objectify(2, @_);
1930 }
990fb837 1931
6320cdc0
SH
1932 if (($x->{sign} !~ /^[+-]$/) || ($y->{sign} !~ /^[+-]$/)) {
1933 # handle +-inf and NaN
6853e8af
RL
1934 return if (($x->{sign} eq $nan) || ($y->{sign} eq $nan));
1935 return 0 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} =~ /^[+-]inf$/;
1936 return 1 if $x->{sign} =~ /^[+-]inf$/ && $y->{sign} !~ /^[+-]inf$/;
6320cdc0
SH
1937 return -1;
1938 }
9b924220 1939
0c2fbbe3
CBW
1940 my $t = $LIB->_mul($LIB->_copy($x->{_n}), $y->{_d});
1941 my $u = $LIB->_mul($LIB->_copy($y->{_n}), $x->{_d});
1942 $LIB->_acmp($t, $u); # ignore signs
6320cdc0 1943}
12fc2493 1944
6320cdc0
SH
1945sub beq {
1946 my $self = shift;
1947 my $selfref = ref $self;
7deec013 1948 #my $class = $selfref || $self;
184f15d5 1949
3cc1ad36
SH
1950 croak 'beq() is an instance method, not a class method' unless $selfref;
1951 croak 'Wrong number of arguments for beq()' unless @_ == 1;
12fc2493 1952
6320cdc0
SH
1953 my $cmp = $self -> bcmp(shift);
1954 return defined($cmp) && ! $cmp;
1955}
12fc2493 1956
6320cdc0
SH
1957sub bne {
1958 my $self = shift;
1959 my $selfref = ref $self;
7deec013 1960 #my $class = $selfref || $self;
184f15d5 1961
3cc1ad36
SH
1962 croak 'bne() is an instance method, not a class method' unless $selfref;
1963 croak 'Wrong number of arguments for bne()' unless @_ == 1;
ccbfef19 1964
6320cdc0
SH
1965 my $cmp = $self -> bcmp(shift);
1966 return defined($cmp) && ! $cmp ? '' : 1;
1967}
184f15d5 1968
6320cdc0
SH
1969sub blt {
1970 my $self = shift;
1971 my $selfref = ref $self;
7deec013 1972 #my $class = $selfref || $self;
184f15d5 1973
3cc1ad36
SH
1974 croak 'blt() is an instance method, not a class method' unless $selfref;
1975 croak 'Wrong number of arguments for blt()' unless @_ == 1;
184f15d5 1976
6320cdc0
SH
1977 my $cmp = $self -> bcmp(shift);
1978 return defined($cmp) && $cmp < 0;
1979}
184f15d5 1980
6320cdc0
SH
1981sub ble {
1982 my $self = shift;
1983 my $selfref = ref $self;
7deec013 1984 #my $class = $selfref || $self;
184f15d5 1985
3cc1ad36
SH
1986 croak 'ble() is an instance method, not a class method' unless $selfref;
1987 croak 'Wrong number of arguments for ble()' unless @_ == 1;
184f15d5 1988
6320cdc0
SH
1989 my $cmp = $self -> bcmp(shift);
1990 return defined($cmp) && $cmp <= 0;
1991}
184f15d5 1992
6320cdc0
SH
1993sub bgt {
1994 my $self = shift;
1995 my $selfref = ref $self;
7deec013 1996 #my $class = $selfref || $self;
184f15d5 1997
3cc1ad36
SH
1998 croak 'bgt() is an instance method, not a class method' unless $selfref;
1999 croak 'Wrong number of arguments for bgt()' unless @_ == 1;
ccbfef19 2000
6320cdc0
SH
2001 my $cmp = $self -> bcmp(shift);
2002 return defined($cmp) && $cmp > 0;
2003}
184f15d5 2004
6320cdc0
SH
2005sub bge {
2006 my $self = shift;
2007 my $selfref = ref $self;
7deec013 2008 #my $class = $selfref || $self;
184f15d5 2009
3cc1ad36 2010 croak 'bge() is an instance method, not a class method'
6320cdc0 2011 unless $selfref;
3cc1ad36 2012 croak 'Wrong number of arguments for bge()' unless @_ == 1;
184f15d5 2013
6320cdc0
SH
2014 my $cmp = $self -> bcmp(shift);
2015 return defined($cmp) && $cmp >= 0;
2016}
184f15d5
JH
2017
2018##############################################################################
6320cdc0 2019# output conversion
184f15d5 2020
6320cdc0
SH
2021sub numify {
2022 # convert 17/8 => float (aka 2.125)
2023 my ($self, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
ccbfef19 2024
6320cdc0 2025 # Non-finite number.
7d341013 2026
6853e8af
RL
2027 if ($x -> is_nan()) {
2028 require Math::Complex;
2029 my $inf = $Math::Complex::Inf;
2030 return $inf - $inf;
2031 }
2032
2033 if ($x -> is_inf()) {
2034 require Math::Complex;
2035 my $inf = $Math::Complex::Inf;
2036 return $x -> is_negative() ? -$inf : $inf;
2037 }
93c87d9d 2038
6320cdc0 2039 # Finite number.
7d341013 2040
0c2fbbe3
CBW
2041 my $abs = $LIB->_is_one($x->{_d})
2042 ? $LIB->_num($x->{_n})
2043 : Math::BigFloat -> new($LIB->_str($x->{_n}))
2044 -> bdiv($LIB->_str($x->{_d}))
6320cdc0
SH
2045 -> bstr();
2046 return $x->{sign} eq '-' ? 0 - $abs : 0 + $abs;
2047}
2048
3cc1ad36 2049sub as_int {
6320cdc0 2050 my ($self, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
184f15d5 2051
6320cdc0
SH
2052 # NaN, inf etc
2053 return Math::BigInt->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
2054
2055 my $u = Math::BigInt->bzero();
0c2fbbe3 2056 $u->{value} = $LIB->_div($LIB->_copy($x->{_n}), $x->{_d}); # 22/7 => 3
6320cdc0
SH
2057 $u->bneg if $x->{sign} eq '-'; # no negative zero
2058 $u;
2059}
ccbfef19 2060
6320cdc0
SH
2061sub as_float {
2062 # return N/D as Math::BigFloat
184f15d5 2063
6320cdc0
SH
2064 # set up parameters
2065 my ($class, $x, @r) = (ref($_[0]), @_);
2066 # objectify is costly, so avoid it
2067 ($class, $x, @r) = objectify(1, @_) unless ref $_[0];
4de3d162 2068
6320cdc0
SH
2069 # NaN, inf etc
2070 return Math::BigFloat->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
4de3d162 2071
0c2fbbe3
CBW
2072 my $xd = Math::BigFloat -> new($LIB -> _str($x->{_d}));
2073 my $xflt = Math::BigFloat -> new($LIB -> _str($x->{_n}));
6320cdc0
SH
2074 $xflt -> {sign} = $x -> {sign};
2075 $xflt -> bdiv($xd, @r);
ccbfef19 2076
6320cdc0
SH
2077 return $xflt;
2078}
4de3d162 2079
6320cdc0
SH
2080sub as_bin {
2081 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
9b924220 2082
6320cdc0 2083 return $x unless $x->is_int();
9b924220 2084
6320cdc0
SH
2085 my $s = $x->{sign};
2086 $s = '' if $s eq '+';
0c2fbbe3 2087 $s . $LIB->_as_bin($x->{_n});
6320cdc0 2088}
9b924220 2089
6320cdc0
SH
2090sub as_hex {
2091 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
9b924220 2092
6320cdc0 2093 return $x unless $x->is_int();
9b924220 2094
6320cdc0 2095 my $s = $x->{sign}; $s = '' if $s eq '+';
0c2fbbe3 2096 $s . $LIB->_as_hex($x->{_n});
6320cdc0 2097}
9b924220 2098
6320cdc0
SH
2099sub as_oct {
2100 my ($class, $x) = ref($_[0]) ? (undef, $_[0]) : objectify(1, @_);
b8884ce4 2101
6320cdc0 2102 return $x unless $x->is_int();
b8884ce4 2103
6320cdc0 2104 my $s = $x->{sign}; $s = '' if $s eq '+';
0c2fbbe3 2105 $s . $LIB->_as_oct($x->{_n});
6320cdc0 2106}
b8884ce4
T
2107
2108##############################################################################
2109
6320cdc0
SH
2110sub from_hex {
2111 my $class = shift;
b8884ce4 2112
6853e8af
RL
2113 # The relationship should probably go the otherway, i.e, that new() calls
2114 # from_hex(). Fixme!
2115 my ($x, @r) = @_;
2116 $x =~ s|^\s*(?:0?[Xx]_*)?|0x|;
2117 $class->new($x, @r);
6320cdc0 2118}
b8884ce4 2119
6320cdc0
SH
2120sub from_bin {
2121 my $class = shift;
b8884ce4 2122
6853e8af
RL
2123 # The relationship should probably go the otherway, i.e, that new() calls
2124 # from_bin(). Fixme!
2125 my ($x, @r) = @_;
2126 $x =~ s|^\s*(?:0?[Bb]_*)?|0b|;
2127 $class->new($x, @r);
6320cdc0 2128}
b8884ce4 2129
6320cdc0
SH
2130sub from_oct {
2131 my $class = shift;
b8884ce4 2132
6853e8af 2133 # Why is this different from from_hex() and from_bin()? Fixme!
6320cdc0
SH
2134 my @parts;
2135 for my $c (@_) {
2136 push @parts, Math::BigInt->from_oct($c);
b8884ce4 2137 }
6320cdc0
SH
2138 $class->new (@parts);
2139}
b8884ce4 2140
b68b7ab1
T
2141##############################################################################
2142# import
2143
6320cdc0
SH
2144sub import {
2145 my $class = shift;
6853e8af
RL
2146 my @a; # unrecognized arguments
2147 my $lib_param = '';
2148 my $lib_value = '';
2149
2150 while (@_) {
2151 my $param = shift;
2152
2153 # Enable overloading of constants.
2154
2155 if ($param eq ':constant') {
2156 overload::constant
2157
2158 integer => sub {
2159 $class -> new(shift);
2160 },
9b924220 2161
6853e8af
RL
2162 float => sub {
2163 $class -> new(shift);
2164 },
7deec013 2165
6853e8af
RL
2166 binary => sub {
2167 # E.g., a literal 0377 shall result in an object whose value
2168 # is decimal 255, but new("0377") returns decimal 377.
2169 return $class -> from_oct($_[0]) if $_[0] =~ /^0_*[0-7]/;
2170 $class -> new(shift);
2171 };
2172 next;
6320cdc0 2173 }
7deec013 2174
6853e8af 2175 # Upgrading.
7deec013 2176
6853e8af
RL
2177 if ($param eq 'upgrade') {
2178 $class -> upgrade(shift);
2179 next;
7deec013
NB
2180 }
2181
6853e8af
RL
2182 # Downgrading.
2183
2184 if ($param eq 'downgrade') {
2185 $class -> downgrade(shift);
2186 next;
7deec013
NB
2187 }
2188
6853e8af
RL
2189 # Accuracy.
2190
2191 if ($param eq 'accuracy') {
2192 $class -> accuracy(shift);
2193 next;
2194 }
2195
2196 # Precision.
2197
2198 if ($param eq 'precision') {
2199 $class -> precision(shift);
2200 next;
2201 }
2202
2203 # Rounding mode.
2204
2205 if ($param eq 'round_mode') {
2206 $class -> round_mode(shift);
2207 next;
6320cdc0 2208 }
6de7f0cc 2209
6853e8af
RL
2210 # Backend library.
2211
2212 if ($param =~ /^(lib|try|only)\z/) {
2213 # alternative library
2214 $lib_param = $param; # "lib", "try", or "only"
2215 $lib_value = shift;
2216 next;
6320cdc0 2217 }
6853e8af
RL
2218
2219 if ($param eq 'with') {
2220 # alternative class for our private parts()
2221 # XXX: no longer supported
2222 # $LIB = shift() || 'Calc';
2223 # carp "'with' is no longer supported, use 'lib', 'try', or 'only'";
2224 shift;
2225 next;
2226 }
2227
2228 # Unrecognized parameter.
2229
2230 push @a, $param;
93c87d9d 2231 }
233f7bc0 2232
7deec013 2233 require Math::BigInt;
6de7f0cc 2234
7deec013 2235 my @import = ('objectify');
6853e8af 2236 push @import, $lib_param, $lib_value if $lib_param ne '';
7deec013 2237 Math::BigInt -> import(@import);
b68b7ab1 2238
7deec013
NB
2239 # find out which one was actually loaded
2240 $LIB = Math::BigInt -> config("lib");
ccbfef19 2241
3cc1ad36
SH
2242 # any non :constant stuff is handled by Exporter (loaded by parent class)
2243 # even if @_ is empty, to give it a chance
6320cdc0
SH
2244 $class->SUPER::import(@a); # for subclasses
2245 $class->export_to_level(1, $class, @a); # need this, too
2246}
184f15d5
JH
2247
22481;
2249
2250__END__
2251
a7752796
PJA
2252=pod
2253
184f15d5
JH
2254=head1 NAME
2255
b68b7ab1 2256Math::BigRat - Arbitrary big rational numbers
184f15d5
JH
2257
2258=head1 SYNOPSIS
2259
6320cdc0 2260 use Math::BigRat;
184f15d5 2261
6320cdc0 2262 my $x = Math::BigRat->new('3/7'); $x += '5/9';
184f15d5 2263
6320cdc0
SH
2264 print $x->bstr(), "\n";
2265 print $x ** 2, "\n";
184f15d5 2266
6320cdc0
SH
2267 my $y = Math::BigRat->new('inf');
2268 print "$y ", ($y->is_inf ? 'is' : 'is not'), " infinity\n";
7afd7a91 2269
6320cdc0 2270 my $z = Math::BigRat->new(144); $z->bsqrt();
7afd7a91 2271
184f15d5
JH
2272=head1 DESCRIPTION
2273
7d341013 2274Math::BigRat complements Math::BigInt and Math::BigFloat by providing support
b68b7ab1 2275for arbitrary big rational numbers.
184f15d5
JH
2276
2277=head2 MATH LIBRARY
2278
b8884ce4
T
2279You can change the underlying module that does the low-level
2280math operations by using:
184f15d5 2281
6320cdc0 2282 use Math::BigRat try => 'GMP';
184f15d5 2283
b8884ce4 2284Note: This needs Math::BigInt::GMP installed.
184f15d5
JH
2285
2286The following would first try to find Math::BigInt::Foo, then
2287Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc:
2288
6320cdc0 2289 use Math::BigRat try => 'Foo,Math::BigInt::Bar';
184f15d5 2290
6320cdc0 2291If you want to get warned when the fallback occurs, replace "try" with "lib":
184f15d5 2292
6320cdc0 2293 use Math::BigRat lib => 'Foo,Math::BigInt::Bar';
7d341013 2294
6320cdc0 2295If you want the code to die instead, replace "try" with "only":
b8884ce4 2296
6320cdc0 2297 use Math::BigRat only => 'Foo,Math::BigInt::Bar';
7d341013 2298
184f15d5
JH
2299=head1 METHODS
2300
3c4b39be 2301Any methods not listed here are derived from Math::BigFloat (or
6de7f0cc
JH
2302Math::BigInt), so make sure you check these two modules for further
2303information.
2304
6320cdc0
SH
2305=over
2306
2307=item new()
184f15d5 2308
6320cdc0 2309 $x = Math::BigRat->new('1/3');
184f15d5
JH
2310
2311Create a new Math::BigRat object. Input can come in various forms:
2312
6320cdc0
SH
2313 $x = Math::BigRat->new(123); # scalars
2314 $x = Math::BigRat->new('inf'); # infinity
2315 $x = Math::BigRat->new('123.3'); # float
2316 $x = Math::BigRat->new('1/3'); # simple string
2317 $x = Math::BigRat->new('1 / 3'); # spaced
2318 $x = Math::BigRat->new('1 / 0.1'); # w/ floats
2319 $x = Math::BigRat->new(Math::BigInt->new(3)); # BigInt
2320 $x = Math::BigRat->new(Math::BigFloat->new('3.1')); # BigFloat
2321 $x = Math::BigRat->new(Math::BigInt::Lite->new('2')); # BigLite
184f15d5 2322
6320cdc0
SH
2323 # You can also give D and N as different objects:
2324 $x = Math::BigRat->new(
2325 Math::BigInt->new(-123),
2326 Math::BigInt->new(7),
2327 ); # => -123/7
b68b7ab1 2328
6320cdc0 2329=item numerator()
184f15d5 2330
6320cdc0 2331 $n = $x->numerator();
184f15d5
JH
2332
2333Returns a copy of the numerator (the part above the line) as signed BigInt.
2334
6320cdc0 2335=item denominator()
ccbfef19 2336
6320cdc0 2337 $d = $x->denominator();
184f15d5
JH
2338
2339Returns a copy of the denominator (the part under the line) as positive BigInt.
2340
6320cdc0 2341=item parts()
184f15d5 2342
6320cdc0 2343 ($n, $d) = $x->parts();
184f15d5
JH
2344
2345Return a list consisting of (signed) numerator and (unsigned) denominator as
2346BigInts.
2347
6853e8af
RL
2348=item dparts()
2349
2350Returns the integer part and the fraction part.
2351
6320cdc0 2352=item numify()
b8884ce4 2353
6320cdc0 2354 my $y = $x->numify();
b8884ce4
T
2355
2356Returns the object as a scalar. This will lose some data if the object
2357cannot be represented by a normal Perl scalar (integer or float), so
3cc1ad36 2358use L</as_int()> or L</as_float()> instead.
b8884ce4
T
2359
2360This routine is automatically used whenever a scalar is required:
2361
6320cdc0
SH
2362 my $x = Math::BigRat->new('3/1');
2363 @array = (0, 1, 2, 3);
2364 $y = $array[$x]; # set $y to 3
b8884ce4 2365
3cc1ad36
SH
2366=item as_int()
2367
2368=item as_number()
6de7f0cc 2369
6320cdc0
SH
2370 $x = Math::BigRat->new('13/7');
2371 print $x->as_int(), "\n"; # '1'
b68b7ab1
T
2372
2373Returns a copy of the object as BigInt, truncated to an integer.
7d341013 2374
b68b7ab1
T
2375C<as_number()> is an alias for C<as_int()>.
2376
6320cdc0 2377=item as_float()
4de3d162 2378
6320cdc0
SH
2379 $x = Math::BigRat->new('13/7');
2380 print $x->as_float(), "\n"; # '1'
4de3d162 2381
6320cdc0
SH
2382 $x = Math::BigRat->new('2/3');
2383 print $x->as_float(5), "\n"; # '0.66667'
4de3d162
T
2384
2385Returns a copy of the object as BigFloat, preserving the
2386accuracy as wanted, or the default of 40 digits.
2387
2388This method was added in v0.22 of Math::BigRat (April 2008).
2389
6320cdc0 2390=item as_hex()
b68b7ab1 2391
6320cdc0
SH
2392 $x = Math::BigRat->new('13');
2393 print $x->as_hex(), "\n"; # '0xd'
b68b7ab1 2394
ccbfef19 2395Returns the BigRat as hexadecimal string. Works only for integers.
b68b7ab1 2396
6320cdc0 2397=item as_bin()
b68b7ab1 2398
6320cdc0
SH
2399 $x = Math::BigRat->new('13');
2400 print $x->as_bin(), "\n"; # '0x1101'
b68b7ab1 2401
ccbfef19 2402Returns the BigRat as binary string. Works only for integers.
6de7f0cc 2403
6320cdc0 2404=item as_oct()
b8884ce4 2405
6320cdc0
SH
2406 $x = Math::BigRat->new('13');
2407 print $x->as_oct(), "\n"; # '015'
b8884ce4 2408
ccbfef19 2409Returns the BigRat as octal string. Works only for integers.
b8884ce4 2410
6320cdc0
SH
2411=item from_hex()
2412
2413 my $h = Math::BigRat->from_hex('0x10');
2414
2415Create a BigRat from a hexadecimal number in string form.
2416
2417=item from_oct()
2418
2419 my $o = Math::BigRat->from_oct('020');
2420
2421Create a BigRat from an octal number in string form.
2422
2423=item from_bin()
2424
2425 my $b = Math::BigRat->from_bin('0b10000000');
2426
2427Create a BigRat from an binary number in string form.
2428
2429=item bnan()
2430
2431 $x = Math::BigRat->bnan();
2432
2433Creates a new BigRat object representing NaN (Not A Number).
2434If used on an object, it will set it to NaN:
2435
2436 $x->bnan();
b8884ce4 2437
6320cdc0 2438=item bzero()
b8884ce4 2439
6320cdc0 2440 $x = Math::BigRat->bzero();
b8884ce4 2441
6320cdc0
SH
2442Creates a new BigRat object representing zero.
2443If used on an object, it will set it to zero:
b8884ce4 2444
6320cdc0
SH
2445 $x->bzero();
2446
2447=item binf()
2448
2449 $x = Math::BigRat->binf($sign);
2450
2451Creates a new BigRat object representing infinity. The optional argument is
2452either '-' or '+', indicating whether you want infinity or minus infinity.
2453If used on an object, it will set it to infinity:
2454
2455 $x->binf();
2456 $x->binf('-');
2457
2458=item bone()
2459
2460 $x = Math::BigRat->bone($sign);
2461
2462Creates a new BigRat object representing one. The optional argument is
2463either '-' or '+', indicating whether you want one or minus one.
2464If used on an object, it will set it to one:
2465
2466 $x->bone(); # +1
2467 $x->bone('-'); # -1
2468
2469=item length()
2470
2471 $len = $x->length();
b8884ce4 2472
c4a6f826 2473Return the length of $x in digits for integer values.
b8884ce4 2474
6320cdc0 2475=item digit()
b8884ce4 2476
6320cdc0
SH
2477 print Math::BigRat->new('123/1')->digit(1); # 1
2478 print Math::BigRat->new('123/1')->digit(-1); # 3
b8884ce4
T
2479
2480Return the N'ths digit from X when X is an integer value.
2481
6320cdc0 2482=item bnorm()
b8884ce4 2483
6320cdc0 2484 $x->bnorm();
b8884ce4
T
2485
2486Reduce the number to the shortest form. This routine is called
2487automatically whenever it is needed.
2488
6320cdc0 2489=item bfac()
6de7f0cc 2490
6320cdc0 2491 $x->bfac();
6de7f0cc 2492
a4e2b1c6 2493Calculates the factorial of $x. For instance:
6de7f0cc 2494
6320cdc0
SH
2495 print Math::BigRat->new('3/1')->bfac(), "\n"; # 1*2*3
2496 print Math::BigRat->new('5/1')->bfac(), "\n"; # 1*2*3*4*5
184f15d5 2497
7d341013 2498Works currently only for integers.
6de7f0cc 2499
6320cdc0 2500=item bround()/round()/bfround()
6de7f0cc 2501
a4e2b1c6 2502Are not yet implemented.
6de7f0cc 2503
6320cdc0 2504=item bmod()
990fb837 2505
6320cdc0 2506 $x->bmod($y);
990fb837 2507
3f185657
PJA
2508Returns $x modulo $y. When $x is finite, and $y is finite and non-zero, the
2509result is identical to the remainder after floored division (F-division). If,
2510in addition, both $x and $y are integers, the result is identical to the result
2511from Perl's % operator.
990fb837 2512
6320cdc0
SH
2513=item bmodinv()
2514
2515 $x->bmodinv($mod); # modular multiplicative inverse
2516
2517Returns the multiplicative inverse of C<$x> modulo C<$mod>. If
2518
2519 $y = $x -> copy() -> bmodinv($mod)
2520
2521then C<$y> is the number closest to zero, and with the same sign as C<$mod>,
2522satisfying
2523
2524 ($x * $y) % $mod = 1 % $mod
2525
2526If C<$x> and C<$y> are non-zero, they must be relative primes, i.e.,
2527C<bgcd($y, $mod)==1>. 'C<NaN>' is returned when no modular multiplicative
2528inverse exists.
b8884ce4 2529
6320cdc0
SH
2530=item bmodpow()
2531
2532 $num->bmodpow($exp,$mod); # modular exponentiation
2533 # ($num**$exp % $mod)
2534
2535Returns the value of C<$num> taken to the power C<$exp> in the modulus
2536C<$mod> using binary exponentiation. C<bmodpow> is far superior to
2537writing
2538
2539 $num ** $exp % $mod
2540
2541because it is much faster - it reduces internal variables into
2542the modulus whenever possible, so it operates on smaller numbers.
2543
2544C<bmodpow> also supports negative exponents.
2545
2546 bmodpow($num, -1, $mod)
2547
2548is exactly equivalent to
2549
2550 bmodinv($num, $mod)
2551
2552=item bneg()
2553
2554 $x->bneg();
b8884ce4
T
2555
2556Used to negate the object in-place.
2557
6320cdc0 2558=item is_one()
7d341013 2559
6320cdc0 2560 print "$x is 1\n" if $x->is_one();
7d341013
T
2561
2562Return true if $x is exactly one, otherwise false.
2563
6320cdc0 2564=item is_zero()
7d341013 2565
6320cdc0 2566 print "$x is 0\n" if $x->is_zero();
7d341013
T
2567
2568Return true if $x is exactly zero, otherwise false.
2569
6320cdc0 2570=item is_pos()/is_positive()
7d341013 2571
6320cdc0 2572 print "$x is >= 0\n" if $x->is_positive();
7d341013
T
2573
2574Return true if $x is positive (greater than or equal to zero), otherwise
2575false. Please note that '+inf' is also positive, while 'NaN' and '-inf' aren't.
2576
b68b7ab1
T
2577C<is_positive()> is an alias for C<is_pos()>.
2578
6320cdc0 2579=item is_neg()/is_negative()
7d341013 2580
6320cdc0 2581 print "$x is < 0\n" if $x->is_negative();
7d341013
T
2582
2583Return true if $x is negative (smaller than zero), otherwise false. Please
2584note that '-inf' is also negative, while 'NaN' and '+inf' aren't.
2585
b68b7ab1
T
2586C<is_negative()> is an alias for C<is_neg()>.
2587
6320cdc0 2588=item is_int()
7d341013 2589
6320cdc0 2590 print "$x is an integer\n" if $x->is_int();
7d341013
T
2591
2592Return true if $x has a denominator of 1 (e.g. no fraction parts), otherwise
2593false. Please note that '-inf', 'inf' and 'NaN' aren't integer.
2594
6320cdc0 2595=item is_odd()
7d341013 2596
6320cdc0 2597 print "$x is odd\n" if $x->is_odd();
7d341013
T
2598
2599Return true if $x is odd, otherwise false.
2600
6320cdc0 2601=item is_even()
7d341013 2602
6320cdc0 2603 print "$x is even\n" if $x->is_even();
7d341013
T
2604
2605Return true if $x is even, otherwise false.
2606
6320cdc0 2607=item bceil()
7d341013 2608
6320cdc0 2609 $x->bceil();
7d341013
T
2610
2611Set $x to the next bigger integer value (e.g. truncate the number to integer
2612and then increment it by one).
2613
6320cdc0 2614=item bfloor()
ccbfef19 2615
6320cdc0 2616 $x->bfloor();
7d341013
T
2617
2618Truncate $x to an integer value.
6de7f0cc 2619
6320cdc0
SH
2620=item bint()
2621
2622 $x->bint();
2623
2624Round $x towards zero.
ccbfef19 2625
6320cdc0
SH
2626=item bsqrt()
2627
2628 $x->bsqrt();
7afd7a91
T
2629
2630Calculate the square root of $x.
2631
6320cdc0 2632=item broot()
ccbfef19 2633
6320cdc0 2634 $x->broot($n);
b8884ce4
T
2635
2636Calculate the N'th root of $x.
2637
6320cdc0 2638=item badd()
3f185657 2639
6320cdc0 2640 $x->badd($y);
3f185657
PJA
2641
2642Adds $y to $x and returns the result.
2643
6320cdc0 2644=item bmul()
3f185657 2645
6320cdc0 2646 $x->bmul($y);
3f185657
PJA
2647
2648Multiplies $y to $x and returns the result.
2649
6320cdc0 2650=item bsub()
3f185657 2651
6320cdc0 2652 $x->bsub($y);
3f185657
PJA
2653
2654Subtracts $y from $x and returns the result.
2655
6320cdc0 2656=item bdiv()
3f185657 2657
6320cdc0
SH
2658 $q = $x->bdiv($y);
2659 ($q, $r) = $x->bdiv($y);
3f185657
PJA
2660
2661In scalar context, divides $x by $y and returns the result. In list context,
2662does floored division (F-division), returning an integer $q and a remainder $r
2663so that $x = $q * $y + $r. The remainer (modulo) is equal to what is returned
7deec013 2664by C<< $x->bmod($y) >>.
3f185657 2665
6853e8af
RL
2666=item binv()
2667
2668 $x->binv();
2669
2670Inverse of $x.
2671
6320cdc0 2672=item bdec()
3f185657 2673
6320cdc0 2674 $x->bdec();
3f185657
PJA
2675
2676Decrements $x by 1 and returns the result.
2677
6320cdc0 2678=item binc()
3f185657 2679
6320cdc0 2680 $x->binc();
b8884ce4 2681
3f185657 2682Increments $x by 1 and returns the result.
b8884ce4 2683
6320cdc0 2684=item copy()
b8884ce4 2685
6320cdc0 2686 my $z = $x->copy();
b8884ce4
T
2687
2688Makes a deep copy of the object.
2689
2690Please see the documentation in L<Math::BigInt> for further details.
2691
6320cdc0 2692=item bstr()/bsstr()
b8884ce4 2693
6320cdc0
SH
2694 my $x = Math::BigRat->new('8/4');
2695 print $x->bstr(), "\n"; # prints 1/2
2696 print $x->bsstr(), "\n"; # prints 1/2
b8884ce4 2697
c4a6f826 2698Return a string representing this object.
b8884ce4 2699
6320cdc0 2700=item bcmp()
b8884ce4 2701
6320cdc0 2702 $x->bcmp($y);
b8884ce4 2703
6320cdc0
SH
2704Compares $x with $y and takes the sign into account.
2705Returns -1, 0, 1 or undef.
2706
2707=item bacmp()
2708
2709 $x->bacmp($y);
b8884ce4 2710
6320cdc0
SH
2711Compares $x with $y while ignoring their sign. Returns -1, 0, 1 or undef.
2712
2713=item beq()
2714
2715 $x -> beq($y);
2716
2717Returns true if and only if $x is equal to $y, and false otherwise.
2718
2719=item bne()
2720
2721 $x -> bne($y);
2722
2723Returns true if and only if $x is not equal to $y, and false otherwise.
2724
2725=item blt()
2726
2727 $x -> blt($y);
2728
2729Returns true if and only if $x is equal to $y, and false otherwise.
2730
2731=item ble()
2732
2733 $x -> ble($y);
2734
2735Returns true if and only if $x is less than or equal to $y, and false
2736otherwise.
2737
2738=item bgt()
2739
2740 $x -> bgt($y);
2741
2742Returns true if and only if $x is greater than $y, and false otherwise.
2743
2744=item bge()
2745
2746 $x -> bge($y);
2747
2748Returns true if and only if $x is greater than or equal to $y, and false
2749otherwise.
2750
2751=item blsft()/brsft()
b8884ce4
T
2752
2753Used to shift numbers left/right.
2754
2755Please see the documentation in L<Math::BigInt> for further details.
2756
6320cdc0
SH
2757=item band()
2758
2759 $x->band($y); # bitwise and
2760
2761=item bior()
2762
2763 $x->bior($y); # bitwise inclusive or
2764
2765=item bxor()
2766
2767 $x->bxor($y); # bitwise exclusive or
b8884ce4 2768
6320cdc0
SH
2769=item bnot()
2770
2771 $x->bnot(); # bitwise not (two's complement)
2772
2773=item bpow()
2774
2775 $x->bpow($y);
b8884ce4
T
2776
2777Compute $x ** $y.
2778
2779Please see the documentation in L<Math::BigInt> for further details.
2780
6320cdc0
SH
2781=item blog()
2782
2783 $x->blog($base, $accuracy); # logarithm of x to the base $base
116a1b2f 2784
6320cdc0
SH
2785If C<$base> is not defined, Euler's number (e) is used:
2786
2787 print $x->blog(undef, 100); # log(x) to 100 digits
2788
2789=item bexp()
2790
2791 $x->bexp($accuracy); # calculate e ** X
116a1b2f
SP
2792
2793Calculates two integers A and B so that A/B is equal to C<e ** $x>, where C<e> is
2794Euler's number.
2795
2796This method was added in v0.20 of Math::BigRat (May 2007).
2797
3d6c5fec 2798See also C<blog()>.
116a1b2f 2799
6320cdc0 2800=item bnok()
116a1b2f 2801
6320cdc0 2802 $x->bnok($y); # x over y (binomial coefficient n over k)
116a1b2f
SP
2803
2804Calculates the binomial coefficient n over k, also called the "choose"
2805function. The result is equivalent to:
2806
6320cdc0
SH
2807 ( n ) n!
2808 | - | = -------
2809 ( k ) k!(n-k)!
116a1b2f
SP
2810
2811This method was added in v0.20 of Math::BigRat (May 2007).
2812
6320cdc0 2813=item config()
990fb837 2814
3cc1ad36
SH
2815 Math::BigRat->config("trap_nan" => 1); # set
2816 $accu = Math::BigRat->config("accuracy"); # get
990fb837 2817
3cc1ad36
SH
2818Set or get configuration parameter values. Read-only parameters are marked as
2819RO. Read-write parameters are marked as RW. The following parameters are
2820supported.
990fb837 2821
3cc1ad36 2822 Parameter RO/RW Description
6320cdc0
SH
2823 Example
2824 ============================================================
3cc1ad36 2825 lib RO Name of the math backend library
6320cdc0 2826 Math::BigInt::Calc
3cc1ad36 2827 lib_version RO Version of the math backend library
6320cdc0
SH
2828 0.30
2829 class RO The class of config you just called
2830 Math::BigRat
2831 version RO version number of the class you used
2832 0.10
2833 upgrade RW To which class numbers are upgraded
2834 undef
2835 downgrade RW To which class numbers are downgraded
2836 undef
2837 precision RW Global precision
2838 undef
2839 accuracy RW Global accuracy
2840 undef
2841 round_mode RW Global round mode
2842 even
3cc1ad36 2843 div_scale RW Fallback accuracy for div, sqrt etc.
6320cdc0 2844 40
3cc1ad36 2845 trap_nan RW Trap NaNs
6320cdc0 2846 undef
3cc1ad36 2847 trap_inf RW Trap +inf/-inf
6320cdc0 2848 undef
990fb837 2849
6320cdc0 2850=back
4de3d162 2851
6853e8af
RL
2852=head1 NUMERIC LITERALS
2853
2854After C<use Math::BigRat ':constant'> all numeric literals in the given scope
2855are converted to C<Math::BigRat> objects. This conversion happens at compile
2856time. Every non-integer is convert to a NaN.
2857
2858For example,
2859
2860 perl -MMath::BigRat=:constant -le 'print 2**150'
2861
2862prints the exact value of C<2**150>. Note that without conversion of constants
2863to objects the expression C<2**150> is calculated using Perl scalars, which
2864leads to an inaccurate result.
2865
2866Please note that strings are not affected, so that
2867
2868 use Math::BigRat qw/:constant/;
2869
2870 $x = "1234567890123456789012345678901234567890"
2871 + "123456789123456789";
2872
2873does give you what you expect. You need an explicit Math::BigRat->new() around
2874at least one of the operands. You should also quote large constants to prevent
2875loss of precision:
2876
2877 use Math::BigRat;
2878
2879 $x = Math::BigRat->new("1234567889123456789123456789123456789");
2880
2881Without the quotes Perl first converts the large number to a floating point
2882constant at compile time, and then converts the result to a Math::BigRat object
2883at run time, which results in an inaccurate result.
2884
2885=head2 Hexadecimal, octal, and binary floating point literals
2886
2887Perl (and this module) accepts hexadecimal, octal, and binary floating point
2888literals, but use them with care with Perl versions before v5.32.0, because some
2889versions of Perl silently give the wrong result. Below are some examples of
2890different ways to write the number decimal 314.
2891
2892Hexadecimal floating point literals:
2893
2894 0x1.3ap+8 0X1.3AP+8
2895 0x1.3ap8 0X1.3AP8
2896 0x13a0p-4 0X13A0P-4
2897
2898Octal floating point literals (with "0" prefix):
2899
2900 01.164p+8 01.164P+8
2901 01.164p8 01.164P8
2902 011640p-4 011640P-4
2903
2904Octal floating point literals (with "0o" prefix) (requires v5.34.0):
2905
2906 0o1.164p+8 0O1.164P+8
2907 0o1.164p8 0O1.164P8
2908 0o11640p-4 0O11640P-4
2909
2910Binary floating point literals:
2911
2912 0b1.0011101p+8 0B1.0011101P+8
2913 0b1.0011101p8 0B1.0011101P8
2914 0b10011101000p-2 0B10011101000P-2
2915
a4e2b1c6 2916=head1 BUGS
6de7f0cc 2917
a7752796
PJA
2918Please report any bugs or feature requests to
2919C<bug-math-bigrat at rt.cpan.org>, or through the web interface at
2920L<https://rt.cpan.org/Ticket/Create.html?Queue=Math-BigRat>
2921(requires login).
2922We will be notified, and then you'll automatically be notified of progress on
2923your bug as I make changes.
2924
2925=head1 SUPPORT
2926
2927You can find documentation for this module with the perldoc command.
2928
2929 perldoc Math::BigRat
2930
2931You can also look for information at:
2932
2933=over 4
2934
7deec013 2935=item * GitHub
a7752796 2936
7deec013 2937L<https://github.com/pjacklam/p5-Math-BigRat>
a7752796 2938
7deec013 2939=item * RT: CPAN's request tracker
7d341013 2940
7deec013 2941L<https://rt.cpan.org/Dist/Display.html?Name=Math-BigRat>
7d341013 2942
7deec013 2943=item * MetaCPAN
7d341013 2944
7deec013 2945L<https://metacpan.org/release/Math-BigRat>
7d341013 2946
a7752796 2947=item * CPAN Testers Matrix
7d341013 2948
a7752796 2949L<http://matrix.cpantesters.org/?dist=Math-BigRat>
7d341013 2950
7deec013 2951=item * CPAN Ratings
a7752796 2952
7deec013 2953L<https://cpanratings.perl.org/dist/Math-BigRat>
7afd7a91 2954
7d341013 2955=back
184f15d5
JH
2956
2957=head1 LICENSE
2958
2959This program is free software; you may redistribute it and/or modify it under
2960the same terms as Perl itself.
2961
2962=head1 SEE ALSO
2963
a7752796
PJA
2964L<bigrat>, L<Math::BigFloat> and L<Math::BigInt> as well as the backends
2965L<Math::BigInt::FastCalc>, L<Math::BigInt::GMP>, and L<Math::BigInt::Pari>.
184f15d5
JH
2966
2967=head1 AUTHORS
2968
0b299427
SH
2969=over 4
2970
2971=item *
2972
2973Tels L<http://bloodgate.com/> 2001-2009.
c6c613ed 2974
0b299427
SH
2975=item *
2976
7deec013 2977Maintained by Peter John Acklam <pjacklam@gmail.com> 2011-
0b299427
SH
2978
2979=back
184f15d5
JH
2980
2981=cut