File Coverage

blib/lib/Data/IEEE754/Tools.pm
Criterion Covered Total %
statement 237 237 100.0
branch 136 138 98.5
condition 65 70 92.8
subroutine 60 60 100.0
pod 27 49 55.1
total 525 554 94.7


line stmt bran cond sub pod time code
1             package Data::IEEE754::Tools;
2 11     11   141963 use 5.006;
  11         26  
3 11     11   37 use warnings;
  11         11  
  11         207  
4 11     11   28 use strict;
  11         19  
  11         167  
5 11     11   31 use Carp;
  11         8  
  11         697  
6 11     11   43 use Exporter 'import'; # just use the import() function, without the rest of the overhead of ISA
  11         9  
  11         317  
7            
8 11     11   3908 use version 0.77; our $VERSION = version->declare('0.014001');
  11         13678  
  11         49  
9            
10             =pod
11            
12             =head1 NAME
13            
14             Data::IEEE754::Tools - Various tools for understanding and manipulating the underlying IEEE-754 representation of floating point values
15            
16             =head1 SYNOPSIS
17            
18             use Data::IEEE754::Tools qw/:floatingpoint :ulp/;
19            
20             # return -12.875 as decimal and hexadecimal floating point numbers
21             to_dec_floatingpoint(-12.875); # -0d1.6093750000000000p+0003
22             to_hex_floatingpoint(-12.875); # -0x1.9c00000000000p+0003
23            
24             # shows the smallest value you can add or subtract to 16.16 (ulp = "Unit in the Last Place")
25             print ulp( 16.16 ); # 3.5527136788005e-015
26            
27             # toggles the ulp: returns a float that has the ULP of 16.16 toggled
28             # (if it was a 1, it will be 0, and vice versa);
29             # running it twice should give the original value
30             print $t16 = toggle_ulp( 16.16 ); # 16.159999999999997
31             print $v16 = toggle_ulp( $t16 ); # 16.160000000000000
32            
33             =head1 DESCRIPTION
34            
35             These tools give access to the underlying IEEE 754 floating-point 64bit representation
36             used by many instances of Perl (see L). They include functions for converting
37             from the 64bit internal representation to a string that shows those bits (either as
38             hexadecimal or binary) and back, functions for converting that encoded value
39             into a more human-readable format to give insight into the meaning of the encoded
40             values, and functions to manipulate the smallest possible change for a given
41             floating-point value (which is the L or
42             "Unit in the Last Place").
43            
44             =head2 IEEE 754 Encoding
45            
46             The L standard describes
47             various floating-point encodings. The double format (`binary64') is a 64-bit base-2
48             encoding, and correpsonds to the usual Perl floating value (NV). The format includes the
49             sign (s), the power of 2 (q), and a significand (aka, mantissa; the coefficient, c):
50             C. The C<(-1)**s> term evaluates to the sign of the
51             number, where s=0 means the sign is +1 and s=1 means the sign is -1.
52            
53             For most numbers, the coefficient is an implied 1 plus an encoded fraction,
54             which is itself encoded as a 52-bit integer divided by an implied 2**52. The range of
55             valid exponents is from -1022 to +1023, which are encoded as an 11bit integer from 1
56             to 2046 (where C). With an 11bit integer,
57             there are two exponent values (C<0b000_0000_0000 = 0 - 1023 = -1023> and
58             C<0b111_1111_1111 = 2047 - 1023 = +1024>), which are used to indicate conditions outside
59             the normal range: The first special encoded-exponent, C<0b000_0000_0000>, indicates that
60             the coefficient is 0 plus the encoded fraction, at an exponent of -1022; thus, the
61             floating-point zero is encoded using an encoded-exponent of 0 and an encoded-fraction of 0
62             (C<[0 + 0/(2**52)] * [2**-1022] = 0*(2**-1022) = 0>); other numbers
63             smaller than can normally be encoded (so-called "denormals" or "subnormals"), lying
64             between 0 and 1 (non-inclusive) are encoded with the same exponent, but have a non-zero
65             encoded-fraction. The second special encoded-exponent, C<0b111_1111_1111>, indicates a
66             number that is infinite (too big to represent), or something that is not a number (NAN);
67             infinities are indicated by that special exponent and an encoded-fraction of 0; NAN
68             is indicated by that special exponent and a non-zero encoded-fraction.
69            
70             =head2 Justification for the existence of B
71            
72             L, or the equivalent L recipe L>, do a
73             good job of converting a perl floating value (NV) into the big-endian bytes
74             that encode that value, but they don't help you interpret the value.
75            
76             L has a similar suite of tools to B, but
77             uses numerical methods rather than accessing the underlying bits. It L
78             shown|http://perlmonks.org/?node_id=1167146> that its interpretation function can take
79             an order of magnitude longer than a routine that manipulates the underlying bits
80             to gather the information.
81            
82             This B module combines the two sets of functions, giving
83             access to the raw IEEE 754 encoding, or a stringification of the encoding which
84             interprets the encoding as a sign and a coefficient and a power of 2, or access to
85             the ULP and ULP-manipulating features, all using direct bit manipulation when
86             appropriate.
87            
88             =head2 Compatibility
89            
90             B works with 64bit floating-point representations.
91            
92             If you have a Perl setup which uses a larger representation (for example,
93             C; print $Config{nvsize}; # 16 =E 128bit>), values reported by
94             this module will be reduced in precision to fit the 64bit representation.
95            
96             If you have a Perl setup which uses a smaller representation (for example,
97             C; print $Config{nvsize}; # 4 =E 32bit>), the installation
98             will likely fail, because the unit tests were not set up for lower precision
99             inputs. However, forcing the installation I still allow coercion
100             from the smaller Perl NV into a true IEEE 754 double (64bit) floating-point,
101             but there is no guarantee it will work.
102            
103             =head1 INTERFACE NOT YET STABLE
104            
105             Please note: the interface to this module is not yet stable. There may be changes
106             to function naming conventions (under_scores vs. camelCase, argument order, etc).
107             Once B hits v1.000, the interface should be stable for all
108             sub-versions of v1: existing functions should keep the same calling conventions,
109             though new functions may be added; significant changes to the interface will cause
110             a transition to v2.
111            
112             =over
113            
114             =item v0.013_003: C renamed to C
115            
116             =item v0.013_003: C renamed to C
117            
118             =item v0.013_003: C renamed to C
119            
120             =item v0.013_008: C renamed to C, and noted that perl's builtin can be accessed via C
121            
122             =back
123            
124             =head1 EXPORTABLE FUNCTIONS AND VARIABLES
125            
126             =cut
127            
128             my @EXPORT_RAW754 = qw(
129             hexstr754_from_double binstr754_from_double
130             hexstr754_to_double binstr754_to_double
131             );
132             my @EXPORT_FLOATING = qw(to_hex_floatingpoint to_dec_floatingpoint);
133             my @EXPORT_ULP = qw(ulp toggle_ulp nextUp nextDown nextAfter);
134             my @EXPORT_CONST = qw(
135             POS_ZERO
136             POS_DENORM_SMALLEST POS_DENORM_BIGGEST
137             POS_NORM_SMALLEST POS_NORM_BIGGEST
138             POS_INF
139             POS_SNAN_FIRST POS_SNAN_LAST
140             POS_IND POS_QNAN_FIRST POS_QNAN_LAST
141             NEG_ZERO
142             NEG_DENORM_SMALLEST NEG_DENORM_BIGGEST
143             NEG_NORM_SMALLEST NEG_NORM_BIGGEST
144             NEG_INF
145             NEG_SNAN_FIRST NEG_SNAN_LAST
146             NEG_IND NEG_QNAN_FIRST NEG_QNAN_LAST
147             );
148             my @EXPORT_INFO = qw(isSignMinus isNormal isFinite isZero isSubnormal
149             isInfinite isNaN isSignaling isSignalingConvertedToQuiet isCanonical
150             class radix totalOrder totalOrderMag compareFloatingValue compareFloatingMag);
151             my @EXPORT_SIGNBIT = qw(copy negate abs copySign isSignMinus);
152            
153             our @EXPORT_OK = (@EXPORT_FLOATING, @EXPORT_RAW754, @EXPORT_ULP, @EXPORT_CONST, @EXPORT_INFO, @EXPORT_SIGNBIT);
154             our %EXPORT_TAGS = (
155             floating => [@EXPORT_FLOATING],
156             floatingpoint => [@EXPORT_FLOATING],
157             raw754 => [@EXPORT_RAW754],
158             ulp => [@EXPORT_ULP],
159             constants => [@EXPORT_CONST],
160             info => [@EXPORT_INFO],
161             signbit => [@EXPORT_SIGNBIT],
162             all => [@EXPORT_OK],
163             );
164            
165             =head2 :raw754
166            
167             These are the functions to do raw conversion from a floating-point value to a hexadecimal or binary
168             string of the underlying IEEE754 encoded value, and back.
169            
170             =head3 hexstr754_from_double( I )
171            
172             Converts the floating-point I into a big-endian hexadecimal representation of the underlying
173             IEEE754 encoding.
174            
175             hexstr754_from_double(12.875); # 4029C00000000000
176             # ^^^
177             # : ^^^^^^^^^^^^^
178             # : :
179             # : `- fraction
180             # :
181             # `- sign+exponent
182            
183             The first three nibbles (hexadecimal digits) encode the sign and the exponent. The sign is
184             the most significant bit of the three nibbles (so AND the first nibble with 8; if it's true,
185             the number is negative, else it's positive). The remaining 11 bits of the nibbles encode the
186             exponent: convert the 11bits to decimal, then subtract 1023. If the resulting exponent is -1023,
187             it indicates a zero or denormal value; if the exponent is +1024, it indicates an infinite (Inf) or
188             not-a-number (NaN) value, which are generally used to indicate the calculation has grown to large
189             to fit in an IEEE754 double (Inf) or has tried an performed some other undefined operation (divide
190             by zero or the logarithm of a zero or negative value) (NaN).
191            
192             The final thirteen nibbles are the encoding of the fractional value (usually C<1 + thirteennibbles /
193             16**13>, unless it's zero, denormal, infinite, or not a number).
194            
195             Of course, this is easier to decode using the L function, which interprets
196             the sign, fraction, and exponent for you. (See below for more details.)
197            
198             to_dec_floatingpoint(12.875); # +0d1.6093750000000000p+0003
199             # ^ ^^^^^^^^^^^^^^^^^^ ^^^^
200             # : : :
201             # : `- coefficient `- exponent (power of 2)
202             # :
203             # `- sign
204            
205             =head3 binstr754_from_double( I )
206            
207             Converts the floating-point I into a big-endian binary representation of the underlying
208             IEEE754 encoding.
209            
210             binstr754_from_double(12.875); # 0100000000101001110000000000000000000000000000000000000000000000
211             # ^
212             # `- sign
213             # ^^^^^^^^^^^
214             # `- exponent
215             # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
216             # `- fraction
217            
218             The first bit is the sign, the next 11 are the exponent's encoding
219            
220             =head3 hexstr754_to_double( I )
221            
222             The inverse of C: it takes a string representing the 16 nibbles
223             of the IEEE754 double value, and converts it back to a perl floating-point value.
224            
225             print hexstr754_to_double('4029C00000000000');
226             12.875
227            
228             =head3 binstr754_to_double( I )
229            
230             The inverse of C: it takes a string representing the 64 bits
231             of the IEEE754 double value, and converts it back to a perl floating-point value.
232            
233             print binstr754_to_double('0100000000101001110000000000000000000000000000000000000000000000');
234             12.875
235            
236             =cut
237             # Perl 5.10 introduced the ">" and "<" modifiers for pack which can be used to
238             # force a specific endianness.
239             if( $] lt '5.010' ) {
240             my $str = join('', unpack("H*", pack 'L' => 0x12345678));
241             if('78563412' eq $str) { # little endian, so reverse byteorder
242             *hexstr754_from_double = sub { return uc unpack('H*' => reverse pack 'd' => shift); };
243             *binstr754_from_double = sub { return uc unpack('B*' => reverse pack 'd' => shift); };
244            
245             *hexstr754_to_double = sub { return unpack('d' => reverse pack 'H*' => shift); };
246             *binstr754_to_double = sub { return unpack('d' => reverse pack 'B*' => shift); };
247            
248             *arr2x32b_from_double = sub { return unpack('N2' => reverse pack 'd' => shift); };
249             } elsif('12345678' eq $str) { # big endian, so keep default byteorder
250             *hexstr754_from_double = sub { return uc unpack('H*' => pack 'd' => shift); };
251             *binstr754_from_double = sub { return uc unpack('B*' => pack 'd' => shift); };
252            
253             *hexstr754_to_double = sub { return unpack('d' => pack 'H*' => shift); };
254             *binstr754_to_double = sub { return unpack('d' => pack 'B*' => shift); };
255            
256             *arr2x32b_from_double = sub { return unpack('N2' => pack 'd' => shift); };
257             } else {
258             # I don't handle middle-endian / mixed-endian; sorry
259             *hexstr754_from_double = sub { undef };
260             *binstr754_from_double = sub { undef };
261            
262             *hexstr754_to_double = sub { undef };
263             *binstr754_to_double = sub { undef };
264             }
265             } else {
266 6997     6997   135170 *hexstr754_from_double = sub { return uc unpack('H*' => pack 'd>' => shift); };
267 7911     7911   25016 *binstr754_from_double = sub { return uc unpack('B*' => pack 'd>' => shift); };
268            
269 1912     1912   193132 *hexstr754_to_double = sub { return unpack('d>' => pack 'H*' => shift); };
270 4325     4325   14319 *binstr754_to_double = sub { return unpack('d>' => pack 'B*' => shift); };
271            
272 2386     2386   3779 *arr2x32b_from_double = sub { return unpack('N2' => pack 'd>' => shift); };
273             }
274            
275             =head2 :floatingpoint
276            
277             =head3 to_hex_floatingpoint( I )
278            
279             =head3 to_dec_floatingpoint( I )
280            
281             Converts value to a hexadecimal or decimal floating-point notation that indicates the sign and
282             the coefficient and the power of two, with the coefficient either in hexadecimal or decimal
283             notation.
284            
285             to_hex_floatingpoint(-3.9999999999999996) # -0x1.fffffffffffffp+0001
286             to_dec_floatingpoint(-3.9999999999999996) # -0d1.9999999999999998p+0001
287            
288             It displays the value as (sign)(0base)(implied).(fraction)p(exponent):
289            
290             =cut
291            
292             sub to_hex_floatingpoint {
293             # thanks to BrowserUK @ http://perlmonks.org/?node_id=1167146 for slighly better decision factors
294             # I tweaked it to use the two 32bit words instead of one 64bit word (which wouldn't work on some systems)
295 2180     2180 1 10420 my $v = shift;
296 2180         2128 my ($msb,$lsb) = arr2x32b_from_double($v);
297 2180         2070 my $sbit = ($msb & 0x80000000) >> 31;
298 2180 100       2621 my $sign = $sbit ? '-' : '+';
299 2180         2941 my $exp = (($msb & 0x7FF00000) >> 20) - 1023;
300 2180         4142 my $mant = sprintf '%05x%08x', $msb & 0x000FFFFF, $lsb & 0xFFFFFFFF;
301 2180 100       3143 if($exp == 1024) {
302 1164 100       1852 return $sign . "0x1.#INF000000000p+0000" if $mant eq '0000000000000';
303 970 100 100     1866 return $sign . "0x1.#IND000000000p+0000" if $mant eq '8000000000000' and $sign eq '-';
304 919 100       2962 return $sign . ( (($msb & 0x00080000) != 0x00080000) ? "0x1.#SNAN00000000p+0000" : "0x1.#QNAN00000000p+0000"); # v0.012 coverage note: '!=' condition only triggered on systems with SNAN; ignore Devel::Cover failures on this line on systems which quiet all SNAN to QNAN
305             }
306 1016         711 my $implied = 1;
307 1016 100       1332 if( $exp == -1023 ) { # zero or denormal
308 582         403 $implied = 0;
309 582 100       848 $exp = $mant eq '0000000000000' ? 0 : -1022; # 0 for zero, -1022 for denormal
310             }
311 1016         4462 sprintf '%s0x%1u.%13.13sp%+05d', $sign, $implied, $mant, $exp;
312             }
313            
314             sub to_dec_floatingpoint {
315             # based on to_hex_floatingpoint
316 68     68 1 53 my $v = shift;
317 68         86 my ($msb,$lsb) = arr2x32b_from_double($v);
318 68         72 my $sbit = ($msb & 0x80000000) >> 31;
319 68 100       98 my $sign = $sbit ? '-' : '+';
320 68         69 my $exp = (($msb & 0x7FF00000) >> 20) - 1023;
321 68         149 my $mant = sprintf '%05x%08x', $msb & 0x000FFFFF, $lsb & 0xFFFFFFFF;
322 68 100       102 if($exp == 1024) {
323 12 100       46 return $sign . "0d1.#INF000000000000p+0000" if $mant eq '0000000000000';
324 10 100 100     37 return $sign . "0d1.#IND000000000000p+0000" if $mant eq '8000000000000' and $sign eq '-';
325 9 100       144 return $sign . ( (($msb & 0x00080000) != 0x00080000) ? "0d1.#SNAN00000000000p+0000" : "0d1.#QNAN00000000000p+0000"); # v0.012 coverage note: '!=' condition only triggered on systems with SNAN; ignore Devel::Cover failures on this line on systems which quiet all SNAN to QNAN
326             }
327 56         40 my $implied = 1;
328 56 100       68 if( $exp == -1023 ) { # zero or denormal
329 6         5 $implied = 0;
330 6 100       9 $exp = $mant eq '0000000000000' ? 0 : -1022; # 0 for zero, -1022 for denormal
331             }
332             #$mant = (($msb & 0x000FFFFF)*4_294_967_296.0 + ($lsb & 0xFFFFFFFF)*1.0) / (2.0**52);
333             #sprintf '%s0d%1u.%.16fp%+05d', $sign, $implied, $mant, $exp;
334 56         110 my $other = abs($v) / (2.0**$exp);
335 56         1062 sprintf '%s0d%.16fp%+05d', $sign, $other, $exp;
336             }
337            
338            
339             =over
340            
341             =item sign
342            
343             The I will be + or -
344            
345             =item 0base
346            
347             The I<0base> will be C<0x> for hexadecimal, C<0d> for decimal
348            
349             =item implied.fraction
350            
351             The I indicates the hexadecimal or decimal equivalent for the coefficient
352            
353             I will be 0 for zero or denormal numbers, 1 for everything else
354            
355             I will indicate infinities (#INF), signaling not-a-numbers (#SNAN), and quiet not-a-numbers (#QNAN).
356            
357             I will range from decimal 0.0000000000000000 to 0.9999999999999998 for zero thru all the denormals,
358             and from 1.0000000000000000 to 1.9999999999999998 for normal values.
359            
360             =item p
361            
362             The I

introduces the "power" of 2. (It is analogous to the C in C<1.0e3> introducing the power of 10 in a

363             standard decimal floating-point notation, but indicates that the exponent is 2**exp instead of 10**exp.)
364            
365             =item exponent
366            
367             The I is the power of 2. Is is always a decimal number, whether the coefficient's base is hexadecimal or decimal.
368            
369             +0d1.500000000000000p+0010
370             = 1.5 * (2**10)
371             = 1.5 * 1024.0
372             = 1536.0.
373            
374             The I can range from -1022 to +1023.
375            
376             Internally, the IEEE 754 representation uses the encoding of -1023 for zero and denormals; to
377             aid in understanding the actual number, the C conversions represent
378             them as +0000 for zero, and -1022 for denormals: since denormals are C<(0+fraction)*(2**min_exp)>,
379             they are really multiples of 2**-1022, not 2**-1023.
380            
381             =back
382            
383             =head2 :constants
384            
385             These can be useful as references for the specialty values, and include the positive and negative
386             zeroes, infinities, a variety of signaling and quiet NAN values.
387            
388             POS_ZERO # +0x0.0000000000000p+0000 # signed zero (positive)
389             POS_DENORM_SMALLEST # +0x0.0000000000001p-1022 # smallest positive value that requires denormal representation in 64bit floating-point
390             POS_DENORM_BIGGEST # +0x0.fffffffffffffp-1022 # largest positive value that requires denormal representation in 64bit floating-point
391             POS_NORM_SMALLEST # +0x1.0000000000000p-1022 # smallest positive value that allows for normal representation in 64bit floating-point
392             POS_NORM_BIGGEST # +0x1.fffffffffffffp+1023 # largest positive value that allows for normal representation in 64bit floating-point
393             POS_INF # +0x1.#INF000000000p+0000 # positive infinity: indicates that the answer is out of the range of a 64bit floating-point
394             POS_SNAN_FIRST # +0x1.#SNAN00000000p+0000 # positive signaling NAN with "0x0000000000001" as the system-dependent information [*]
395             POS_SNAN_LAST # +0x1.#SNAN00000000p+0000 # positive signaling NAN with "0x7FFFFFFFFFFFF" as the system-dependent information [*]
396             POS_IND # +0x1.#QNAN00000000p+0000 # positive quiet NAN with "0x8000000000000" as the system-dependent information [%]
397             POS_QNAN_FIRST # +0x1.#QNAN00000000p+0000 # positive quiet NAN with "0x8000000000001" as the system-dependent information
398             POS_QNAN_LAST # +0x1.#QNAN00000000p+0000 # positive quiet NAN with "0xFFFFFFFFFFFFF" as the system-dependent information
399            
400             NEG_ZERO # -0x0.0000000000000p+0000 # signed zero (negative)
401             NEG_DENORM_SMALLEST # -0x0.0000000000001p-1022 # smallest negative value that requires denormal representation in 64bit floating-point
402             NEG_DENORM_BIGGEST # -0x0.fffffffffffffp-1022 # largest negative value that requires denormal representation in 64bit floating-point
403             NEG_NORM_SMALLEST # -0x1.0000000000000p-1022 # smallest negative value that allows for normal representation in 64bit floating-point
404             NEG_NORM_BIGGEST # -0x1.fffffffffffffp+1023 # largest negative value that allows for normal representation in 64bit floating-point
405             NEG_INF # -0x1.#INF000000000p+0000 # negative infinity: indicates that the answer is out of the range of a 64bit floating-point
406             NEG_SNAN_FIRST # -0x1.#SNAN00000000p+0000 # negative signaling NAN with "0x0000000000001" as the system-dependent information [*]
407             NEG_SNAN_LAST # -0x1.#SNAN00000000p+0000 # negative signaling NAN with "0x7FFFFFFFFFFFF" as the system-dependent information [*]
408             NEG_IND # -0x1.#IND000000000p+0000 # negative quiet NAN with "0x8000000000000" as the system-dependent information [%]
409             NEG_QNAN_FIRST # -0x1.#QNAN00000000p+0000 # negative quiet NAN with "0x8000000000001" as the system-dependent information
410             NEG_QNAN_LAST # -0x1.#QNAN00000000p+0000 # negative quiet NAN with "0xFFFFFFFFFFFFF" as the system-dependent information
411            
412             [*] note that many perl interpreters will internally convert Signalling NaN (SNAN) to Quiet NaN (QNAN)
413             [%] some perl interpreters define the zeroeth negative Quiet NaN, NEG_IND, as an "indeterminate" value (IND);
414             in a symmetrical world, they would also define the zeroeth positive Quiet NaN, POS_IND, as an "indeterminate" value (IND)
415            
416             =cut
417            
418 9 100   9 0 40 { my $local; sub POS_ZERO () { $local = hexstr754_to_double('000'.'0000000000000') unless defined $local; return $local; } }
  9         22  
419 15 100   15 0 39 { my $local; sub POS_DENORM_SMALLEST() { $local = hexstr754_to_double('000'.'0000000000001') unless defined $local; return $local; } }
  15         28  
420 9 100   9 0 37 { my $local; sub POS_DENORM_BIGGEST () { $local = hexstr754_to_double('000'.'FFFFFFFFFFFFF') unless defined $local; return $local; } }
  9         22  
421 9 100   9 0 28 { my $local; sub POS_NORM_SMALLEST () { $local = hexstr754_to_double('001'.'0000000000000') unless defined $local; return $local; } }
  9         21  
422 9 100   9 0 24 { my $local; sub POS_NORM_BIGGEST () { $local = hexstr754_to_double('7FE'.'FFFFFFFFFFFFF') unless defined $local; return $local; } }
  9         25  
423 9 100   9 0 33 { my $local; sub POS_INF () { $local = hexstr754_to_double('7FF'.'0000000000000') unless defined $local; return $local; } }
  9         23  
424 521 100   521 0 901 { my $local; sub POS_SNAN_FIRST () { $local = hexstr754_to_double('7FF'.'0000000000001') unless defined $local; return $local; } }
  521         665  
425 9 100   9 0 33 { my $local; sub POS_SNAN_LAST () { $local = hexstr754_to_double('7FF'.'7FFFFFFFFFFFF') unless defined $local; return $local; } }
  9         16  
426 9 100   9 0 26 { my $local; sub POS_IND () { $local = hexstr754_to_double('7FF'.'8000000000000') unless defined $local; return $local; } }
  9         18  
427 9 100   9 0 33 { my $local; sub POS_QNAN_FIRST () { $local = hexstr754_to_double('7FF'.'8000000000001') unless defined $local; return $local; } }
  9         23  
428 9 100   9 0 30 { my $local; sub POS_QNAN_LAST () { $local = hexstr754_to_double('7FF'.'FFFFFFFFFFFFF') unless defined $local; return $local; } }
  9         24  
429 7 100   7 0 38 { my $local; sub NEG_ZERO () { $local = hexstr754_to_double('800'.'0000000000000') unless defined $local; return $local; } }
  7         18  
430 7 100   7 0 25 { my $local; sub NEG_DENORM_SMALLEST() { $local = hexstr754_to_double('800'.'0000000000001') unless defined $local; return $local; } }
  7         16  
431 7 100   7 0 23 { my $local; sub NEG_DENORM_BIGGEST () { $local = hexstr754_to_double('800'.'FFFFFFFFFFFFF') unless defined $local; return $local; } }
  7         14  
432 7 100   7 0 21 { my $local; sub NEG_NORM_SMALLEST () { $local = hexstr754_to_double('801'.'0000000000000') unless defined $local; return $local; } }
  7         16  
433 7 100   7 0 26 { my $local; sub NEG_NORM_BIGGEST () { $local = hexstr754_to_double('FFE'.'FFFFFFFFFFFFF') unless defined $local; return $local; } }
  7         15  
434 7 100   7 0 21 { my $local; sub NEG_INF () { $local = hexstr754_to_double('FFF'.'0000000000000') unless defined $local; return $local; } }
  7         18  
435 7 100   7 0 22 { my $local; sub NEG_SNAN_FIRST () { $local = hexstr754_to_double('FFF'.'0000000000001') unless defined $local; return $local; } }
  7         21  
436 7 100   7 0 39 { my $local; sub NEG_SNAN_LAST () { $local = hexstr754_to_double('FFF'.'7FFFFFFFFFFFF') unless defined $local; return $local; } }
  7         14  
437 7 100   7 0 28 { my $local; sub NEG_IND () { $local = hexstr754_to_double('FFF'.'8000000000000') unless defined $local; return $local; } }
  7         17  
438 7 100   7 0 31 { my $local; sub NEG_QNAN_FIRST () { $local = hexstr754_to_double('FFF'.'8000000000001') unless defined $local; return $local; } }
  7         15  
439 7 100   7 0 34 { my $local; sub NEG_QNAN_LAST () { $local = hexstr754_to_double('FFF'.'FFFFFFFFFFFFF') unless defined $local; return $local; } }
  7         19  
440            
441             =head2 :ulp
442            
443             =head3 ulp( I )
444            
445             Returns the ULP ("Unit in the Last Place") for the given I, which is the smallest number
446             that you can add to or subtract from I and still be able to discern a difference between
447             the original and modified. Under normal (or denormal) circumstances, C $val>
448             is true.
449            
450             If the I is a zero or a denormal, C will return the smallest possible denormal.
451            
452             Since INF and NAN are not really numbers, C will just return the same I. Because
453             of the way they are handled, C $val> no longer makes sense (infinity plus
454             anything is still infinity, and adding NAN to NAN is not numerically defined, so a numerical
455             comparison is meaningless on both).
456            
457             =cut
458            
459             my $TWONEG52 = sub { 2.0**-52 };
460             my $FIFTYTWOZEROES = sub { '0'x52 };
461            
462             sub ulp { # ulp_by_div
463 30     30 1 59 my $val = shift;
464 30         32 my $rawbin = binstr754_from_double($val);
465 30         95 my ($sgn, $exp, $frac) = ($rawbin =~ /(.)(.{11})(.{52})/);
466            
467 30 100       72 return $val if $exp eq '11111111111'; # return SELF for INF or NAN
468 18 100       26 return POS_DENORM_SMALLEST if $exp eq '00000000000'; # return first positive denorm for 0 or denorm
469            
470             # this method will multiply by 2**-52 (as a constant) after
471 12         13 $sgn = '0';
472 12         14 $frac = $FIFTYTWOZEROES->();
473 12         18 $val = binstr754_to_double( $sgn . $exp . $frac );
474 12         14 $val *= $TWONEG52->();
475             }
476            
477             =head3 toggle_ulp( I )
478            
479             Returns the orginal I, but with the ULP toggled. In other words, if the ULP bit
480             was a 0, it will return a value with the ULP of 1 (equivalent to adding one ULP to a positive
481             I); if the ULP bit was a 1, it will return a value with the ULP of 0 (equivalent to
482             subtracting one ULP from a positive I). Under normal (or denormal) circumstances,
483             C is true.
484            
485             Since INF and NAN are not really numbers, C will just return the same I. Because
486             of the way they are handled, C no longer makes sense.
487            
488             =cut
489            
490             sub toggle_ulp {
491 26     26 1 71 my $val = shift;
492 26         32 my $rawbin = binstr754_from_double($val);
493 26         106 my ($sign, $exp, $fract) = ($rawbin =~ /(.)(.{11})(.{52})/);
494            
495             # INF and NAN do not have a meaningful ULP; just return SELF
496 26 100       68 if( $exp == '1'x11 ) {
497 12         20 return $val;
498             }
499            
500             # ZERO, DENORMAL, and NORMAL: toggle the last bit of fract
501 14         18 my $ulp_bit = substr $fract, -1;
502 14         19 substr $fract, -1, 1, (1-$ulp_bit);
503 14         15 $rawbin = join '', $sign, $exp, $fract;
504 14         19 return binstr754_to_double($rawbin);
505             }
506            
507             =head3 nextUp( I )
508            
509             Returns the next floating point value numerically greater than I; that is, it adds one ULP.
510             Returns infinite when I is the highest normal floating-point value.
511             Returns I when I is positive-infinite or NAN; returns the largest negative normal
512             floating-point value when I is negative-infinite.
513            
514             C is an IEEE 754r standard function (754-2008 #5.3.1).
515            
516             =cut
517            
518             sub nextUp {
519             # thanks again to BrowserUK: http://perlmonks.org/?node_id=1167146
520 176     176 1 199 my $val = shift;
521 176 100       329 return $val if $val != $val; # interestingly, NAN != NAN
522 156         204 my $h754 = hexstr754_from_double($val);
523 156 100       256 return $val if $h754 eq '7FF0000000000000'; # return self for +INF
524 154 100       189 return hexstr754_to_double('FFEFFFFFFFFFFFFF') if $h754 eq 'FFF0000000000000'; # return largest negative for -INF
525 142 100       178 return hexstr754_to_double('0000000000000001') if $h754 eq '8000000000000000'; # return +SmallestDenormal for -ZERO
526 138         157 my ($msb,$lsb) = arr2x32b_from_double($val);
527 138 100       231 $lsb += ($msb & 0x80000000) ? -1.0 : +1.0;
528 138 100       229 if($lsb == 4_294_967_296.0) {
    100          
529 22         19 $lsb = 0.0;
530 22         20 $msb += 1.0; # v0.012: LSB==4e9 only happens if you add one to LSB = 0xFFFFFFFF, so only when +msb; thus, remove extra check for msb sign here
531             } elsif ($lsb == -1.0) {
532 30         23 $lsb = 0xFFFFFFFF;
533 30         30 $msb -= 1.0; # v0.012: LSB==-1 only happens if you subtract one from LSB = 0x00000000, so only when -msb; thus, remove extra check for msb sign here
534             }
535 138         105 $msb &= 0xFFFFFFFF; # v0.011_001: bugfix: ensure 32bit MSB
536 138         101 $lsb &= 0xFFFFFFFF; # v0.011_001: bugfix: ensure 32bit MSB
537 138         388 return hexstr754_to_double( sprintf '%08X%08X', $msb, $lsb );
538             }
539            
540             =head3 nextDown( I )
541            
542             Returns the next floating point value numerically lower than I; that is, it subtracts one ULP.
543             Returns -infinity when I is the largest negative normal floating-point value.
544             Returns I when I is negative-infinite or NAN; returns the largest positive normal
545             floating-point value when I is positive-infinite.
546            
547             C is an IEEE 754r standard function (754-2008 #5.3.1).
548            
549             =cut
550            
551             sub nextDown {
552 88     88 1 181 return - nextUp( - $_[0] );
553             }
554            
555             =head3 nextAfter( I, I )
556            
557             Returns the next floating point value after I in the direction of I. If the
558             two are identical, return I; if I is numerically above I, return
559             C)>; if I is numerically below I, return C)>.
560            
561             =cut
562            
563             sub nextAfter {
564 270 100   270 1 1006 return $_[0] if $_[0] != $_[0]; # return value when value is NaN
565 160 100       243 return $_[1] if $_[1] != $_[1]; # return direction when direction is NaN
566 140 100       204 return $_[1] if $_[1] == $_[0]; # return direction when the two are equal
567 112 100       241 return nextUp($_[0]) if $_[1] > $_[0]; # return nextUp if direction > value
568 56         78 return nextDown($_[0]); # otherwise, return nextDown()
569             }
570            
571             =head2 :info
572            
573             The informational functions include various operations (defined in 754-2008 #5.7.2) that provide general
574             information about the floating-point value: most define whether a value is a special condition of
575             floating-point or not (such as normal, finite, zero, ...).
576            
577             =head3 isSignMinus( I )
578            
579             Returns 1 if I has negative sign (even applies to zeroes and NaNs); otherwise, returns 0.
580            
581             =cut
582            
583             sub isSignMinus {
584             # look at leftmost nibble, and determine whether it has the 8-bit or not (which is the sign bit)
585 1030     1030 1 180033 return (hex(substr(hexstr754_from_double(shift),0,1)) & 8) >> 3;
586             }
587            
588             =head3 isNormal( I )
589            
590             Returns 1 if I is a normal number (not zero, subnormal, infinite, or NaN); otherwise, returns 0.
591            
592             =cut
593            
594             sub isNormal {
595             # it's normal if the leftmost three nibbles (excluding sign bit) are not 000 or 7FF
596 36     36 1 7708 my $exp = hex(substr(hexstr754_from_double(shift),0,3)) & 0x7FF;
597 36   100     267 return (0 < $exp) && ($exp < 0x7FF) || 0;
598             }
599            
600             =head3 isFinite( I )
601            
602             Returns 1 if I is a finite number (zero, subnormal, or normal; not infinite or NaN); otherwise, returns 0.
603            
604             =cut
605            
606             sub isFinite {
607             # it's finite if the leftmost three nibbles (excluding sign bit) are not 7FF
608 22     22 1 7904 my $exp = hex(substr(hexstr754_from_double(shift),0,3)) & 0x7FF;
609 22   100     150 return ($exp < 0x7FF) || 0;
610             }
611            
612             =head3 isZero( I )
613            
614             Returns 1 if I is positive or negative zero; otherwise, returns 0.
615            
616             =cut
617            
618             sub isZero {
619             # it's zero if it's 0x[80]000000000000000
620 707     707 1 8278 my $str = substr(hexstr754_from_double(shift),1,15);
621 707   100     2516 return ($str eq '0'x15) || 0;
622             }
623            
624             =head3 isSubnormal( I )
625            
626             Returns 1 if I is subnormal (not zero, normal, infinite, nor NaN); otherwise, returns 0.
627            
628             =cut
629            
630             sub isSubnormal {
631             # it's subnormal if it's 0x[80]00___ and the last 13 digits are not all zero
632 36     36 1 7415 my $h = hexstr754_from_double(shift);
633 36         40 my $exp = substr($h,0,3);
634 36         35 my $frc = substr($h,3,13);
635 36   100     307 return ($exp eq '000' || $exp eq '800') && ($frc ne '0'x13) || 0;
636             }
637            
638             =head3 isInfinite( I )
639            
640             Returns 1 if I is positive or negative infinity (not zero, subnormal, normal, nor NaN); otherwise, returns 0.
641            
642             =cut
643            
644             sub isInfinite {
645             # it's infinite if it's 0x[F7]FF_0000000000000
646 35     35 1 7606 my $h = hexstr754_from_double(shift);
647 35         41 my $exp = substr($h,0,3);
648 35         34 my $frc = substr($h,3,13);
649 35   100     299 return ($exp eq '7FF' || $exp eq 'FFF') && ($frc eq '0'x13) || 0;
650             }
651            
652             =head3 isNaN( I )
653            
654             Returns 1 if I is NaN (not zero, subnormal, normal, nor infinite); otherwise, returns 0.
655            
656             =cut
657            
658             sub isNaN {
659             # it's infinite if it's 0x[F7]FF_0000000000000
660 3912     3912 1 11543 my $h = hexstr754_from_double(shift);
661 3912         3805 my $exp = substr($h,0,3);
662 3912         3042 my $frc = substr($h,3,13);
663 3912   100     18467 return ($exp eq '7FF' || $exp eq 'FFF') && ($frc ne '0'x13) || 0;
664             }
665            
666             =head3 isSignaling( I )
667            
668             Returns 1 if I is a signaling NaN (not zero, subnormal, normal, nor infinite), otherwise, returns 0.
669            
670             Note that some perl implementations convert some or all signaling NaNs to quiet NaNs, in which case,
671             C might return only 0.
672            
673             =cut
674            
675             sub isSignaling {
676             # it's signaling if isNaN and MSB of fractional portion is 1
677 556     556 1 673 my $h = hexstr754_from_double(shift);
678 556         626 my $exp = substr($h,0,3);
679 556         513 my $frc = substr($h,3,13);
680 556         685 my $qbit = (0x8 && hex(substr($h,3,1))) >> 3; # 1: quiet, 0: signaling
681 556   100     4388 return ($exp eq '7FF' || $exp eq 'FFF') && ($frc ne '0'x13) && (!$qbit) || 0; # v0.013_007 = possible coverage bug: don't know whether it's the paren or non-paren, but the "LEFT=TRUE" condition of "OR 2 CONDITIONS" is never covered
682             }
683            
684             =head4 isSignalingConvertedToQuiet()
685            
686             Returns 1 if your implementation of perl converts a SignalingNaN to a QuietNaN, otherwise returns 0.
687            
688             This is I a standard IEEE 754 function; but this is used to determine if the C
689             function is meaningful in your implementation of perl.
690            
691             =cut
692            
693             sub isSignalingConvertedToQuiet {
694 512 50   512 1 12062 !isSignaling( POS_SNAN_FIRST ) || 0 # v0.013 coverage note: ignore Devel::Cover failures on this line
695             }
696            
697             =head3 isCanonical( I )
698            
699             Returns 1 to indicate that I is Canonical.
700            
701             Per IEEE Std 754-2008, "Canonical" is the "preferred" encoding. Based on the
702             B's author's reading of the standard, non-canonical
703             applies to decimal floating-point encodings, not the binary floating-point
704             encodings that B handles. Since there are not multiple
705             choicesfor the representation of a binary-encoded floating-point, all
706             Is seem canonical, and thus return 1.
707            
708             =cut
709            
710 22     22 1 7813 sub isCanonical { 1 }
711            
712             =head3 class( I )
713            
714             Returns the "class" of the I:
715            
716             signalingNaN
717             quietNaN
718             negativeInfinity
719             negativeNormal
720             negativeSubnormal
721             negativeZero
722             positiveZero
723             positiveSubnormal
724             positiveNormal
725             positiveInfinity
726            
727             =cut
728            
729             sub class {
730 22 100   22 1 6214 return 'signalingNaN' if isSignaling($_[0]); # v0.013 coverage note: ignore Devel::Cover failures on this line (won't return on systems that quiet SNaNs
731 18 100       27 return 'quietNaN' if isNaN($_[0]);
732 12 100 100     19 return 'negativeInfinity' if isInfinite($_[0]) && isSignMinus($_[0]);
733 11 100 100     19 return 'negativeNormal' if isNormal($_[0]) && isSignMinus($_[0]);
734 9 100 100     12 return 'negativeSubnormal' if isSubnormal($_[0]) && isSignMinus($_[0]);
735 7 100 100     12 return 'negativeZero' if isZero($_[0]) && isSignMinus($_[0]);
736 6 100 66     8 return 'positiveZero' if isZero($_[0]) && !isSignMinus($_[0]); # v0.013 coverage note: ignore Devel::Cover->CONDITION failure; alternate condition already returned above
737 5 100 66     11 return 'positiveSubnormal' if isSubnormal($_[0]) && !isSignMinus($_[0]); # v0.013 coverage note: ignore Devel::Cover->CONDITION failure; alternate condition already returned above
738 3 100 66     5 return 'positiveNormal' if isNormal($_[0]) && !isSignMinus($_[0]); # v0.013 coverage note: ignore Devel::Cover->CONDITION failure; alternate condition already returned above
739 1 50 33     2 return 'positiveInfinity' if isInfinite($_[0]) && !isSignMinus($_[0]); # v0.013 coverage note: no tests for FALSE because all conditions covered above
740             }
741            
742             =head3 radix( I )
743            
744             Returns the base (radix) of the internal floating point representation.
745             This module works with the binary floating-point representations, so will always return 2.
746            
747             =cut
748            
749 22     22 1 7818 sub radix { 2 }
750            
751             =head3 totalOrder( I, I )
752            
753             Returns TRUE if I E I, FALSE if I E I.
754            
755             Special cases are ordered as below:
756            
757             -quietNaN < -signalingNaN < -infinity < ...
758             ... < -normal < -subnormal < -zero < ...
759             ... < +zero < +subnormal < +normal < ...
760             ... < +infinity < +signalingNaN < +quietNaN
761            
762             =cut
763            
764             sub totalOrder {
765 968     968 1 2577 my ($x, $y) = @_[0,1];
766 968         881 my ($bx,$by) = map { binstr754_from_double($_) } $x, $y; # convert to binary strings
  1936         1780  
767 968         3784 my @xsegs = ($bx =~ /(.)(.{11})(.{20})(.{32})/); # split into sign, exponent, MSB, LSB
768 968         2249 my @ysegs = ($by =~ /(.)(.{11})(.{20})(.{32})/); # split into sign, exponent, MSB, LSB
769 968         877 my ($xin, $yin) = map { isNaN($_) } $x, $y; # determine if NaN: used twice each, so save the values rather than running twice each during if-switch
  1936         1905  
770            
771 968 100 100     2944 if( $xin && $yin ) { # BOTH NaN
    100 100        
    100          
    100          
772             # use a trick: the rules for both-NaN treat it as if it's just another floating point,
773             # so lie about the exponent and do a normal comparison
774 200         209 ($bx, $by) = map { $_->[1] = '1' . '0'x10; join '', @$_ } \@xsegs, \@ysegs;
  400         349  
  400         727  
775 200         197 ($x, $y) = map { binstr754_to_double($_) } $bx, $by;
  400         371  
776 200   100     792 return (($x <= $y) || 0);
777             } elsif ( $xin ) { # just x NaN: TRUE if x is NEG
778 240   100     820 return ( ($xsegs[0]) || 0 );
779             } elsif ( $yin ) { # just y NaN: TRUE if y is not NEG
780 240   100     765 return ( (!$ysegs[0]) || 0 );
781             } elsif ( isZero($x) && isZero($y) ) { # both zero: TRUE if x NEG, or if x==y
782             # trick = -signbit(x) <= -signbit(y), since signbit is 1 for negative, -signbit = -1 for negative
783 8   100     39 return ( (-$xsegs[0] <= -$ysegs[0]) || 0 );
784             } else { # numeric comparison (works for inf, normal, subnormal, or only one +/-zero)
785 280   100     1074 return( ($x <= $y) || 0 );
786             }
787             }
788            
789             =head3 totalOrderMag( I, I )
790            
791             Returns TRUE if I E I, otherwise FALSE.
792             Equivalent to
793            
794             totalOrder( abs(x), abs(y) )
795            
796             Special cases are ordered as below:
797            
798             zero < subnormal < normal < infinity < signalingNaN < quietNaN
799            
800             =cut
801            
802             sub totalOrderMag {
803 484     484 1 121585 my ($x, $y) = @_[0,1];
804 484         577 my ($bx,$by) = map { binstr754_from_double($_) } $x, $y; # convert to binary strings
  968         1040  
805 484         443 ($x, $y) = map { substr $_, 0, 1, '0'; binstr754_to_double($_) } $bx, $by; # set sign bit to 0, and convert back to number
  968         882  
  968         974  
806 484         638 return totalOrder( $x, $y ); # compare normally
807             }
808            
809             =head3 compareFloatingValue( I, I )
810            
811             =head3 compareFloatingMag( I, I )
812            
813             These are similar to C and C, except they return
814             -1 for C y>, 0 for C, and +1 for C y>.
815            
816             These are not in IEEE 754-2008, but are included as functions to replace the perl spaceship
817             (C=E>) when comparing floating-point values that might be NaN.
818            
819             =cut
820            
821             sub compareFloatingValue {
822 968     968 1 122408 my ($x, $y) = @_[0,1];
823 968         936 my ($bx,$by) = map { binstr754_from_double($_) } $x, $y; # convert to binary strings
  1936         2045  
824 968         3508 my @xsegs = ($bx =~ /(.)(.{11})(.{20})(.{32})/); # split into sign, exponent, MSB, LSB
825 968         2342 my @ysegs = ($by =~ /(.)(.{11})(.{20})(.{32})/); # split into sign, exponent, MSB, LSB
826 968         920 my ($xin, $yin) = map { isNaN($_) } $x, $y; # determine if NaN: used twice each, so save the values rather than running twice each during if-switch
  1936         1994  
827            
828 968 100 100     2882 if( $xin && $yin ) { # BOTH NaN
    100 100        
    100          
    100          
829             # use a trick: the rules for both-NaN treat it as if it's just another floating point,
830             # so lie about the exponent and do a normal comparison
831 200         215 ($bx, $by) = map { $_->[1] = '1' . '0'x10; join '', @$_ } \@xsegs, \@ysegs;
  400         328  
  400         719  
832 200         207 ($x, $y) = map { binstr754_to_double($_) } $bx, $by;
  400         381  
833 200         543 return ($x <=> $y);
834             } elsif ( $xin ) { # just x NaN: if isNaN(x) && isNegative(x) THEN -1 (xy)
835 240   100     1050 return ( ($xsegs[0])*-1 || +1 );
836             } elsif ( $yin ) { # just y NaN: if isNaN(y) && !isNegative(y) THEN -1 (xy)
837 240   100     848 return ( (!$ysegs[0])*-1 || +1 );
838             } elsif ( isZero($x) && isZero($y) ) { # both zero: TRUE if x NEG, or if x==y
839             # trick = -signbit(x) <=> -signbit(y), since signbit is 1 for negative, -signbit = -1 for negative
840 8         25 return (-$xsegs[0] <=> -$ysegs[0]);
841             } else { # numeric comparison (works for inf, normal, subnormal, or only one +/-zero)
842 280         669 return ($x <=> $y);
843             }
844             }
845            
846             sub compareFloatingMag {
847 484     484 1 120112 my ($x, $y) = @_[0,1];
848 484         585 my ($bx,$by) = map { binstr754_from_double($_) } $x, $y; # convert to binary strings
  968         993  
849 484         426 ($x, $y) = map { substr $_, 0, 1, '0'; binstr754_to_double($_) } $bx, $by; # set sign bit to 0, and convert back to number
  968         884  
  968         1026  
850 484         624 return compareFloatingValue( $x, $y ); # compare normally
851             }
852            
853             =head2 :signbit
854            
855             These functions, from IEEE Std 754-2008, manipulate the sign bits
856             of the argument(s)set P.
857            
858             See IEEE Std 754-2008 #5.5.1 "Sign bit operations": This section asserts
859             that the sign bit operations (including C, C, and C)
860             should only affect the sign bit, and should treat numbers and NaNs alike.
861            
862             =head3 copy( I )
863            
864             Copies the I to the output, leaving the sign bit unchanged, for all
865             numbers and NaNs.
866            
867             =cut
868            
869             sub copy {
870 44     44 1 5290 return shift;
871             }
872            
873             =head3 negate( I )
874            
875             Reverses the sign bit of I. (If the sign bit is set on I,
876             it will not be set on the output, and vice versa; this will work on
877             signed zeroes, on infinities, and on NaNs.)
878            
879             =cut
880            
881             sub negate {
882 44     44 1 5146 my $b = binstr754_from_double(shift); # convert to binary string
883 44         86 my $s = 1 - substr $b, 0, 1; # toggle sign
884 44         46 substr $b, 0, 1, $s; # replace sign
885 44         54 return binstr754_to_double($b); # convert to floating-point
886             }
887            
888             =head3 abs( I )
889            
890             Similar to the C builtin function, C is provided as a
891             module-based function to get the absolute value (magnitude) of a 64bit
892             floating-point number.
893            
894             The C function behaves properly (per the IEEE 754 description)
895             for all classes of I, except that many implementations do not correctly
896             handle -NaN properly, outputting -NaN, which is in violation of the standard.
897             The C function correctly treats NaNs in the same
898             way it treats numerical values, and clears the sign bit on the output.
899            
900             Please note that exporting C or C<:signbit> from this module will
901             "hide" the builtin C function. If you really need to use the builtin
902             version (for example, you care more about execution speed than its ability to find
903             the absolute value of a signed NaN), then you may call it as C.
904            
905             =cut
906            
907             sub abs {
908 1012     1012 1 179138 my $b = binstr754_from_double(shift); # convert to binary string
909 1012         1090 substr $b, 0, 1, '0'; # replace sign
910 1012         1224 return binstr754_to_double($b); # convert to floating-point
911             }
912            
913             =head3 copySign( I, I )
914            
915             Copies the sign from I, but uses the value from I. For example,
916            
917             $new = copySign( 1.25, -5.5); # $new is -1.25: the value of x, but the sign of y
918            
919             =cut
920            
921             sub copySign {
922 484     484 1 1428 my ($x, $y) = @_[0,1];
923 484         642 my ($bx,$by) = map { binstr754_from_double($_) } $x, $y; # convert to binary strings
  968         963  
924 484         643 substr($bx, 0, 1) = substr($by, 0, 1); # copy the sign bit from y to x
925 484         623 return binstr754_to_double($bx); # convert binary-x (with modified sign) back to double
926             }
927            
928             =head3 also exports C I C<)> (see :info)
929            
930             (:signbit also exports the C function, described in :info, above)
931            
932             =head2 :all
933            
934             Include all of the above.
935            
936             =head1 INSTALLATION
937            
938             To install this module, use your favorite CPAN client.
939            
940             For a manual install, type the following:
941            
942             perl Makefile.PL
943             make
944             make test
945             make install
946            
947             (On Windows machines, you may need to use "dmake" instead of "make".)
948            
949             =head1 SEE ALSO
950            
951             =over
952            
953             =item * L
954            
955             =item * L for
956             inspiring me to go down the IEEE754-expansion trail in perl.
957            
958             =item * L as a resource
959             for how perl interacts with the various "edge cases" (+/-infinity, L,
960             signaling and quiet L.
961            
962             =item * L: I really wanted to use this module, but it didn't get me very far down the "Tools" track,
963             and included a lot of overhead modules for its install/test that I didn't want to require for B.
964             However, I was inspired by his byteorder-dependent anonymous subs (which were in turn derived from L);
965             they were more efficient, on a per-call-to-subroutine basis, than my original inclusion of the if(byteorder) in every call to
966             the sub.
967            
968             =item * L: Similar to this module, but uses numeric manipulation.
969            
970             =back
971            
972             =head1 AUTHOR
973            
974             Peter C. Jones Cpetercj AT cpan DOT orgE>
975            
976             Please report any bugs or feature requests emailing Cbug-Data-IEEE754-Tools AT rt.cpan.orgE>
977             or thru the web interface at L,
978             or thru the repository's interface at L.
979            
980             =head1 COPYRIGHT
981            
982             Copyright (C) 2016 Peter C. Jones
983            
984             =head1 LICENSE
985            
986             This program is free software; you can redistribute it and/or modify it
987             under the terms of either: the GNU General Public License as published
988             by the Free Software Foundation; or the Artistic License.
989            
990             See L for more information.
991            
992             =cut
993            
994             1;