File Coverage

blib/lib/Math/Float128.pm
Criterion Covered Total %
statement 84 93 90.3
branch 36 42 85.7
condition 3 6 50.0
subroutine 34 34 100.0
pod 0 3 0.0
total 157 178 88.2


line stmt bran cond sub pod time code
1             ## This file generated by InlineX::C2XS (version 0.22) using Inline::C (version 0.53)
2             package Math::Float128;
3 23     23   9926 use warnings;
  23         148  
  23         603  
4 23     23   103 use strict;
  23         35  
  23         379  
5              
6 23     23   7913 use Math::Float128::Constant;
  23         50  
  23         6083  
7              
8             require Exporter;
9             *import = \&Exporter::import;
10             require DynaLoader;
11              
12             use overload
13 23         551 '+' => \&_overload_add,
14             '*' => \&_overload_mul,
15             '-' => \&_overload_sub,
16             '/' => \&_overload_div,
17             '**' => \&_overload_pow,
18             '+=' => \&_overload_add_eq,
19             '*=' => \&_overload_mul_eq,
20             '-=' => \&_overload_sub_eq,
21             '/=' => \&_overload_div_eq,
22             '**=' => \&_overload_pow_eq,
23             '==' => \&_overload_equiv,
24             '""' => \&_overload_string,
25             '!=' => \&_overload_not_equiv,
26             'bool' => \&_overload_true,
27             '!' => \&_overload_not,
28             '=' => \&_overload_copy,
29             '<' => \&_overload_lt,
30             '<=' => \&_overload_lte,
31             '>' => \&_overload_gt,
32             '>=' => \&_overload_gte,
33             '<=>' => \&_overload_spaceship,
34             'abs' => \&_overload_abs,
35             'int' => \&_overload_int,
36             'sqrt' => \&_overload_sqrt,
37             'log' => \&_overload_log,
38             'exp' => \&_overload_exp,
39             'sin' => \&_overload_sin,
40             'cos' => \&_overload_cos,
41             'atan2' => \&_overload_atan2,
42             '++' => \&_overload_inc,
43             '--' => \&_overload_dec,
44 23     23   23095 ;
  23         20417  
45              
46 23     23   7191 use constant F128_PV_NV_BUG => Math::Float128::Constant::_has_pv_nv_bug();
  23         42  
  23         2455  
47              
48             # Inspired by https://github.com/Perl/perl5/issues/19550:
49 23     23   138 use constant ISSUE_19550 => Math::Float128::Constant::_issue_19550();
  23         38  
  23         85  
50              
51 23         108 use subs qw(FLT128_DIG FLT128_MANT_DIG FLT128_MIN_EXP FLT128_MAX_EXP FLT128_MIN_10_EXP FLT128_MAX_10_EXP
52             M_Eq M_LOG2Eq M_LOG10Eq M_LN2q M_LN10q M_PIq M_PI_2q M_PI_4q M_1_PIq M_2_PIq
53             M_2_SQRTPIq M_SQRT2q M_SQRT1_2q
54 23     23   11206 FLT128_MAX FLT128_MIN FLT128_EPSILON FLT128_DENORM_MIN);
  23         599  
55              
56             $Math::Float128::VERSION = '0.16';
57              
58             Math::Float128->DynaLoader::bootstrap($Math::Float128::VERSION);
59              
60             @Math::Float128::EXPORT = ();
61             @Math::Float128::EXPORT_OK = qw(
62             F128_PV_NV_BUG
63             flt128_set_prec flt128_get_prec InfF128 NaNF128 ZeroF128 UnityF128 is_NaNF128
64             is_InfF128 is_InfF128 is_ZeroF128 STRtoF128 NVtoF128 IVtoF128 UVtoF128 F128toSTR
65             F128toSTRP F128toF128 F128toNV
66             FLT128_DIG FLT128_MANT_DIG FLT128_MIN_EXP FLT128_MAX_EXP FLT128_MIN_10_EXP FLT128_MAX_10_EXP
67             M_Eq M_LOG2Eq M_LOG10Eq M_LN2q M_LN10q M_PIq M_PI_2q M_PI_4q M_1_PIq M_2_PIq
68             M_2_SQRTPIq M_SQRT2q M_SQRT1_2q
69             FLT128_MAX FLT128_MIN FLT128_EPSILON FLT128_DENORM_MIN
70             cmp2NV f128_bytes
71             acos_F128 acosh_F128 asin_F128 asinh_F128 atan_F128 atanh_F128 atan2_F128 cbrt_F128 ceil_F128
72             copysign_F128 cosh_F128 cos_F128 erf_F128 erfc_F128 exp_F128 expm1_F128 fabs_F128 fdim_F128
73             finite_F128 floor_F128 fma_F128 fmax_F128 fmin_F128 fmod_F128 frexp_F128 hypot_F128 isinf_F128
74             ilogb_F128 isnan_F128 j0_F128 j1_F128 jn_F128 ldexp_F128 lgamma_F128 llrint_F128 llround_F128
75             log_F128 log10_F128 log2_F128 log1p_F128 lrint_F128 lround_F128 modf_F128 nan_F128
76             nearbyint_F128 nextafter_F128 pow_F128 remainder_F128 remquo_F128 rint_F128 round_F128
77             scalbln_F128 scalbn_F128 signbit_F128 sincos_F128 sinh_F128 sin_F128 sqrt_F128 tan_F128
78             tanh_F128 tgamma_F128 trunc_F128 y0_F128 y1_F128 yn_F128
79             fromSTR fromNV fromIV fromUV fromF128
80             );
81              
82             %Math::Float128::EXPORT_TAGS = (all => [qw(
83             F128_PV_NV_BUG
84             flt128_set_prec flt128_get_prec InfF128 NaNF128 ZeroF128 UnityF128 is_NaNF128
85             is_InfF128 is_InfF128 is_ZeroF128 STRtoF128 NVtoF128 IVtoF128 UVtoF128 F128toSTR
86             F128toSTRP F128toF128 F128toNV
87             FLT128_DIG FLT128_MANT_DIG FLT128_MIN_EXP FLT128_MAX_EXP FLT128_MIN_10_EXP FLT128_MAX_10_EXP
88             M_Eq M_LOG2Eq M_LOG10Eq M_LN2q M_LN10q M_PIq M_PI_2q M_PI_4q M_1_PIq M_2_PIq
89             M_2_SQRTPIq M_SQRT2q M_SQRT1_2q
90             FLT128_MAX FLT128_MIN FLT128_EPSILON FLT128_DENORM_MIN
91             cmp2NV f128_bytes
92             acos_F128 acosh_F128 asin_F128 asinh_F128 atan_F128 atanh_F128 atan2_F128 cbrt_F128 ceil_F128
93             copysign_F128 cosh_F128 cos_F128 erf_F128 erfc_F128 exp_F128 expm1_F128 fabs_F128 fdim_F128
94             finite_F128 floor_F128 fma_F128 fmax_F128 fmin_F128 fmod_F128 frexp_F128 hypot_F128 isinf_F128
95             ilogb_F128 isnan_F128 j0_F128 j1_F128 jn_F128 ldexp_F128 lgamma_F128 llrint_F128 llround_F128
96             log_F128 log10_F128 log2_F128 log1p_F128 lrint_F128 lround_F128 modf_F128 nan_F128
97             nearbyint_F128 nextafter_F128 pow_F128 remainder_F128 remquo_F128 rint_F128 round_F128
98             scalbln_F128 scalbn_F128 signbit_F128 sincos_F128 sinh_F128 sin_F128 sqrt_F128 tan_F128
99             tanh_F128 tgamma_F128 trunc_F128 y0_F128 y1_F128 yn_F128
100             fromSTR fromNV fromIV fromUV fromF128
101             )]);
102              
103             $Math::Float128::NOK_POK = 0; # Set to 1 to allow warnings in new() and overloaded operations when
104             # a scalar that has set both NOK (NV) and POK (PV) flags is encountered
105              
106 23     23 0 24412 sub dl_load_flags {0} # Prevent DynaLoader from complaining and croaking
107              
108             sub _overload_string {
109              
110 8 100   8   207 if(is_ZeroF128($_[0])) {
111 4 100       13 return '-0' if is_ZeroF128($_[0]) < 0;
112 2         5 return '0';
113             }
114              
115 4 100       17 if(is_NaNF128($_[0])) {return 'NaN'}
  2         7  
116              
117 2         7 my $inf = is_InfF128($_[0]);
118 2 100       7 return '-Inf' if $inf < 0;
119 1 50       14 return 'Inf' if $inf > 0;
120              
121 0         0 my @p = split /e/i, F128toSTR($_[0]);
122 0   0     0 while(substr($p[0], -1, 1) eq '0' && substr($p[0], -2, 1) ne '.') {
123 0         0 chop $p[0];
124             }
125 0         0 return $p[0] . 'e' . $p[1];
126             }
127              
128             sub new {
129              
130             # This function caters for 2 possibilities:
131             # 1) that 'new' has been called as a method - in which
132             # case there will be a maximum of 2 args
133             # 2) that 'new' has been called as a function - in
134             # which case there will be a maximum of 1 arg.
135             # If there are no args, then we just want to return a
136             # Math::Float128 object that's a NaN.
137              
138 450 50   450 0 12131 if(!@_) {return NaNF128()}
  0         0  
139              
140 450 50       734 if(@_ > 2) {die "More than 2 arguments supplied to new()"}
  0         0  
141              
142             # If 'new' has been called OOP style, the first arg is the string
143             # "Math::Float128" which we don't need - so let's remove it. However,
144             # if the first arg is a Math::Float128 object (which is a possibility),
145             # then we'll get a fatal error when we check it for equivalence to
146             # the string "Math::Float128". So we first need to check that it's
147             # not an object - which we'll do by using the ref() function:
148 450 100 100     1218 if(!ref($_[0]) && $_[0] eq "Math::Float128") {
149 444         505 shift;
150 444 100       668 if(!@_) {return NaNF128()}
  8         59  
151             }
152              
153 442 50       633 if(@_ > 1) {die "Too many arguments supplied to new() - expected no more than 1"}
  0         0  
154              
155 442         526 my $arg = shift; # At this point, an infnan might acquire a POK flag - thus
156             # assigning to $type a value of 4, instead of 3. Such behaviour also
157             # turns $arg into a PV and NV dualvar. It's a fairly inconsequential
158             # bug - https://github.com/Perl/perl5/issues/19550.
159             # I could workaround this by simply not shifting and re-assigning, but
160             # I'll leave it as it is - otherwise there's nothing to mark that this
161             # minor issue (which might also show up in user code) ever existed.
162 442         1066 my $type = _itsa($arg);
163              
164 442 100       864 return UVtoF128 ($arg) if $type == 1; #UV
165 417 100       1483 return IVtoF128 ($arg) if $type == 2; #IV
166              
167 267 100       397 if($type == 4) { #PV
168 98 100       221 if(_SvNOK($arg)) {
169 6         34 set_nok_pok(nok_pokflag() + 1);
170 6 50       14 if($Math::Float128::NOK_POK) {
171 0         0 warn "Scalar passed to new() is both NV and PV. Using PV (string) value";
172             }
173             }
174 98         678 return STRtoF128($arg);
175             }
176              
177 169 100       255 if($type == 3) { # NV
178              
179 142         141 if(F128_PV_NV_BUG) {
180             if(_SvPOK($arg)) {
181             set_nok_pok(nok_pokflag() + 1);
182             if($Math::Float128::NOK_POK) {
183             warn "Scalar passed to new() is both NV and PV. Using NV (numeric) value";
184             }
185             }
186             }
187              
188 142 100       239 if($arg == 0) {return NVtoF128($arg)}
  2         8  
189 140 100       240 if($arg != $arg) { return NaNF128()}
  2         24  
190 138 100       220 if(($arg / $arg) != 1) { # Inf
191 4 100       10 if($arg < 0) {return InfF128(-1)}
  2         21  
192 2         8 return InfF128(1);
193             }
194 134         864 return NVtoF128($arg);
195             }
196              
197 27 50       52 if($type == 113) { # Math::Float128
198 27         138 return F128toF128($arg);
199             }
200              
201 0         0 die "Bad argument given to new";
202             }
203              
204              
205             sub f128_bytes {
206 1     1 0 69 my @ret = _f128_bytes($_[0]);
207 1         6 return join '', @ret;
208             }
209              
210 2     2   242 sub FLT128_DIG () {return _FLT128_DIG()}
211 1     1   36 sub FLT128_MAX () {return _FLT128_MAX()}
212 1     1   41 sub FLT128_MIN () {return _FLT128_MIN()}
213 1     1   22 sub FLT128_EPSILON () {return _FLT128_EPSILON()}
214 1     1   42 sub FLT128_DENORM_MIN () {return _FLT128_DENORM_MIN()}
215 1     1   34 sub FLT128_MANT_DIG () {return _FLT128_MANT_DIG()}
216 1     1   13 sub FLT128_MIN_EXP () {return _FLT128_MIN_EXP()}
217 1     1   11 sub FLT128_MAX_EXP () {return _FLT128_MAX_EXP()}
218 1     1   11 sub FLT128_MIN_10_EXP () {return _FLT128_MIN_10_EXP()}
219 1     1   11 sub FLT128_MAX_10_EXP () {return _FLT128_MAX_10_EXP()}
220 1     1   38 sub M_Eq () {return _M_Eq()}
221 1     1   21 sub M_LOG2Eq () {return _M_LOG2Eq()}
222 1     1   34 sub M_LOG10Eq () {return _M_LOG10Eq()}
223 1     1   16 sub M_LN2q () {return _M_LN2q()}
224 1     1   18 sub M_LN10q () {return _M_LN10q()}
225 1     1   16 sub M_PIq () {return _M_PIq()}
226 1     1   16 sub M_PI_2q () {return _M_PI_2q()}
227 1     1   17 sub M_PI_4q () {return _M_PI_4q()}
228 1     1   30 sub M_1_PIq () {return _M_1_PIq()}
229 1     1   23 sub M_2_PIq () {return _M_2_PIq()}
230 1     1   16 sub M_2_SQRTPIq () {return _M_2_SQRTPIq()}
231 1     1   30 sub M_SQRT2q () {return _M_SQRT2q()}
232 1     1   21 sub M_SQRT1_2q () {return _M_SQRT1_2q()}
233              
234             1;
235