File Coverage

blib/lib/Math/decNumber.pm
Criterion Covered Total %
statement 166 167 99.4
branch 56 74 75.6
condition n/a
subroutine 56 57 98.2
pod 3 3 100.0
total 281 301 93.3


line stmt bran cond sub pod time code
1             package Math::decNumber;
2             #
3             # Copyright (c) 2014 Jean-Louis Morel
4             #
5             # Version 0.01
6             #
7             # This program is free software; you can redistribute it and/or modify
8             # it under the same terms as Perl itself.
9             #
10             # This program is distributed in the hope that it will be useful,
11             # but WITHOUT ANY WARRANTY; without even the implied warranty of
12             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the
13             # GNU General Public License or the Artistic License for more details.
14             #
15              
16 51     51   103060 use 5.006000;
  51         174  
  51         2828  
17 51     51   289 use strict;
  51         238  
  51         2255  
18 51     51   273 use warnings;
  51         84  
  51         3656  
19              
20             require Exporter;
21              
22             our @ISA = qw(Exporter);
23              
24             # Round modes
25 51     51   288 use constant ROUND_CEILING => 0; # round towards +infinity
  51         87  
  51         4616  
26 51     51   580 use constant ROUND_UP => 1; # round away from 0
  51         98  
  51         6257  
27 51     51   416 use constant ROUND_HALF_UP => 2; # 0.5 rounds up
  51         90  
  51         3341  
28 51     51   251 use constant ROUND_HALF_EVEN => 3; # 0.5 rounds to nearest even
  51         671  
  51         3658  
29 51     51   286 use constant ROUND_HALF_DOWN => 4; # 0.5 rounds down
  51         94  
  51         2772  
30 51     51   282 use constant ROUND_DOWN => 5; # round towards 0 (truncate)
  51         96  
  51         3564  
31 51     51   833 use constant ROUND_FLOOR => 6; # round towards -infinity
  51         111  
  51         2502  
32 51     51   253 use constant ROUND_05UP => 7; # Round away from zero if the last digit
  51         156  
  51         2381  
33             # is 0 or 5, otherwise towards zero.
34              
35             # Trap-enabler and Status flags
36 51     51   3462 use constant DEC_Conversion_syntax => 0x00000001;
  51         1424  
  51         2667  
37 51     51   302 use constant DEC_Division_by_zero => 0x00000002;
  51         105  
  51         3027  
38 51     51   259 use constant DEC_Division_impossible => 0x00000004;
  51         94  
  51         3744  
39 51     51   270 use constant DEC_Division_undefined => 0x00000008;
  51         90  
  51         2798  
40 51     51   277 use constant DEC_Insufficient_storage => 0x00000010;
  51         111  
  51         2841  
41 51     51   273 use constant DEC_Inexact => 0x00000020;
  51         169  
  51         2804  
42 51     51   237 use constant DEC_Invalid_context => 0x00000040;
  51         95  
  51         3072  
43 51     51   253 use constant DEC_Invalid_operation => 0x00000080;
  51         82  
  51         2775  
44 51     51   330 use constant DEC_Lost_digits => 0x00000100;
  51         81  
  51         2184  
45 51     51   259 use constant DEC_Overflow => 0x00000200;
  51         95  
  51         2391  
46 51     51   247 use constant DEC_Clamped => 0x00000400;
  51         93  
  51         2351  
47 51     51   334 use constant DEC_Rounded => 0x00000800;
  51         94  
  51         3010  
48 51     51   276 use constant DEC_Subnormal => 0x00001000;
  51         96  
  51         2331  
49 51     51   256 use constant DEC_Underflow => 0x00002000;
  51         93  
  51         11096  
50              
51             # flags which cause a result to become qNaN
52 51         14168 use constant DEC_NaNs => DEC_Conversion_syntax |
53             DEC_Division_impossible |
54             DEC_Division_undefined |
55             DEC_Insufficient_storage |
56             DEC_Invalid_context |
57 51     51   620 DEC_Invalid_operation;
  51         90  
58              
59             # flags which are normally errors (result is qNaN, infinite, or 0)
60 51         5112 use constant DEC_Errors => DEC_Division_by_zero |
61             DEC_NaNs |
62             DEC_Overflow |
63 51     51   401 DEC_Underflow;
  51         2246  
64              
65             # flags which are normally for information only (finite results)
66 51         160693 use constant DEC_Information => DEC_Clamped |
67             DEC_Rounded |
68             DEC_Inexact |
69 51     51   273 DEC_Lost_digits;
  51         85  
70              
71             # Items to export into callers namespace by default. Note: do not export
72             # names by default without a very good reason. Use EXPORT_OK instead.
73             # Do not simply export all your public functions/methods/constants.
74              
75             # This allows declaration use Math::decNumber ':all';
76             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
77             # will save memory.
78             our %EXPORT_TAGS = (
79             'all' => [ qw(
80             ROUND_CEILING ROUND_UP ROUND_HALF_UP ROUND_HALF_EVEN ROUND_HALF_DOWN
81             ROUND_DOWN ROUND_FLOOR ROUND_05UP ROUND_MAX
82             DEC_Conversion_syntax DEC_Division_by_zero DEC_Division_impossible
83             DEC_Division_undefined DEC_Insufficient_storage DEC_Inexact
84             DEC_Invalid_context DEC_Invalid_operation DEC_Lost_digits
85             DEC_Overflow constant DEC_Clamped DEC_Rounded
86             DEC_Subnormal DEC_Underflow
87             DEC_NaNs DEC_Errors DEC_Information
88              
89             ToIntegralValue FMA NextToward Divide Xor Or Max DivideInteger
90             ToEngString SquareRoot Exp Min ToString FromString Add Multiply Abs
91             CompareSignal Shift RemainderNear ScaleB NextPlus LogB
92             CompareTotalMag Subtract Invert Log10 NextMinus Plus
93             Quantize Compare Power ToIntegralExact And SameQuantum
94             Rescale Remainder CompareTotal Ln Minus MaxMag MinMag d_
95             Class ClassToString Reduce Rotate Trim Radix Copy CopyNegate
96             CopySign CopyAbs Version
97              
98             ContextClearStatus ContextGetStatus ContextStatusToString
99             ContextSetStatus ContextSetStatusQuiet ContextSetStatusFromString
100             ContextSetStatusFromStringQuiet ContextSaveStatus
101             ContextTestStatus ContextTestSavedStatus ContextRestoreStatus
102             ContextZeroStatus
103             ContextRounding ContextPrecision ContextMaxExponent
104             ContextMinExponent ContextTraps ContextClamp ContextExtended
105              
106             IsNormal IsSubnormal IsCanonical IsFinite IsInfinite IsNaN
107             IsNegative IsQNaN IsSNaN IsSpecial IsZero
108             ) ],
109             'ROUND_' => [ qw(
110             ROUND_CEILING ROUND_UP ROUND_HALF_UP ROUND_HALF_EVEN ROUND_HALF_DOWN
111             ROUND_DOWN ROUND_FLOOR ROUND_05UP
112             ) ],
113             'DEC_' => [ qw(
114             DEC_Conversion_syntax DEC_Division_by_zero DEC_Division_impossible
115             DEC_Division_undefined DEC_Insufficient_storage DEC_Inexact
116             DEC_Invalid_context DEC_Invalid_operation DEC_Lost_digits
117             DEC_Overflow DEC_Clamped DEC_Rounded
118             DEC_Subnormal DEC_Underflow
119             DEC_NaNs DEC_Errors DEC_Information
120             ) ],
121              
122             );
123              
124             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
125              
126             our @EXPORT = qw(
127             );
128              
129             our $VERSION = '0.02';
130              
131             require XSLoader;
132             XSLoader::load('Math::decNumber', $VERSION);
133              
134             sub _d_ {
135 469 100   469   1011 return $_[0] if (ref($_[0]) eq 'decNumberPtr');
136 468         620 my $s = shift;
137 468         3327 $s =~ s/^\s*//;
138 468         1713 $s =~ s/\s*$//;
139 468         3380 return Math::decNumber::FromString($s);
140             }
141              
142             sub d_ {
143 462 100   462 1 14247 return _d_($_[0]) if 1 == @_;
144 4         15 return map _d_($_), @_;
145             }
146              
147             sub ContextStatusToString {
148 23 100   23 1 17755 return _ContextStatusToString() unless wantarray;
149 5         11 my @r;
150 5         14 my $status = ContextGetStatus();
151 5 50       14 push @r,'Conversion syntax' if ( $status & DEC_Conversion_syntax );
152 5 50       12 push @r,'Division by zero' if ( $status & DEC_Division_by_zero );
153 5 100       14 push @r,'Division impossible' if ( $status & DEC_Division_impossible );
154 5 50       11 push @r,'Division undefined' if ( $status & DEC_Division_undefined );
155 5 50       12 push @r,'Insufficient storage' if ( $status & DEC_Insufficient_storage );
156 5 100       14 push @r,'Inexact' if ( $status & DEC_Inexact );
157 5 50       68 push @r,'Invalid context' if ( $status & DEC_Invalid_context );
158 5 50       13 push @r,'Invalid operation' if ( $status & DEC_Invalid_operation );
159 5 50       12 push @r,'Lost digits' if ( $status & DEC_Lost_digits );
160 5 50       9 push @r,'Overflow' if ( $status & DEC_Overflow );
161 5 50       16 push @r,'Clamped' if ( $status & DEC_Clamped );
162 5 50       9 push @r,'Rounded' if ( $status & DEC_Rounded );
163 5 100       12 push @r,'Subnormal' if ( $status & DEC_Subnormal );
164 5 100       19 push @r,'Underflow' if ( $status & DEC_Underflow );
165 5         22 return @r;
166             }
167              
168             sub ClassToString {
169 103     103 1 44189 my $a = shift;
170 103 100       306 $a = Class($a) if ref $a eq 'decNumberPtr';
171 103         448 return _ClassToString($a);
172             }
173              
174             package decNumberPtr;
175              
176             sub as_string{
177 512     512   3026 return Math::decNumber::ToString($_[0]);
178             }
179              
180             sub _add { # +
181 394     394   1142 my ($u, $v) = @_;
182 394 100       2403 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
183 394         2469 return Math::decNumber::Add( $u, $v );
184             }
185              
186             sub _sub { # -
187 286     286   460 my ($u, $v, $mut) = @_;
188 286 50       627 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
189 286 50       1701 return $mut? Math::decNumber::Subtract( $v, $u )
190             : Math::decNumber::Subtract( $u, $v );
191             }
192              
193             sub _mul { # *
194 272     272   1447 my ($u, $v) = @_;
195 272 100       1004 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
196 272         1798 return Math::decNumber::Multiply( $u, $v );
197             }
198              
199             sub _div { # /
200 17     17   31 my ($u, $v, $mut) = @_;
201 17 100       71 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
202 17 50       193 return $mut? Math::decNumber::Divide( $v, $u )
203             : Math::decNumber::Divide( $u, $v );
204             }
205              
206             sub _abs {
207 2     2   19 return Math::decNumber::Abs($_[0]);
208             }
209              
210             sub _sqrt {
211 2     2   88 return Math::decNumber::SquareRoot($_[0]);
212             }
213              
214             sub _equiv { # ==
215 388     388   606 my ($u, $v) = @_;
216 388 100       994 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
217 388         1714 return !Math::decNumber::Compare( $u, $v );
218             }
219              
220             sub _diff { # !=
221 111     111   163 my ($u, $v) = @_;
222 111 100       441 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
223 111         651 return Math::decNumber::Compare( $u, $v );
224             }
225              
226             sub _comp { # <=>
227 16     16   31 my ($u, $v, $mut) = @_;
228 16 100       74 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
229 16 100       143 return $mut? Math::decNumber::Compare( $v, $u )
230             : Math::decNumber::Compare( $u, $v );
231             }
232              
233             sub _copy {
234 2     2   19 return Math::decNumber::Copy($_[0]);
235             }
236              
237             sub _copyneg {
238 6     6   67 return Math::decNumber::CopyNegate($_[0]);
239             }
240              
241             sub _power {
242 3     3   7 my ($u, $v, $mut) = @_;
243 3 100       63 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
244 3 100       49 return $mut? Math::decNumber::Power( $v, $u )
245             : Math::decNumber::Power( $u, $v );
246             }
247              
248             sub _log {
249 1     1   24 return Math::decNumber::Ln($_[0]);
250             }
251              
252             sub _exp {
253 0     0   0 return Math::decNumber::Exp($_[0]);
254             }
255              
256             sub _mod { # %
257 3     3   5 my ($u, $v, $mut) = @_;
258 3 100       16 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
259 3 100       42 return $mut? Math::decNumber::Remainder( $v, $u )
260             : Math::decNumber::Remainder( $u, $v );
261             }
262              
263             sub _inv { # ~
264 1     1   16 return Math::decNumber::Invert($_[0]);
265             }
266              
267             sub _and { # and
268 1     1   4 my ($u, $v) = @_;
269 1 50       6 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
270 1         9 return Math::decNumber::And( $u, $v );
271             }
272              
273             sub _or { # or
274 1     1   3 my ($u, $v) = @_;
275 1 50       6 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
276 1         10 return Math::decNumber::Or( $u, $v );
277             }
278              
279             sub _xor { # xor
280 1     1   3 my ($u, $v) = @_;
281 1 50       5 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
282 1         9 return Math::decNumber::Xor( $u, $v );
283             }
284              
285             sub _lshift { # shift
286 1     1   3 my ($u, $v) = @_;
287 1 50       7 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
288 1         8 return Math::decNumber::Shift( $u, $v );
289             }
290              
291             sub _rshift { # rotate
292 1     1   2 my ($u, $v) = @_;
293 1 50       9 $v = Math::decNumber::FromString($v) unless ref $v eq 'decNumberPtr';
294 1         5 return Math::decNumber::Shift( $u, -$v );
295             }
296              
297             sub _increment { # ++
298 2     2   21 Math::decNumber::_increment( $_[0] )
299             }
300              
301             sub _decrement { # --
302 2     2   19 Math::decNumber::_decrement( $_[0] )
303             }
304              
305             use overload
306 51         998 '""' => \&as_string,
307             '+' => \&_add,
308             '-' => \&_sub,
309             '*' => \&_mul,
310             '/' => \&_div,
311             'abs' => \&_abs,
312             'sqrt' => \&_sqrt,
313             '==' => \&_equiv,
314             '!=' => \&_diff,
315             '=' => \&_copy,
316             'neg' => \&_copyneg,
317             '**' => \&_power,
318             'log' => \&_log,
319             '<=>' => \&_comp,
320             'exp' => \&_exp,
321             '%' => \&_mod,
322             '~' => \&_inv,
323             '&' => \&_and,
324             '|' => \&_or,
325             '^' => \&_xor,
326             '<<' => \&_lshift,
327             '>>' => \&_rshift,
328             '++' => \&_increment,
329 51     51   126903 '--' => \&_decrement;
  51         75539  
330              
331             1;