File Coverage

blib/lib/Math/BigInt/Parts.pm
Criterion Covered Total %
statement 66 72 91.6
branch 27 34 79.4
condition 5 9 55.5
subroutine 9 9 100.0
pod 2 2 100.0
total 109 126 86.5


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