File Coverage

blib/lib/Math/BigInt/Parts.pm
Criterion Covered Total %
statement 65 71 91.5
branch 27 34 79.4
condition 5 9 55.5
subroutine 9 9 100.0
pod 2 2 100.0
total 108 125 86.4


line stmt bran cond sub pod time code
1             # -*- mode: perl; coding: us-ascii-unix; -*-
2              
3             package Math::BigInt::Parts;
4              
5 3     3   183270 use 5.008; # required version of Perl
  3         9  
6 3     3   14 use strict; # restrict unsafe constructs
  3         4  
  3         64  
7 3     3   11 use warnings; # control optional warnings
  3         5  
  3         81  
8 3     3   11 use utf8; # enable UTF-8 in source code
  3         3  
  3         29  
9              
10 3     3   65 use Carp; # routines like die() and warn() useful for modules
  3         4  
  3         259  
11 3     3   12 use Exporter; # implements default import method for modules
  3         3  
  3         336  
12              
13             our @ISA = qw(Exporter);
14             our @EXPORT = qw();
15             our @EXPORT_OK = qw(fparts eparts);
16             our %EXPORT_TAGS = (all => [ @EXPORT_OK ]);
17              
18             our $VERSION = '0.03';
19              
20 3     3   1203 use Math::BigFloat;
  3         50168  
  3         15  
21              
22             =pod
23              
24             =head1 NAME
25              
26             Math::BigInt::Parts - split a Math::BigInt into signed mantissa and exponent
27              
28             =head1 SYNOPSIS
29              
30             use Math::BigInt::Parts;
31              
32             # Planck's constant
33              
34             $h = Math::BigFloat -> new('6.6260693e-34');
35              
36             # A non-zero, finite mantissa $m always satisfies 1 <= $m < 10:
37              
38             ($m, $e) = fparts($h); # $m = 6.6260693, $e = -34
39              
40             # A non-zero, finite mantissa $m always satisfies 1 <= $m < 1000
41             # and the exponent $e is always a multiple of 3:
42              
43             ($m, $e) = eparts($h); # $m = 662.60693, $e = -36
44              
45             # Compare this to the standard parts method, which returns both
46             # the mantissa and exponent as integers:
47              
48             ($m, $e) = $h -> parts(); # $m = 66260693, $e = -41
49              
50             # The functions can also be used as methods, by importing them
51             # into the Math::BigInt namespace:
52              
53             {
54             package Math::BigInt;
55             use Math::BigInt::Parts ':all';
56             }
57              
58             ($m, $e) = $h -> fparts();
59             ($m, $e) = $h -> eparts();
60              
61             =head1 DESCRIPTION
62              
63             This module implements the Math::BigInt functions fparts() and eparts() which
64             are variants of the standard Math::BigInt method parts(). The functions
65             fparts() and eparts() return the mantissa and exponent with the values that are
66             common for floating point numbers in standard notation and in engineering
67             notation, respectively.
68              
69             =head1 FUNCTIONS
70              
71             =head2 Behaviour common to both functions
72              
73             The following applies to both functions, and assumes the functions are called
74             using
75              
76             ($m, $e) = fparts($x); # fparts() or eparts()
77             $m = fparts($x); # fparts() or eparts()
78              
79             =over 4
80              
81             =item Values
82              
83             For a zero value operand C<$x>, both the mantissa C<$m> and the exponent C<$e>
84             is zero. For plus/minus infinity, the mantissa is a signed infinity and the
85             exponent is plus infinity. For NaN (Not-a-Number), both the mantissa and the
86             exponent is NaN. For a non-zero, finite C<$x>, see the appropriate function
87             below.
88              
89             Regardless of the operand C<$x> and the function, the returned mantissa C<$m>
90             and the exponent C<$e> give back the value of C<$x> with
91              
92             $x = Math::BigFloat -> new(10) -> bpow($e) -> bmul($m);
93              
94             or the more efficient
95              
96             $x = $m -> copy() -> blsft($e, 10);
97              
98             Note that since $e is a Math::BigInt, the following
99              
100             $x = $m * 10 ** $e;
101              
102             will only give back the value of C<$x> when C<$e> is non-negative.
103              
104             =item Context
105              
106             In list context the mantissa and exponent is returned. In scalar context the
107             mantissa is returned. In void context a warning is given, since there is no
108             point in using any of the functions in a void context.
109              
110             =item Classes
111              
112             The mantissa is always a Math::BigFloat object, and the exponent is always a
113             Math::BigInt object.
114              
115             =back
116              
117             =head2 Behaviour specific to each function
118              
119             =over 4
120              
121             =item fparts ()
122              
123             For a non-zero, finite C<$x> the mantissa C<$m> always satisfies 1 E= C<$m>
124             E 10 and the exponent is an integer.
125              
126             =cut
127              
128             sub fparts {
129 484     484 1 100345 my $self = shift;
130 484         680 my $selfref = ref $self;
131 484   33     942 my $class = $selfref || $self;
132 484         533 my $name = 'fparts';
133              
134             # Check the context.
135              
136 484 50       811 unless (defined wantarray) {
137 0         0 carp "$name(): Useless use of $name in void context";
138 0         0 return;
139             }
140              
141             # Check the number of input arguments.
142              
143             #croak "$name(): Not enough input arguments" if @_ < 0;
144 484 50       963 croak "$name(): Too many input arguments" if @_ > 0;
145              
146             # Check the input argument.
147              
148 484 50       1315 unless (UNIVERSAL::isa($self, 'Math::BigInt')) {
149 0         0 croak "$name(): Input argument must be a Math::BigInt object",
150             " or subclass thereof";
151             }
152              
153             # Not-a-number.
154              
155 484 100       1086 if ($self -> is_nan()) {
156 8         61 my $mant = Math::BigFloat -> bnan(); # mantissa
157 8 100       230 return $mant unless wantarray; # scalar context
158 4         16 my $expo = Math::BigInt -> bnan(); # exponent
159 4         81 return ($mant, $expo); # list context
160             }
161              
162             # Infinity.
163             #
164             # Work around Math::BigInt inconsistency. The sign() method returns '-' and
165             # '+' for negative and non-negative numbers, but '-inf' and '+inf' for
166             # negative and positive infinity. Why not '-' and '+' for +/- inf too?
167              
168 476 100       3096 if ($self -> is_inf()) {
169 16 100       148 my $signstr = $self < 0 ? '-' : '+';
170 16         1904 my $mant = Math::BigFloat -> binf($signstr); # mantissa
171 16 100       452 return $mant unless wantarray; # scalar context
172 8         28 my $expo = Math::BigInt -> binf('+'); # exponent
173 8         189 return ($mant, $expo); # list context
174             }
175              
176             # Finite number.
177             #
178             # Get the mantissa and exponent. The documentation for Math::BigInt says
179             # that one should not assume that the mantissa is an integer. The code
180             # below works also if the mantissa is a Math::BigFloat non-integer.
181              
182             # Split the number into mantissa and exponent. E.g., convert 3141500 into
183             # 31415 and 2, since 3141500 = 31415 * 10^2.
184              
185 460         3215 my ($mant, $expo) = $self -> parts();
186              
187             # Make sure the mantissa is a Math::BigFloat.
188              
189 460 50       49722 $mant = Math::BigFloat -> new($mant)
190             unless UNIVERSAL::isa($mant, 'Math::BigFloat');
191              
192             # Adjust the exponent so it is zero if the mantissa is zero.
193              
194 460 100       28117 if ($mant -> bcmp(0)) {
195              
196             # The documentation for Math::BigInt says that the output of parts()
197             # might not be normalized, i.e., 31400 might give 314 and 2, or 3140
198             # and 1, or 314100 and 0. The code below, also works if the output of
199             # parts() is 31.4 and 3, or 3.14 and 5, or 0.314 and 6, ...
200              
201 456         60600 my ($ndigtot, $ndigfrac) = $mant -> length();
202              
203             # Compute the exponent by which the mantissa and exponent should be
204             # adjusted so it is normalized in the sense that the mantissa M
205             # satisfies 1 <= M < 10.
206              
207 456         9840 my $expo10adj = $ndigtot - $ndigfrac - 1;
208              
209             # Adjust the mantissa. E.g., convert 31415 into 3.1415.
210              
211 456         1074 my $fmant = $mant -> brsft($expo10adj, 10);
212              
213             # Scalar context. Return the mantissa only.
214              
215 456 100       342398 return $fmant unless wantarray;
216              
217             # List context. Return the mantissa and the exponent. Adjust the
218             # exponent the "opposite way" of how we adjusted the mantissa, to
219             # ensure that the input argument = $fmant * 10 ** $fexpo.
220              
221 342         967 my $fexpo = $expo -> copy() -> badd($expo10adj);
222              
223             # We return the exponent as a Math::BigFloat so that people can use
224             # $fmant * 10 ** fexpo and get what they expect.
225              
226             #$fexpo = Math::BigFloat -> new($fexpo);
227              
228 342         42471 return ($fmant, $fexpo);
229              
230             } else {
231              
232 4 100       501 return $mant unless wantarray;
233              
234             # 0 -> 0e0, not 0e1
235              
236 3         10 $expo = $expo -> bzero();
237              
238 3         47 return ($mant, $expo);
239             }
240              
241             }
242              
243             =pod
244              
245             =item eparts ()
246              
247             For a non-zero, finite C<$x> the mantissa C<$m> always satisfies 1 E= C<$m>
248             E 1000 and the exponent is an integer which is a multiple of 3.
249              
250             =cut
251              
252             sub eparts {
253 242     242 1 83036 my $self = shift;
254 242         331 my $selfref = ref $self;
255 242   33     484 my $class = $selfref || $self;
256 242         234 my $name = 'eparts';
257              
258             # Check the context.
259              
260 242 50       435 unless (defined wantarray) {
261 0         0 carp "$name(): Useless use of $name in void context";
262 0         0 return;
263             }
264              
265             # Check the number of input arguments.
266              
267             #croak "$name(): Not enough input arguments" if @_ < 0;
268 242 50       521 croak "$name(): Too many input arguments" if @_ > 0;
269              
270             # Check the input argument.
271              
272 242 50       639 unless (UNIVERSAL::isa($self, 'Math::BigInt')) {
273 0         0 croak "$name(): Input argument must be a Math::BigInt object",
274             " or subclass thereof";
275             }
276              
277             # Not-a-number and Infinity.
278             #
279             # Simply call the "fparts" method in this case.
280              
281 242 100 100     566 if ($self -> is_nan() || $self -> is_inf()) {
282 12         167 return fparts($self);
283             }
284              
285             # Finite number.
286             #
287             # Call the "fparts" method and adjust its output so the exponent becomes a
288             # multiple of 3.
289              
290 230         3224 my ($fmant, $fexpo) = fparts($self);
291              
292             # Make sure the exponent is a multiple of 3, and adjust the mantissa and
293             # accordingly.
294              
295 230         481 my $c = $fexpo -> copy() -> bmod(3);
296              
297             #my $emant = $fmant * 10 ** $c;
298 230         26619 my $emant = $fmant -> blsft($c, 10);
299              
300             # Scalar context. Return the mantissa only.
301              
302 230 100       92455 return $emant unless wantarray;
303              
304             # List context.
305              
306 115         321 my $eexpo = $fexpo - $c;
307 115         7748 return ($emant, $eexpo);
308             }
309              
310             =pod
311              
312             =back
313              
314             =head1 BUGS
315              
316             Please report any bugs or feature requests to
317             C, or through the web interface at
318              
319             L
320              
321             I will be notified, and then you'll automatically be notified of progress on
322             your bug as I make changes.
323              
324             =head1 SUPPORT
325              
326             You can find documentation for this module with the perldoc command.
327              
328             perldoc Math::BigInt::Parts
329              
330             You can also look for information at:
331              
332             =over 4
333              
334             =item * RT: CPAN's request tracker
335              
336             L
337              
338             =item * CPAN Ratings
339              
340             L
341              
342             =item * Search CPAN
343              
344             L
345              
346             =item * CPAN Testers PASS Matrix
347              
348             L
349              
350             =item * CPAN Testers Reports
351              
352             L
353              
354             =item * CPAN Testers Matrix
355              
356             L
357              
358             =back
359              
360             =head1 SEE ALSO
361              
362             The documentation for Math::BigInt and Math::BigFloat.
363              
364             =head1 AUTHOR
365              
366             Peter John Acklam, Epjacklam@online.noE
367              
368             If you have found this module to be useful, I will be happy to hear about it!
369              
370             =head1 COPYRIGHT AND LICENSE
371              
372             Copyright 2006-2010 by Peter John Acklam Epjacklam@online.noE
373              
374             This library is free software; you can redistribute it and/or modify
375             it under the same terms as Perl itself, either Perl version 5.8.0 or,
376             at your option, any later version of Perl 5 you may have available.
377              
378             =cut
379              
380             1; # modules must return true