From 96632c541426e6a510159f44507eb348acfcea8c Mon Sep 17 00:00:00 2001 From: PeterCJ Date: Thu, 23 Mar 2017 15:07:50 -0700 Subject: [PATCH 1/8] v0.017_002: rename :floatingpoint, to_hex_floatingpoint(), to_dec_floatingpoint() to :convertToCharacter, convertToHexCharacter(), convertToDecimalCharacter() --- CHANGES | 7 +++- TODO | 11 ++++-- lib/Data/IEEE754/Tools.pm | 72 +++++++++++++++++++++++---------------- t/02-floatingpoint.t | 12 +++---- t/03-ulp.t | 10 +++--- t/04-nextupdown.t | 16 ++++----- t/06-constants.t | 12 +++++-- t/09-signbit.t | 4 +-- t/10-copysign.t | 8 ++--- 9 files changed, 91 insertions(+), 61 deletions(-) diff --git a/CHANGES b/CHANGES index a0eb9f7..09ad31a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,7 +1,12 @@ Revision history for Perl module Data::IEEE754::Tools. v0.017 internal development version - - v0.017_001: META = adding Travis-CI, coveralls.io, automatic signatures, etc. + - v0.017_001_github_integrations: META = adding Travis-CI, coveralls.io, + automatic signatures, etc. + - v0.017_002_namingconvention: start changing names per the naming- + convention issue#6 + - rename :floatingpoint, to_hex_floatingpoint(), to_dec_floatingpoint() + to :convertToCharacter, convertToHexCharacter(), convertToDecimalCharacter() v0.016 2016-Aug-29 - had a bug in v0.014 Makefile which caused CPAN to not diff --git a/TODO b/TODO index 0ae0049..c875104 100644 --- a/TODO +++ b/TODO @@ -3,19 +3,24 @@ TODO + IEEE754 5.4.2 => 5.12 -convertFormat -convertFromDecimalCharacter - -convertToDecimalCharacter + # converts a string decimal number (ie, output of to_dec_floatingpoint) + # into a -floating point value + -convertToDecimalCharacter(source, conversionSpecification) # alias for to_dec_floatingpoint() # conversionSpecification is supposed to indicate formatting # might want to use an optional integer which indicates how many places - # after the fractional-point to display (default to 16 => %16.16s for to_dec_floatingpoint) + # after the fractional-point to display (default to 16 => %.16f for to_dec_floatingpoint) + IEEE754 5.4.3 => 5.12 -convertFromHexCharacter + # converts a string hexadecimal number (ie, output of to_hex_floatingpoint) + # into a -floating point value -convertToHexCharacter(source, conversionSpecification) # alias for to_hex_floatingpoint() # I originally thought these were aliases for my rawhex754 functions... but no # conversionSpecification is supposed to indicate formatting # might want to use an optional integer which indicates how many places - # after the fractional-point to display (default to 16 => %16.16s for to_dec_floatingpoint) + # after the fractional-point to display (default to 13 => %13.13s for to_hex_floatingpoint) + + valid = qw(binary32 binary64 binary128) - long-term: add in _32bit and _128bit versions - what's official name of 128bit long-double? quad? something else? check IEEE754 diff --git a/lib/Data/IEEE754/Tools.pm b/lib/Data/IEEE754/Tools.pm index e7b1d1e..95f6da1 100644 --- a/lib/Data/IEEE754/Tools.pm +++ b/lib/Data/IEEE754/Tools.pm @@ -5,9 +5,9 @@ use strict; use Carp; use Exporter 'import'; # just use the import() function, without the rest of the overhead of ISA -use version 0.77; our $VERSION = version->declare('0.017_001'); - # use rrr.mmmsss, where rrr is major revision, mmm is EVEN minor revision, and sss is sub-revision - # use rrr.mmm_aaa, where rrr is major revision, mmm is ODD minor revision, and aaa is alpha sub-revision +use version 0.77; our $VERSION = version->declare('0.017_002'); + # use rrr.mmm_aaa, where rrr is major revision, mmm is ODD minor revision, and aaa is alpha sub-revision (for ALPHA code) + # use rrr.mmm, where rrr is major revision, mmm is EVEN minor revision (for releases) =pod @@ -17,11 +17,11 @@ Data::IEEE754::Tools - Various tools for understanding and manipulating the unde =head1 SYNOPSIS - use Data::IEEE754::Tools qw/:floatingpoint :ulp/; + use Data::IEEE754::Tools qw/:convertToCharacter :ulp/; - # return -12.875 as decimal and hexadecimal floating point numbers - to_dec_floatingpoint(-12.875); # -0d1.6093750000000000p+0003 - to_hex_floatingpoint(-12.875); # -0x1.9c00000000000p+0003 + # return -12.875 as decimal and hexadecimal floating point numbers ("convertToCharacter" in IEEE-754 parlance) + convertToDecimalCharacter(-12.875); # -0d1.6093750000000000p+0003 + convertToHexCharacter(-12.875); # -0x1.9c00000000000p+0003 # shows the smallest value you can add or subtract to 16.16 (ulp = "Unit in the Last Place") print ulp( 16.16 ); # 3.5527136788005e-015 @@ -133,7 +133,8 @@ my @EXPORT_RAW754 = qw( hexstr754_from_double binstr754_from_double hexstr754_to_double binstr754_to_double ); -my @EXPORT_FLOATING = qw(to_hex_floatingpoint to_dec_floatingpoint); +my @EXPORT_FLOATING = qw(to_hex_floatingpoint to_dec_floatingpoint); # deprecated +my @EXPORT_CONVERT2CHAR = qw(convertToHexCharacter convertToDecimalCharacter); my @EXPORT_ULP = qw(ulp toggle_ulp nextUp nextDown nextAfter); my @EXPORT_CONST = qw( POS_ZERO @@ -154,16 +155,17 @@ my @EXPORT_INFO = qw(isSignMinus isNormal isFinite isZero isSubnormal class radix totalOrder totalOrderMag compareFloatingValue compareFloatingMag); my @EXPORT_SIGNBIT = qw(copy negate abs copySign isSignMinus); -our @EXPORT_OK = (@EXPORT_FLOATING, @EXPORT_RAW754, @EXPORT_ULP, @EXPORT_CONST, @EXPORT_INFO, @EXPORT_SIGNBIT); +our @EXPORT_OK = (@EXPORT_FLOATING, @EXPORT_CONVERT2CHAR, @EXPORT_RAW754, @EXPORT_ULP, @EXPORT_CONST, @EXPORT_INFO, @EXPORT_SIGNBIT); our %EXPORT_TAGS = ( - floating => [@EXPORT_FLOATING], - floatingpoint => [@EXPORT_FLOATING], - raw754 => [@EXPORT_RAW754], - ulp => [@EXPORT_ULP], - constants => [@EXPORT_CONST], - info => [@EXPORT_INFO], - signbit => [@EXPORT_SIGNBIT], - all => [@EXPORT_OK], + convertToCharacter => [@EXPORT_CONVERT2CHAR], + floating => [@EXPORT_FLOATING], # deprecated + floatingpoint => [@EXPORT_FLOATING], # deprecated + raw754 => [@EXPORT_RAW754], + ulp => [@EXPORT_ULP], + constants => [@EXPORT_CONST], + info => [@EXPORT_INFO], + signbit => [@EXPORT_SIGNBIT], + all => [@EXPORT_OK], ); =head2 :raw754 @@ -196,10 +198,10 @@ by zero or the logarithm of a zero or negative value) (NaN). The final thirteen nibbles are the encoding of the fractional value (usually C<1 + thirteennibbles / 16**13>, unless it's zero, denormal, infinite, or not a number). -Of course, this is easier to decode using the L function, which interprets +Of course, this is easier to decode using the L function, which interprets the sign, fraction, and exponent for you. (See below for more details.) - to_dec_floatingpoint(12.875); # +0d1.6093750000000000p+0003 + convertToDecimalString(12.875); # +0d1.6093750000000000p+0003 # ^ ^^^^^^^^^^^^^^^^^^ ^^^^ # : : : # : `- coefficient `- exponent (power of 2) @@ -276,24 +278,24 @@ if( $] lt '5.010' ) { *arr2x32b_from_double = sub { return unpack('N2' => pack 'd>' => shift); }; } -=head2 :floatingpoint +=head2 :convertToCharacter -=head3 to_hex_floatingpoint( I ) +=head3 convertToHexCharacter( I ) -=head3 to_dec_floatingpoint( I ) +=head3 convertToDecimalCharacter( I ) Converts value to a hexadecimal or decimal floating-point notation that indicates the sign and the coefficient and the power of two, with the coefficient either in hexadecimal or decimal notation. - to_hex_floatingpoint(-3.9999999999999996) # -0x1.fffffffffffffp+0001 - to_dec_floatingpoint(-3.9999999999999996) # -0d1.9999999999999998p+0001 + convertToHexCharacter(-3.9999999999999996) # -0x1.fffffffffffffp+0001 + convertToDecimalCharacter(-3.9999999999999996) # -0d1.9999999999999998p+0001 It displays the value as (sign)(0base)(implied).(fraction)p(exponent): =cut -sub to_hex_floatingpoint { +sub binary64_convertToHexCharacter { # thanks to BrowserUK @ http://perlmonks.org/?node_id=1167146 for slighly better decision factors # I tweaked it to use the two 32bit words instead of one 64bit word (which wouldn't work on some systems) my $v = shift; @@ -314,9 +316,13 @@ sub to_hex_floatingpoint { } sprintf '%s0x%1u.%13.13sp%+05d', $sign, $implied, $mant, $exp; } +*convertToHexCharacter = \*binary64_convertToHexCharacter; +*to_hex_floatingpoint = \*convertToHexCharacter; + # TODO = update POD and @EXPORT* to use the canonical-based names + # TODO: switch($Config{nvsize}) { 4 => \*binary32_convertToDecimalCharacter, 8 => \*binary64, 16 => \*binary128} -sub to_dec_floatingpoint { - # based on to_hex_floatingpoint +sub binary64_convertToDecimalCharacter { + # derived from binary64_convertToHexCharacter my $v = shift; my ($msb,$lsb) = arr2x32b_from_double($v); my $sbit = ($msb & 0x80000000) >> 31; @@ -338,6 +344,9 @@ sub to_dec_floatingpoint { my $other = abs($v) / (2.0**$exp); sprintf '%s0d%.16fp%+05d', $sign, $other, $exp; } +*convertToDecimalCharacter = \*binary64_convertToDecimalCharacter; +*to_dec_floatingpoint = \*convertToDecimalCharacter; + # TODO = same as above =over @@ -378,12 +387,15 @@ The I is the power of 2. Is is always a decimal number, whether the c The I can range from -1022 to +1023. Internally, the IEEE 754 representation uses the encoding of -1023 for zero and denormals; to -aid in understanding the actual number, the C conversions represent +aid in understanding the actual number, the C<:convertToCharacter> conversions represent them as +0000 for zero, and -1022 for denormals: since denormals are C<(0+fraction)*(2**min_exp)>, they are really multiples of 2**-1022, not 2**-1023. =back +For backward compatibility, if you use the older tag C<:floatingpoint>, you can refer to these +functions as C and C. + =head2 :constants These can be useful as references for the specialty values, and include the positive and negative @@ -695,7 +707,7 @@ function is meaningful in your implementation of perl. =cut sub isSignalingConvertedToQuiet { - !isSignaling( POS_SNAN_FIRST ) || 0 # v0.013 coverage note: ignore Devel::Cover failures on this line + !isSignaling( POS_SNAN_FIRST ) || 0 # v0.013 coverage note: ignore Devel::Cover failures on this line -- will be only LEFT on quiet systems vs. only RIGHT on signaling systems } =head3 isCanonical( I ) @@ -731,7 +743,7 @@ Returns the "class" of the I: =cut sub class { - return 'signalingNaN' if isSignaling($_[0]); # v0.013 coverage note: ignore Devel::Cover failures on this line (won't return on systems that quiet SNaNs + return 'signalingNaN' if isSignaling($_[0]); # v0.013 coverage note: ignore Devel::Cover failures on this line (won't return on systems that quiet SNaNs) return 'quietNaN' if isNaN($_[0]); return 'negativeInfinity' if isInfinite($_[0]) && isSignMinus($_[0]); return 'negativeNormal' if isNormal($_[0]) && isSignMinus($_[0]); diff --git a/t/02-floatingpoint.t b/t/02-floatingpoint.t index 3585e45..29d9c76 100644 --- a/t/02-floatingpoint.t +++ b/t/02-floatingpoint.t @@ -1,14 +1,14 @@ ######################################################################## # Verifies the following functions: -# :floatingpoint -# to_hex_floatingpoint(v) -# to_dec_floatingpoint(v) +# :convertToCharacter +# convertToHexCharacter(v) +# convertToDecimalCharacter(v) ######################################################################## use 5.006; use warnings; use strict; use Test::More; -use Data::IEEE754::Tools qw/:raw754 :floatingpoint/; +use Data::IEEE754::Tools qw/:raw754 :convertToCharacter/; sub fptest { local $\ = "\n"; @@ -17,11 +17,11 @@ sub fptest { my ($got, $exp, $name); $exp = quotemeta( $h->{exp_hex} ); $exp =~ s/SNAN/[SQ]NAN/; - like( $got = to_hex_floatingpoint($val), qr/$exp/, $name = sprintf('to_hex_floatingpoint(ieee754(%-16.16s) = %-+24.16e)', $h->{src}, $val) ); + like( $got = convertToHexCharacter($val), qr/$exp/, $name = sprintf('convertToHexCharacter(ieee754(%-16.16s) = %-+24.16e)', $h->{src}, $val) ); print( "$name() = $got" ); $exp = quotemeta( $h->{exp_dec} ); $exp =~ s/SNAN/[SQ]NAN/; - like( $got = to_dec_floatingpoint($val), qr/$exp/, $name = sprintf('to_dec_floatingpoint(ieee754(%-16.16s) = %-+24.16e)', $h->{src}, $val) ); + like( $got = convertToDecimalCharacter($val), qr/$exp/, $name = sprintf('convertToDecimalCharacter(ieee754(%-16.16s) = %-+24.16e)', $h->{src}, $val) ); print( "$name() = $got" ); } diff --git a/t/03-ulp.t b/t/03-ulp.t index a0206ca..9d7c06a 100644 --- a/t/03-ulp.t +++ b/t/03-ulp.t @@ -3,13 +3,13 @@ # :ulp # ulp(v) # toggle_ulp(v) -# remaining :ulp features in next test(s) +# -remaining :ulp features in next test(s) ######################################################################## use 5.006; use warnings; use strict; use Test::More; -use Data::IEEE754::Tools qw/:raw754 :ulp :floatingpoint/; +use Data::IEEE754::Tools qw/:raw754 :ulp/; my ($h,$u,$v); @@ -45,9 +45,9 @@ sub fntest { unless($r) { diag ''; diag "$n:"; - diag sprintf "ORIGINAL: hex(%-30s) = %s", to_dec_floatingpoint($v), $h; - diag sprintf "EXPECT: hex(%-30s) = %s", to_dec_floatingpoint($x), hexstr754_from_double($x); - diag sprintf "ANSWER: hex(%-30s) = %s", to_dec_floatingpoint($u), hexstr754_from_double($u); + diag sprintf "ORIGINAL: hex(%-30s) = %s", convertToDecimalCharacter($v), $h; + diag sprintf "EXPECT: hex(%-30s) = %s", convertToDecimalCharacter($x), hexstr754_from_double($x); + diag sprintf "ANSWER: hex(%-30s) = %s", convertToDecimalCharacter($u), hexstr754_from_double($u); diag ''; } note '-'x80; diff --git a/t/04-nextupdown.t b/t/04-nextupdown.t index f9b51b1..bcb3d68 100644 --- a/t/04-nextupdown.t +++ b/t/04-nextupdown.t @@ -9,7 +9,7 @@ use 5.006; use warnings; use strict; use Test::More; -use Data::IEEE754::Tools qw/:raw754 :ulp :floatingpoint/; +use Data::IEEE754::Tools qw/:raw754 :ulp :convertToCharacter/; my ($h,$u,$v); @@ -45,17 +45,17 @@ sub fntest { unless($r) { diag ''; diag "$n:"; - diag sprintf "ORIGINAL: hex(%-30s) = %s", to_dec_floatingpoint($v), $h; - diag sprintf "EXPECT: hex(%-30s) = %s", to_dec_floatingpoint($x), hexstr754_from_double($x); - diag sprintf "ANSWER: hex(%-30s) = %s", to_dec_floatingpoint($u), hexstr754_from_double($u); + diag sprintf "ORIGINAL: hex(%-30s) = %s", convertToDecimalCharacter($v), $h; + diag sprintf "EXPECT: hex(%-30s) = %s", convertToDecimalCharacter($x), hexstr754_from_double($x); + diag sprintf "ANSWER: hex(%-30s) = %s", convertToDecimalCharacter($u), hexstr754_from_double($u); diag ''; SWITCHFUNCTION: foreach ($fn) { my $val = /^nextDown$/ ? - $v : $v; # choose nextUp or nextDown if( $val != $val ) { # NAN - diag( "DEBUG($fn): IS NAN\t" . to_dec_floatingpoint($val) ); + diag( "DEBUG($fn): IS NAN\t" . convertToDecimalCharacter($val) ); last SWITCHFUNCTION; } else { - diag( "DEBUG($fn): ISN'T NAN\t" . to_dec_floatingpoint($val) ); + diag( "DEBUG($fn): ISN'T NAN\t" . convertToDecimalCharacter($val) ); } my $h754 = hexstr754_from_double($val); diag( "DEBUG($fn): h754 = $h754" ); @@ -79,8 +79,8 @@ sub fntest { $lsb &= 0xFFFFFFFF; # v0.011_001: potential bugfix: ensure 32bit MSB diag( "DEBUG($fn): MASKED msb,lsb = $msb,$lsb" ); diag( "DEBUG($fn): FINAL HEXSTR = " .sprintf('%08X%08X', $msb, $lsb )); - diag( "DEBUG($fn): FINAL DOUBLE = " .to_dec_floatingpoint(hexstr754_to_double( sprintf '%08X%08X', $msb, $lsb ))); - diag( "DEBUG($fn): FINAL NEG DOUBLE = " .to_dec_floatingpoint(-hexstr754_to_double( sprintf '%08X%08X', $msb, $lsb ))) + diag( "DEBUG($fn): FINAL DOUBLE = " .convertToDecimalCharacter(hexstr754_to_double( sprintf '%08X%08X', $msb, $lsb ))); + diag( "DEBUG($fn): FINAL NEG DOUBLE = " .convertToDecimalCharacter(-hexstr754_to_double( sprintf '%08X%08X', $msb, $lsb ))) if (/^nextDown$/); last SWITCHFUNCTION; } diff --git a/t/06-constants.t b/t/06-constants.t index 1078cf5..5265d6a 100644 --- a/t/06-constants.t +++ b/t/06-constants.t @@ -1,6 +1,11 @@ ######################################################################## # Verifies the various constant double-float values: # :constants +# +# :floatingpoint: verifies the old naming convention still works +# to_hex_floatingpoint(v) +# to_dec_floatingpoint(v) +# - see 02-floatingpoint.t for new naming ######################################################################## use 5.006; use warnings; @@ -32,13 +37,16 @@ push @tests, [ NEG_IND (), hexstr754_to_double('FFF'.'8000000000000') push @tests, [ NEG_QNAN_FIRST (), hexstr754_to_double('FFF'.'8000000000001') , 'NEG_QNAN_FIRST ']; push @tests, [ NEG_QNAN_LAST (), hexstr754_to_double('FFF'.'FFFFFFFFFFFFF') , 'NEG_QNAN_LAST ']; -plan tests => scalar @tests; +plan tests => 2 * scalar @tests; foreach (@tests) { my ($c, $x, $n) = @$_; my $got = to_hex_floatingpoint $c; my $exp = to_hex_floatingpoint $x; - is( $got , $exp , "const: $n" ); + is( $got , $exp , "const: $n [w/ to_hex_floatingpoint()]" ); + $got = to_dec_floatingpoint $c; + $exp = to_dec_floatingpoint $x; + is( $got , $exp , "const: $n [w/ to_dec_floatingpoint()]" ); } exit; \ No newline at end of file diff --git a/t/09-signbit.t b/t/09-signbit.t index 3d7f7cf..9ae6d66 100644 --- a/t/09-signbit.t +++ b/t/09-signbit.t @@ -11,7 +11,7 @@ use 5.006; use warnings; use strict; use Test::More; -use Data::IEEE754::Tools qw/:raw754 :floatingpoint :constants :signbit/; +use Data::IEEE754::Tools qw/:raw754 :convertToCharacter :constants :signbit/; my @tests = (); # [CONSTANT , 'NAME ', CONSTANT , negate() , abs() ]; @@ -50,7 +50,7 @@ foreach my $t ( @tests ) { my $xi = $x[$i]; my $f = \&{$fn}; is( ($f->($c)), ($xi), sprintf('%-20.20s(%-20.20s)', $fn, $name ) ); - is( to_hex_floatingpoint($f->($c)), to_hex_floatingpoint($xi), sprintf('%-20.20s(%-20.20s)', $fn, $name ) ); + is( convertToHexCharacter($f->($c)), convertToHexCharacter($xi), sprintf('%-20.20s(%-20.20s)', $fn, $name ) ); } } diff --git a/t/10-copysign.t b/t/10-copysign.t index 529f6dd..c1acde1 100644 --- a/t/10-copysign.t +++ b/t/10-copysign.t @@ -8,7 +8,7 @@ use 5.006; use warnings; use strict; use Test::More; -use Data::IEEE754::Tools qw/:raw754 :floatingpoint :constants :info :signbit/; +use Data::IEEE754::Tools qw/:raw754 :convertToCharacter :constants :info :signbit/; my @constants = ( NEG_QNAN_LAST , @@ -44,11 +44,11 @@ foreach my $x (@constants) { my $z = copySign($x, $y); my $zsign = isSignMinus($z); - - my $pre = sprintf('copySign(%-25.25s,%-25.25s): ', to_hex_floatingpoint($x), to_hex_floatingpoint($y)); + + my $pre = sprintf('copySign(%-25.25s,%-25.25s): ', convertToHexCharacter($x), convertToHexCharacter($y)); is( $zsign , $ysign , $pre . 'sign compare' ); - is( to_hex_floatingpoint(abs($z)), to_hex_floatingpoint(abs($x)), $pre . 'abs compare' ); + is( convertToHexCharacter(abs($z)), convertToHexCharacter(abs($x)), $pre . 'abs compare' ); } } From f3e5fddaf24da63a08f21914568384cc05ddbd97 Mon Sep 17 00:00:00 2001 From: PeterCJ Date: Fri, 24 Mar 2017 08:52:59 -0700 Subject: [PATCH 2/8] v0.017_002: function-alias dispatch mechanism (not part of the standard naming (issue#6), really part of extending to alternate bitness (issue#7), but I had the idea for the dispatch table, so wanted to get it roughed in) --- Makefile.PL | 1 + lib/Data/IEEE754/Tools.pm | 30 +++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index a32ce41..2420843 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -13,6 +13,7 @@ use 5.006; 'warnings' => 0, 'strict' => 0, 'Carp' => 0, + 'Config' => 0, }, ); diff --git a/lib/Data/IEEE754/Tools.pm b/lib/Data/IEEE754/Tools.pm index 95f6da1..35ce85d 100644 --- a/lib/Data/IEEE754/Tools.pm +++ b/lib/Data/IEEE754/Tools.pm @@ -4,6 +4,7 @@ use warnings; use strict; use Carp; use Exporter 'import'; # just use the import() function, without the rest of the overhead of ISA +use Config; use version 0.77; our $VERSION = version->declare('0.017_002'); # use rrr.mmm_aaa, where rrr is major revision, mmm is ODD minor revision, and aaa is alpha sub-revision (for ALPHA code) @@ -317,9 +318,26 @@ sub binary64_convertToHexCharacter { sprintf '%s0x%1u.%13.13sp%+05d', $sign, $implied, $mant, $exp; } *convertToHexCharacter = \*binary64_convertToHexCharacter; +my $__glue_dispatch; # issue#7 TODO +if(0) { # issue#7 TODO + $__glue_dispatch = sub { # only use this subref in the glue code, not in any subroutine + my ($arg, %h) = @_; + croak sprintf "\n\n%s %s configuration error: could not determine the right function for your system.\n" + ."Please report a bug in %s.DISPATCH_TABLE#%d('%s').\n" + ."It would be helpful to include the output of perl -V in the bug report\n" + ."\n", + __PACKAGE__, $VERSION, $VERSION, (caller)[2], defined $arg ? $arg : '' + unless exists $h{$arg}; + return $h{$arg}; + }; + + *convertToHexCharacter = $__glue_dispatch->( $Config{nvsize}, + 4 => \*binary32_convertToHexCharacter, + 8 => \*binary64_convertToHexCharacter, + 16 => \*binary128_convertToHexCharacter, + ); +} *to_hex_floatingpoint = \*convertToHexCharacter; - # TODO = update POD and @EXPORT* to use the canonical-based names - # TODO: switch($Config{nvsize}) { 4 => \*binary32_convertToDecimalCharacter, 8 => \*binary64, 16 => \*binary128} sub binary64_convertToDecimalCharacter { # derived from binary64_convertToHexCharacter @@ -345,8 +363,14 @@ sub binary64_convertToDecimalCharacter { sprintf '%s0d%.16fp%+05d', $sign, $other, $exp; } *convertToDecimalCharacter = \*binary64_convertToDecimalCharacter; +if(0) { # issue#7 TODO + *convertToDecimalCharacter = $__glue_dispatch->( $Config{nvsize}, + 4 => \*binary32_convertToDecimalCharacter, + 8 => \*binary64_convertToDecimalCharacter, + 16 => \*binary128_convertToDecimalCharacter, + ); +} *to_dec_floatingpoint = \*convertToDecimalCharacter; - # TODO = same as above =over From f05ee60893f627f397f45758216412309311ee44 Mon Sep 17 00:00:00 2001 From: PeterCJ Date: Fri, 24 Mar 2017 09:12:13 -0700 Subject: [PATCH 3/8] v0.017_002: refuse to compile with unknown endianness; add better error messages --- CHANGES | 3 +++ lib/Data/IEEE754/Tools.pm | 22 ++++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 09ad31a..ea9e66d 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,9 @@ v0.017 internal development version convention issue#6 - rename :floatingpoint, to_hex_floatingpoint(), to_dec_floatingpoint() to :convertToCharacter, convertToHexCharacter(), convertToDecimalCharacter() + - figured out a framework for issue#7's multiple bitness, but disable + for now + - improve error messages, and stop module compile on mixed-endianness v0.016 2016-Aug-29 - had a bug in v0.014 Makefile which caused CPAN to not diff --git a/lib/Data/IEEE754/Tools.pm b/lib/Data/IEEE754/Tools.pm index 35ce85d..15efc6d 100644 --- a/lib/Data/IEEE754/Tools.pm +++ b/lib/Data/IEEE754/Tools.pm @@ -263,11 +263,15 @@ if( $] lt '5.010' ) { *arr2x32b_from_double = sub { return unpack('N2' => pack 'd' => shift); }; } else { # I don't handle middle-endian / mixed-endian; sorry - *hexstr754_from_double = sub { undef }; - *binstr754_from_double = sub { undef }; - - *hexstr754_to_double = sub { undef }; - *binstr754_to_double = sub { undef }; + croak sprintf "\n\n%s %s configuration error:\n" + ."\tCannot understand your system's endianness.\n" + ."\tPlease report a bug in %s.ENDIAN#%d('%s'),\n" + ."\tand include your machine's output of perl -V.\n" + ."\tAlso, let me know if you're willing to run test\n" + ."\tversions on your machine, to help me debug.\n" + ."\tThanks.\n" + ."\n", + __PACKAGE__, $VERSION, $VERSION, (caller)[2], defined $str ? $str : ''; } } else { *hexstr754_from_double = sub { return uc unpack('H*' => pack 'd>' => shift); }; @@ -322,9 +326,11 @@ my $__glue_dispatch; # issue#7 TODO if(0) { # issue#7 TODO $__glue_dispatch = sub { # only use this subref in the glue code, not in any subroutine my ($arg, %h) = @_; - croak sprintf "\n\n%s %s configuration error: could not determine the right function for your system.\n" - ."Please report a bug in %s.DISPATCH_TABLE#%d('%s').\n" - ."It would be helpful to include the output of perl -V in the bug report\n" + croak sprintf "\n\n%s %s configuration error:\n" + ."\tCould not determine the right setup for your system.\n" + ."\tPlease report a bug in %s.DISPATCH_TABLE#%d('%s').\n" + ."\tIt would be helpful to include the output of perl -V\n" + ."\tin the bug report. Thanks.\n" ."\n", __PACKAGE__, $VERSION, $VERSION, (caller)[2], defined $arg ? $arg : '' unless exists $h{$arg}; From e3955d27211b64f78c069802e6d3185dda7076d9 Mon Sep 17 00:00:00 2001 From: PeterCJ Date: Fri, 24 Mar 2017 09:31:06 -0700 Subject: [PATCH 4/8] v0.017_002: update POD for the INTERFACE NOT YET STABLE; noticed that POD above specifically says that while test suite may fail, a smaller {nvsize} might still be usable, so revert to just warning the user -- TODO = determine a way to turn off the endianness carp --- lib/Data/IEEE754/Tools.pm | 50 ++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/lib/Data/IEEE754/Tools.pm b/lib/Data/IEEE754/Tools.pm index 15efc6d..db03771 100644 --- a/lib/Data/IEEE754/Tools.pm +++ b/lib/Data/IEEE754/Tools.pm @@ -114,15 +114,47 @@ a transition to v2. =over -=item v0.013_003: C renamed to C +=item * v0.013_003 -=item v0.013_003: C renamed to C +=over + +=item * C renamed to C + +=item * C renamed to C + +=item * C renamed to C + +=back + +=item * v0.013_008 -=item v0.013_003: C renamed to C +=over + +=item * C renamed to C, and noted that perl's builtin can be accessed via C -=item v0.013_008: C renamed to C, and noted that perl's builtin can be accessed via C +=back -=item v0.14001: messed up version numbering convention when I get to 1.000, it will be reset to decimal-based. +=item * v0.14001 + +=over + +=item * messed up version numbering convention when I get to 1.000, it will be reset to decimal-based. + +=back + +=item * v0.017_002 + +=over + +=item * C<:floatingpoint> renamed to C<:convertToCharacter> + +=item * C renamed to C + +=item * C renamed to C + +=back + +For backward compatibility, the old names are available, but the new names are recommended. =back @@ -263,7 +295,7 @@ if( $] lt '5.010' ) { *arr2x32b_from_double = sub { return unpack('N2' => pack 'd' => shift); }; } else { # I don't handle middle-endian / mixed-endian; sorry - croak sprintf "\n\n%s %s configuration error:\n" + carp sprintf "\n\n%s %s configuration error:\n" ."\tCannot understand your system's endianness.\n" ."\tPlease report a bug in %s.ENDIAN#%d('%s'),\n" ."\tand include your machine's output of perl -V.\n" @@ -272,6 +304,12 @@ if( $] lt '5.010' ) { ."\tThanks.\n" ."\n", __PACKAGE__, $VERSION, $VERSION, (caller)[2], defined $str ? $str : ''; + + *hexstr754_from_double = sub { 'UNKNOWN ENDIANNESS' }; + *binstr754_from_double = sub { 'UNKNOWN ENDIANNESS' }; + + *hexstr754_to_double = sub { undef }; + *binstr754_to_double = sub { undef }; } } else { *hexstr754_from_double = sub { return uc unpack('H*' => pack 'd>' => shift); }; From 5d7167ce60308ac7628aef7ce3cc01360203b632 Mon Sep 17 00:00:00 2001 From: PeterCJ Date: Fri, 24 Mar 2017 10:33:52 -0700 Subject: [PATCH 5/8] v0.017_002: renaming the xxxstr754_xxx_double to be compatible with issue#7, while still trying to decide on canonical camelCase name for hexstr754_from_double and similar, per issue#6 --- CHANGES | 2 +- lib/Data/IEEE754/Tools.pm | 70 ++++++++++++++++++++++++++------------- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/CHANGES b/CHANGES index ea9e66d..917d803 100644 --- a/CHANGES +++ b/CHANGES @@ -16,7 +16,7 @@ v0.016 2016-Aug-29 index; tried a couple of submissions, none of which really did what I wanted. Will try to move up to next public release version number (v0.016), and ask PAUSE - to forget the incorrect v0.14001.0 release, and hopefully + to forget the incorrect v0.14003.0 release, and hopefully re-index to this release. v0.014 2016-Aug-29 diff --git a/lib/Data/IEEE754/Tools.pm b/lib/Data/IEEE754/Tools.pm index db03771..a5c3e63 100644 --- a/lib/Data/IEEE754/Tools.pm +++ b/lib/Data/IEEE754/Tools.pm @@ -138,7 +138,7 @@ a transition to v2. =over -=item * messed up version numbering convention when I get to 1.000, it will be reset to decimal-based. +=item * messed up version numbering convention. Fixed at v0.016. =back @@ -273,26 +273,35 @@ of the IEEE754 double value, and converts it back to a perl floating-point value 12.875 =cut + +my ($_helper64_arr2x32b,$_helper128_arr4x32b); + # Perl 5.10 introduced the ">" and "<" modifiers for pack which can be used to # force a specific endianness. if( $] lt '5.010' ) { my $str = join('', unpack("H*", pack 'L' => 0x12345678)); if('78563412' eq $str) { # little endian, so reverse byteorder - *hexstr754_from_double = sub { return uc unpack('H*' => reverse pack 'd' => shift); }; - *binstr754_from_double = sub { return uc unpack('B*' => reverse pack 'd' => shift); }; + *binary64_hexstr754_from_double = sub { return uc unpack('H*' => reverse pack 'd' => shift); }; + *binary64_binstr754_from_double = sub { return uc unpack('B*' => reverse pack 'd' => shift); }; - *hexstr754_to_double = sub { return unpack('d' => reverse pack 'H*' => shift); }; - *binstr754_to_double = sub { return unpack('d' => reverse pack 'B*' => shift); }; + *binary64_hexstr754_to_double = sub { return unpack('d' => reverse pack 'H*' => shift); }; + *binary64_binstr754_to_double = sub { return unpack('d' => reverse pack 'B*' => shift); }; - *arr2x32b_from_double = sub { return unpack('N2' => reverse pack 'd' => shift); }; + $_helper64_arr2x32b = sub { return unpack('N2' => reverse pack 'd' => shift); }; + $_helper128_arr4x32b = ($Config{d_longdbl}) + ? sub { return unpack('N4' => reverse pack 'D' => shift); } # long doubles are a "thing" + : sub { undef }; # else don't know how to do this } elsif('12345678' eq $str) { # big endian, so keep default byteorder - *hexstr754_from_double = sub { return uc unpack('H*' => pack 'd' => shift); }; - *binstr754_from_double = sub { return uc unpack('B*' => pack 'd' => shift); }; + *binary64_hexstr754_from_double = sub { return uc unpack('H*' => pack 'd' => shift); }; + *binary64_binstr754_from_double = sub { return uc unpack('B*' => pack 'd' => shift); }; - *hexstr754_to_double = sub { return unpack('d' => pack 'H*' => shift); }; - *binstr754_to_double = sub { return unpack('d' => pack 'B*' => shift); }; + *binary64_hexstr754_to_double = sub { return unpack('d' => pack 'H*' => shift); }; + *binary64_binstr754_to_double = sub { return unpack('d' => pack 'B*' => shift); }; - *arr2x32b_from_double = sub { return unpack('N2' => pack 'd' => shift); }; + $_helper64_arr2x32b = sub { return unpack('N2' => pack 'd' => shift); }; + $_helper128_arr4x32b = ($Config{d_longdbl}) + ? sub { return unpack('N4' => pack 'D' => shift); } # long doubles are a "thing" + : sub { undef }; # else don't know how to do this } else { # I don't handle middle-endian / mixed-endian; sorry carp sprintf "\n\n%s %s configuration error:\n" @@ -305,22 +314,37 @@ if( $] lt '5.010' ) { ."\n", __PACKAGE__, $VERSION, $VERSION, (caller)[2], defined $str ? $str : ''; - *hexstr754_from_double = sub { 'UNKNOWN ENDIANNESS' }; - *binstr754_from_double = sub { 'UNKNOWN ENDIANNESS' }; + *binary64_hexstr754_from_double = sub { 'UNKNOWN ENDIANNESS' }; + *binary64_binstr754_from_double = sub { 'UNKNOWN ENDIANNESS' }; - *hexstr754_to_double = sub { undef }; - *binstr754_to_double = sub { undef }; + *binary64_hexstr754_to_double = sub { undef }; + *binary64_binstr754_to_double = sub { undef }; + $_helper64_arr2x32b = sub { undef }; + $_helper128_arr4x32b = sub { undef }; } } else { - *hexstr754_from_double = sub { return uc unpack('H*' => pack 'd>' => shift); }; - *binstr754_from_double = sub { return uc unpack('B*' => pack 'd>' => shift); }; + *binary64_hexstr754_from_double = sub { return uc unpack('H*' => pack 'd>' => shift); }; + *binary64_binstr754_from_double = sub { return uc unpack('B*' => pack 'd>' => shift); }; - *hexstr754_to_double = sub { return unpack('d>' => pack 'H*' => shift); }; - *binstr754_to_double = sub { return unpack('d>' => pack 'B*' => shift); }; + *binary64_hexstr754_to_double = sub { return unpack('d>' => pack 'H*' => shift); }; + *binary64_binstr754_to_double = sub { return unpack('d>' => pack 'B*' => shift); }; - *arr2x32b_from_double = sub { return unpack('N2' => pack 'd>' => shift); }; + $_helper64_arr2x32b = sub { return unpack('N2' => pack 'd>' => shift); }; + $_helper128_arr4x32b = sub { return unpack('N4' => pack 'D>' => shift); }; } +# TODO: issue#6: still trying to determine canonical camelCase name: +# ? _ieee754stringBinaryFromFloat, _ieee754stringBinaryToFloat, _ieee754stringHexFromFloat, _ieee754stringHexToFloat +# ? _binaryStringFromFloat, _binaryStringToFloat, _hexStringFromFloat, _hexStringToFloat +# ? str754__ (ie, stay almost the same as now) +# ? _Binary754string, _Hex754string; generic = float_754string +# ? _from/toInternalString; generic = float_InternalString +*hexstr754_from_double = \*binary64_hexstr754_from_double; +*binstr754_from_double = \*binary64_binstr754_from_double; +*hexstr754_to_double = \*binary64_hexstr754_to_double; +*binstr754_to_double = \*binary64_binstr754_to_double; +# TODO: issue#7 switch, per below + =head2 :convertToCharacter =head3 convertToHexCharacter( I ) @@ -342,7 +366,7 @@ sub binary64_convertToHexCharacter { # thanks to BrowserUK @ http://perlmonks.org/?node_id=1167146 for slighly better decision factors # I tweaked it to use the two 32bit words instead of one 64bit word (which wouldn't work on some systems) my $v = shift; - my ($msb,$lsb) = arr2x32b_from_double($v); + my ($msb,$lsb) = $_helper64_arr2x32b->($v); my $sbit = ($msb & 0x80000000) >> 31; my $sign = $sbit ? '-' : '+'; my $exp = (($msb & 0x7FF00000) >> 20) - 1023; @@ -386,7 +410,7 @@ if(0) { # issue#7 TODO sub binary64_convertToDecimalCharacter { # derived from binary64_convertToHexCharacter my $v = shift; - my ($msb,$lsb) = arr2x32b_from_double($v); + my ($msb,$lsb) = $_helper64_arr2x32b->($v); my $sbit = ($msb & 0x80000000) >> 31; my $sign = $sbit ? '-' : '+'; my $exp = (($msb & 0x7FF00000) >> 20) - 1023; @@ -607,7 +631,7 @@ sub nextUp { return $val if $h754 eq '7FF0000000000000'; # return self for +INF return hexstr754_to_double('FFEFFFFFFFFFFFFF') if $h754 eq 'FFF0000000000000'; # return largest negative for -INF return hexstr754_to_double('0000000000000001') if $h754 eq '8000000000000000'; # return +SmallestDenormal for -ZERO - my ($msb,$lsb) = arr2x32b_from_double($val); + my ($msb,$lsb) = $_helper64_arr2x32b->($val); $lsb += ($msb & 0x80000000) ? -1.0 : +1.0; if($lsb == 4_294_967_296.0) { $lsb = 0.0; From a564d3b0ff5d069613bb53b6dcc1a40ba9e1e8d3 Mon Sep 17 00:00:00 2001 From: PeterCJ Date: Fri, 24 Mar 2017 13:02:13 -0700 Subject: [PATCH 6/8] v0.017_002_namingconvention: start test coverage for aliases t\11*.t --- CHANGES | 1 + lib/Data/IEEE754/Tools.pm | 224 ++++++++++++++++++++------------------ t/11-aliases.t | 27 +++++ 3 files changed, 148 insertions(+), 104 deletions(-) create mode 100644 t/11-aliases.t diff --git a/CHANGES b/CHANGES index 917d803..3fbdcee 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,7 @@ v0.017 internal development version - figured out a framework for issue#7's multiple bitness, but disable for now - improve error messages, and stop module compile on mixed-endianness + - add test coverage for aliases v0.016 2016-Aug-29 - had a bug in v0.014 Makefile which caused CPAN to not diff --git a/lib/Data/IEEE754/Tools.pm b/lib/Data/IEEE754/Tools.pm index a5c3e63..408cd9a 100644 --- a/lib/Data/IEEE754/Tools.pm +++ b/lib/Data/IEEE754/Tools.pm @@ -163,9 +163,14 @@ For backward compatibility, the old names are available, but the new names are r =cut my @EXPORT_RAW754 = qw( - hexstr754_from_double binstr754_from_double - hexstr754_to_double binstr754_to_double + hexstr754_from_double hexstr754_to_double + binstr754_from_double binstr754_to_double ); +my @EXPORT_INTERNALS = qw( + convertToInternalHexString convertToInternalBinaryString + convertFromInternalHexString convertFromInternalBinaryString +); + my @EXPORT_FLOATING = qw(to_hex_floatingpoint to_dec_floatingpoint); # deprecated my @EXPORT_CONVERT2CHAR = qw(convertToHexCharacter convertToDecimalCharacter); my @EXPORT_ULP = qw(ulp toggle_ulp nextUp nextDown nextAfter); @@ -188,16 +193,26 @@ my @EXPORT_INFO = qw(isSignMinus isNormal isFinite isZero isSubnormal class radix totalOrder totalOrderMag compareFloatingValue compareFloatingMag); my @EXPORT_SIGNBIT = qw(copy negate abs copySign isSignMinus); -our @EXPORT_OK = (@EXPORT_FLOATING, @EXPORT_CONVERT2CHAR, @EXPORT_RAW754, @EXPORT_ULP, @EXPORT_CONST, @EXPORT_INFO, @EXPORT_SIGNBIT); +my @EXPORT_BINARY64 = qw( + binary64_convertToInternalHexString + binary64_convertFromInternalHexString + binary64_convertToInternalBinaryString + binary64_convertFromInternalBinaryString +); + +our @EXPORT = (); +our @EXPORT_OK = (@EXPORT_FLOATING, @EXPORT_CONVERT2CHAR, @EXPORT_RAW754, @EXPORT_INTERNALS, @EXPORT_ULP, @EXPORT_CONST, @EXPORT_INFO, @EXPORT_SIGNBIT, @EXPORT_BINARY64); our %EXPORT_TAGS = ( convertToCharacter => [@EXPORT_CONVERT2CHAR], floating => [@EXPORT_FLOATING], # deprecated floatingpoint => [@EXPORT_FLOATING], # deprecated - raw754 => [@EXPORT_RAW754], + internalstring => [@EXPORT_INTERNALS], + raw754 => [@EXPORT_RAW754], # deprecated ulp => [@EXPORT_ULP], constants => [@EXPORT_CONST], info => [@EXPORT_INFO], signbit => [@EXPORT_SIGNBIT], + binary64 => [@EXPORT_BINARY64], all => [@EXPORT_OK], ); @@ -206,12 +221,12 @@ our %EXPORT_TAGS = ( These are the functions to do raw conversion from a floating-point value to a hexadecimal or binary string of the underlying IEEE754 encoded value, and back. -=head3 hexstr754_from_double( I ) +=head3 binary64_convertToInternalHexString( I ) Converts the floating-point I into a big-endian hexadecimal representation of the underlying IEEE754 encoding. - hexstr754_from_double(12.875); # 4029C00000000000 + binary64_convertToInternalHexString(12.875); # 4029C00000000000 # ^^^ # : ^^^^^^^^^^^^^ # : : @@ -241,12 +256,12 @@ the sign, fraction, and exponent for you. (See below for more details.) # : # `- sign -=head3 binstr754_from_double( I ) +=head3 binary64_convertToInternalBinaryString( I ) Converts the floating-point I into a big-endian binary representation of the underlying IEEE754 encoding. - binstr754_from_double(12.875); # 0100000000101001110000000000000000000000000000000000000000000000 + binary64_convertToInternalBinaryString(12.875); # 0100000000101001110000000000000000000000000000000000000000000000 # ^ # `- sign # ^^^^^^^^^^^ @@ -256,20 +271,20 @@ IEEE754 encoding. The first bit is the sign, the next 11 are the exponent's encoding -=head3 hexstr754_to_double( I ) +=head3 binary64_convertFromInternalHexString( I ) -The inverse of C: it takes a string representing the 16 nibbles +The inverse of C: it takes a string representing the 16 nibbles of the IEEE754 double value, and converts it back to a perl floating-point value. - print hexstr754_to_double('4029C00000000000'); + print binary64_convertFromInternalHexString('4029C00000000000'); 12.875 -=head3 binstr754_to_double( I ) +=head3 binary64_convertFromInternalBinaryString( I ) -The inverse of C: it takes a string representing the 64 bits +The inverse of C: it takes a string representing the 64 bits of the IEEE754 double value, and converts it back to a perl floating-point value. - print binstr754_to_double('0100000000101001110000000000000000000000000000000000000000000000'); + print binary64_convertFromInternalBinaryString('0100000000101001110000000000000000000000000000000000000000000000'); 12.875 =cut @@ -281,27 +296,27 @@ my ($_helper64_arr2x32b,$_helper128_arr4x32b); if( $] lt '5.010' ) { my $str = join('', unpack("H*", pack 'L' => 0x12345678)); if('78563412' eq $str) { # little endian, so reverse byteorder - *binary64_hexstr754_from_double = sub { return uc unpack('H*' => reverse pack 'd' => shift); }; - *binary64_binstr754_from_double = sub { return uc unpack('B*' => reverse pack 'd' => shift); }; + *binary64_convertToInternalHexString = sub { return uc unpack('H*' => reverse pack 'd' => shift); }; + *binary64_convertToInternalBinaryString = sub { return uc unpack('B*' => reverse pack 'd' => shift); }; - *binary64_hexstr754_to_double = sub { return unpack('d' => reverse pack 'H*' => shift); }; - *binary64_binstr754_to_double = sub { return unpack('d' => reverse pack 'B*' => shift); }; + *binary64_convertFromInternalHexString = sub { return unpack('d' => reverse pack 'H*' => shift); }; + *binary64_convertFromInternalBinaryString = sub { return unpack('d' => reverse pack 'B*' => shift); }; - $_helper64_arr2x32b = sub { return unpack('N2' => reverse pack 'd' => shift); }; - $_helper128_arr4x32b = ($Config{d_longdbl}) - ? sub { return unpack('N4' => reverse pack 'D' => shift); } # long doubles are a "thing" - : sub { undef }; # else don't know how to do this + $_helper64_arr2x32b = sub { return unpack('N2' => reverse pack 'd' => shift); }; + $_helper128_arr4x32b = ($Config{d_longdbl}) + ? sub { return unpack('N4' => reverse pack 'D' => shift); } # long doubles are a "thing" + : sub { undef }; # else don't know how to do this } elsif('12345678' eq $str) { # big endian, so keep default byteorder - *binary64_hexstr754_from_double = sub { return uc unpack('H*' => pack 'd' => shift); }; - *binary64_binstr754_from_double = sub { return uc unpack('B*' => pack 'd' => shift); }; + *binary64_convertToInternalHexString = sub { return uc unpack('H*' => pack 'd' => shift); }; + *binary64_convertToInternalBinaryString = sub { return uc unpack('B*' => pack 'd' => shift); }; - *binary64_hexstr754_to_double = sub { return unpack('d' => pack 'H*' => shift); }; - *binary64_binstr754_to_double = sub { return unpack('d' => pack 'B*' => shift); }; + *binary64_convertFromInternalHexString = sub { return unpack('d' => pack 'H*' => shift); }; + *binary64_convertFromInternalBinaryString = sub { return unpack('d' => pack 'B*' => shift); }; - $_helper64_arr2x32b = sub { return unpack('N2' => pack 'd' => shift); }; - $_helper128_arr4x32b = ($Config{d_longdbl}) - ? sub { return unpack('N4' => pack 'D' => shift); } # long doubles are a "thing" - : sub { undef }; # else don't know how to do this + $_helper64_arr2x32b = sub { return unpack('N2' => pack 'd' => shift); }; + $_helper128_arr4x32b = ($Config{d_longdbl}) + ? sub { return unpack('N4' => pack 'D' => shift); } # long doubles are a "thing" + : sub { undef }; # else don't know how to do this } else { # I don't handle middle-endian / mixed-endian; sorry carp sprintf "\n\n%s %s configuration error:\n" @@ -314,37 +329,38 @@ if( $] lt '5.010' ) { ."\n", __PACKAGE__, $VERSION, $VERSION, (caller)[2], defined $str ? $str : ''; - *binary64_hexstr754_from_double = sub { 'UNKNOWN ENDIANNESS' }; - *binary64_binstr754_from_double = sub { 'UNKNOWN ENDIANNESS' }; + *binary64_convertToInternalHexString = sub { 'UNKNOWN ENDIANNESS' }; + *binary64_convertToInternalBinaryString = sub { 'UNKNOWN ENDIANNESS' }; - *binary64_hexstr754_to_double = sub { undef }; - *binary64_binstr754_to_double = sub { undef }; - $_helper64_arr2x32b = sub { undef }; - $_helper128_arr4x32b = sub { undef }; + *binary64_convertFromInternalHexString = sub { undef }; + *binary64_convertFromInternalBinaryString = sub { undef }; + $_helper64_arr2x32b = sub { undef }; + $_helper128_arr4x32b = sub { undef }; } } else { - *binary64_hexstr754_from_double = sub { return uc unpack('H*' => pack 'd>' => shift); }; - *binary64_binstr754_from_double = sub { return uc unpack('B*' => pack 'd>' => shift); }; + *binary64_convertToInternalHexString = sub { return uc unpack('H*' => pack 'd>' => shift); }; + *binary64_convertToInternalBinaryString = sub { return uc unpack('B*' => pack 'd>' => shift); }; - *binary64_hexstr754_to_double = sub { return unpack('d>' => pack 'H*' => shift); }; - *binary64_binstr754_to_double = sub { return unpack('d>' => pack 'B*' => shift); }; + *binary64_convertFromInternalHexString = sub { return unpack('d>' => pack 'H*' => shift); }; + *binary64_convertFromInternalBinaryString = sub { return unpack('d>' => pack 'B*' => shift); }; - $_helper64_arr2x32b = sub { return unpack('N2' => pack 'd>' => shift); }; - $_helper128_arr4x32b = sub { return unpack('N4' => pack 'D>' => shift); }; + $_helper64_arr2x32b = sub { return unpack('N2' => pack 'd>' => shift); }; + $_helper128_arr4x32b = sub { return unpack('N4' => pack 'D>' => shift); }; } -# TODO: issue#6: still trying to determine canonical camelCase name: -# ? _ieee754stringBinaryFromFloat, _ieee754stringBinaryToFloat, _ieee754stringHexFromFloat, _ieee754stringHexToFloat -# ? _binaryStringFromFloat, _binaryStringToFloat, _hexStringFromFloat, _hexStringToFloat -# ? str754__ (ie, stay almost the same as now) -# ? _Binary754string, _Hex754string; generic = float_754string -# ? _from/toInternalString; generic = float_InternalString -*hexstr754_from_double = \*binary64_hexstr754_from_double; -*binstr754_from_double = \*binary64_binstr754_from_double; -*hexstr754_to_double = \*binary64_hexstr754_to_double; -*binstr754_to_double = \*binary64_binstr754_to_double; +# issue#6: canonical camelCase name, generic versions +*convertToInternalHexString = \&binary64_convertToInternalHexString; +*convertToInternalBinaryString = \&binary64_convertToInternalBinaryString; +*convertFromInternalHexString = \&binary64_convertFromInternalHexString; +*convertFromInternalBinaryString = \&binary64_convertFromInternalBinaryString; # TODO: issue#7 switch, per below +# backward compatibility: +*hexstr754_from_double = \&convertToInternalHexString; +*binstr754_from_double = \&convertToInternalBinaryString; +*hexstr754_to_double = \&convertFromInternalHexString; +*binstr754_to_double = \&convertFromInternalBinaryString; + =head2 :convertToCharacter =head3 convertToHexCharacter( I ) @@ -523,28 +539,28 @@ zeroes, infinities, a variety of signaling and quiet NAN values. =cut -{ my $local; sub POS_ZERO () { $local = hexstr754_to_double('000'.'0000000000000') unless defined $local; return $local; } } -{ my $local; sub POS_DENORM_SMALLEST() { $local = hexstr754_to_double('000'.'0000000000001') unless defined $local; return $local; } } -{ my $local; sub POS_DENORM_BIGGEST () { $local = hexstr754_to_double('000'.'FFFFFFFFFFFFF') unless defined $local; return $local; } } -{ my $local; sub POS_NORM_SMALLEST () { $local = hexstr754_to_double('001'.'0000000000000') unless defined $local; return $local; } } -{ my $local; sub POS_NORM_BIGGEST () { $local = hexstr754_to_double('7FE'.'FFFFFFFFFFFFF') unless defined $local; return $local; } } -{ my $local; sub POS_INF () { $local = hexstr754_to_double('7FF'.'0000000000000') unless defined $local; return $local; } } -{ my $local; sub POS_SNAN_FIRST () { $local = hexstr754_to_double('7FF'.'0000000000001') unless defined $local; return $local; } } -{ my $local; sub POS_SNAN_LAST () { $local = hexstr754_to_double('7FF'.'7FFFFFFFFFFFF') unless defined $local; return $local; } } -{ my $local; sub POS_IND () { $local = hexstr754_to_double('7FF'.'8000000000000') unless defined $local; return $local; } } -{ my $local; sub POS_QNAN_FIRST () { $local = hexstr754_to_double('7FF'.'8000000000001') unless defined $local; return $local; } } -{ my $local; sub POS_QNAN_LAST () { $local = hexstr754_to_double('7FF'.'FFFFFFFFFFFFF') unless defined $local; return $local; } } -{ my $local; sub NEG_ZERO () { $local = hexstr754_to_double('800'.'0000000000000') unless defined $local; return $local; } } -{ my $local; sub NEG_DENORM_SMALLEST() { $local = hexstr754_to_double('800'.'0000000000001') unless defined $local; return $local; } } -{ my $local; sub NEG_DENORM_BIGGEST () { $local = hexstr754_to_double('800'.'FFFFFFFFFFFFF') unless defined $local; return $local; } } -{ my $local; sub NEG_NORM_SMALLEST () { $local = hexstr754_to_double('801'.'0000000000000') unless defined $local; return $local; } } -{ my $local; sub NEG_NORM_BIGGEST () { $local = hexstr754_to_double('FFE'.'FFFFFFFFFFFFF') unless defined $local; return $local; } } -{ my $local; sub NEG_INF () { $local = hexstr754_to_double('FFF'.'0000000000000') unless defined $local; return $local; } } -{ my $local; sub NEG_SNAN_FIRST () { $local = hexstr754_to_double('FFF'.'0000000000001') unless defined $local; return $local; } } -{ my $local; sub NEG_SNAN_LAST () { $local = hexstr754_to_double('FFF'.'7FFFFFFFFFFFF') unless defined $local; return $local; } } -{ my $local; sub NEG_IND () { $local = hexstr754_to_double('FFF'.'8000000000000') unless defined $local; return $local; } } -{ my $local; sub NEG_QNAN_FIRST () { $local = hexstr754_to_double('FFF'.'8000000000001') unless defined $local; return $local; } } -{ my $local; sub NEG_QNAN_LAST () { $local = hexstr754_to_double('FFF'.'FFFFFFFFFFFFF') unless defined $local; return $local; } } +{ my $local; sub POS_ZERO () { $local = binary64_convertFromInternalHexString('000'.'0000000000000') unless defined $local; return $local; } } +{ my $local; sub POS_DENORM_SMALLEST() { $local = binary64_convertFromInternalHexString('000'.'0000000000001') unless defined $local; return $local; } } +{ my $local; sub POS_DENORM_BIGGEST () { $local = binary64_convertFromInternalHexString('000'.'FFFFFFFFFFFFF') unless defined $local; return $local; } } +{ my $local; sub POS_NORM_SMALLEST () { $local = binary64_convertFromInternalHexString('001'.'0000000000000') unless defined $local; return $local; } } +{ my $local; sub POS_NORM_BIGGEST () { $local = binary64_convertFromInternalHexString('7FE'.'FFFFFFFFFFFFF') unless defined $local; return $local; } } +{ my $local; sub POS_INF () { $local = binary64_convertFromInternalHexString('7FF'.'0000000000000') unless defined $local; return $local; } } +{ my $local; sub POS_SNAN_FIRST () { $local = binary64_convertFromInternalHexString('7FF'.'0000000000001') unless defined $local; return $local; } } +{ my $local; sub POS_SNAN_LAST () { $local = binary64_convertFromInternalHexString('7FF'.'7FFFFFFFFFFFF') unless defined $local; return $local; } } +{ my $local; sub POS_IND () { $local = binary64_convertFromInternalHexString('7FF'.'8000000000000') unless defined $local; return $local; } } +{ my $local; sub POS_QNAN_FIRST () { $local = binary64_convertFromInternalHexString('7FF'.'8000000000001') unless defined $local; return $local; } } +{ my $local; sub POS_QNAN_LAST () { $local = binary64_convertFromInternalHexString('7FF'.'FFFFFFFFFFFFF') unless defined $local; return $local; } } +{ my $local; sub NEG_ZERO () { $local = binary64_convertFromInternalHexString('800'.'0000000000000') unless defined $local; return $local; } } +{ my $local; sub NEG_DENORM_SMALLEST() { $local = binary64_convertFromInternalHexString('800'.'0000000000001') unless defined $local; return $local; } } +{ my $local; sub NEG_DENORM_BIGGEST () { $local = binary64_convertFromInternalHexString('800'.'FFFFFFFFFFFFF') unless defined $local; return $local; } } +{ my $local; sub NEG_NORM_SMALLEST () { $local = binary64_convertFromInternalHexString('801'.'0000000000000') unless defined $local; return $local; } } +{ my $local; sub NEG_NORM_BIGGEST () { $local = binary64_convertFromInternalHexString('FFE'.'FFFFFFFFFFFFF') unless defined $local; return $local; } } +{ my $local; sub NEG_INF () { $local = binary64_convertFromInternalHexString('FFF'.'0000000000000') unless defined $local; return $local; } } +{ my $local; sub NEG_SNAN_FIRST () { $local = binary64_convertFromInternalHexString('FFF'.'0000000000001') unless defined $local; return $local; } } +{ my $local; sub NEG_SNAN_LAST () { $local = binary64_convertFromInternalHexString('FFF'.'7FFFFFFFFFFFF') unless defined $local; return $local; } } +{ my $local; sub NEG_IND () { $local = binary64_convertFromInternalHexString('FFF'.'8000000000000') unless defined $local; return $local; } } +{ my $local; sub NEG_QNAN_FIRST () { $local = binary64_convertFromInternalHexString('FFF'.'8000000000001') unless defined $local; return $local; } } +{ my $local; sub NEG_QNAN_LAST () { $local = binary64_convertFromInternalHexString('FFF'.'FFFFFFFFFFFFF') unless defined $local; return $local; } } =head2 :ulp @@ -569,7 +585,7 @@ my $FIFTYTWOZEROES = sub { '0'x52 }; sub ulp { # ulp_by_div my $val = shift; - my $rawbin = binstr754_from_double($val); + my $rawbin = binary64_convertToInternalBinaryString($val); my ($sgn, $exp, $frac) = ($rawbin =~ /(.)(.{11})(.{52})/); return $val if $exp eq '11111111111'; # return SELF for INF or NAN @@ -578,7 +594,7 @@ sub ulp { # ulp_by_div # this method will multiply by 2**-52 (as a constant) after $sgn = '0'; $frac = $FIFTYTWOZEROES->(); - $val = binstr754_to_double( $sgn . $exp . $frac ); + $val = binary64_convertFromInternalBinaryString( $sgn . $exp . $frac ); $val *= $TWONEG52->(); } @@ -597,7 +613,7 @@ of the way they are handled, C no longer makes sense. sub toggle_ulp { my $val = shift; - my $rawbin = binstr754_from_double($val); + my $rawbin = binary64_convertToInternalBinaryString($val); my ($sign, $exp, $fract) = ($rawbin =~ /(.)(.{11})(.{52})/); # INF and NAN do not have a meaningful ULP; just return SELF @@ -609,7 +625,7 @@ sub toggle_ulp { my $ulp_bit = substr $fract, -1; substr $fract, -1, 1, (1-$ulp_bit); $rawbin = join '', $sign, $exp, $fract; - return binstr754_to_double($rawbin); + return binary64_convertFromInternalBinaryString($rawbin); } =head3 nextUp( I ) @@ -627,10 +643,10 @@ sub nextUp { # thanks again to BrowserUK: http://perlmonks.org/?node_id=1167146 my $val = shift; return $val if $val != $val; # interestingly, NAN != NAN - my $h754 = hexstr754_from_double($val); + my $h754 = binary64_convertToInternalHexString($val); return $val if $h754 eq '7FF0000000000000'; # return self for +INF - return hexstr754_to_double('FFEFFFFFFFFFFFFF') if $h754 eq 'FFF0000000000000'; # return largest negative for -INF - return hexstr754_to_double('0000000000000001') if $h754 eq '8000000000000000'; # return +SmallestDenormal for -ZERO + return binary64_convertFromInternalHexString('FFEFFFFFFFFFFFFF') if $h754 eq 'FFF0000000000000'; # return largest negative for -INF + return binary64_convertFromInternalHexString('0000000000000001') if $h754 eq '8000000000000000'; # return +SmallestDenormal for -ZERO my ($msb,$lsb) = $_helper64_arr2x32b->($val); $lsb += ($msb & 0x80000000) ? -1.0 : +1.0; if($lsb == 4_294_967_296.0) { @@ -642,7 +658,7 @@ sub nextUp { } $msb &= 0xFFFFFFFF; # v0.011_001: bugfix: ensure 32bit MSB $lsb &= 0xFFFFFFFF; # v0.011_001: bugfix: ensure 32bit MSB - return hexstr754_to_double( sprintf '%08X%08X', $msb, $lsb ); + return binary64_convertFromInternalHexString( sprintf '%08X%08X', $msb, $lsb ); } =head3 nextDown( I ) @@ -690,7 +706,7 @@ Returns 1 if I has negative sign (even applies to zeroes and NaNs); other sub isSignMinus { # look at leftmost nibble, and determine whether it has the 8-bit or not (which is the sign bit) - return (hex(substr(hexstr754_from_double(shift),0,1)) & 8) >> 3; + return (hex(substr(binary64_convertToInternalHexString(shift),0,1)) & 8) >> 3; } =head3 isNormal( I ) @@ -701,7 +717,7 @@ Returns 1 if I is a normal number (not zero, subnormal, infinite, or NaN) sub isNormal { # it's normal if the leftmost three nibbles (excluding sign bit) are not 000 or 7FF - my $exp = hex(substr(hexstr754_from_double(shift),0,3)) & 0x7FF; + my $exp = hex(substr(binary64_convertToInternalHexString(shift),0,3)) & 0x7FF; return (0 < $exp) && ($exp < 0x7FF) || 0; } @@ -713,7 +729,7 @@ Returns 1 if I is a finite number (zero, subnormal, or normal; not infini sub isFinite { # it's finite if the leftmost three nibbles (excluding sign bit) are not 7FF - my $exp = hex(substr(hexstr754_from_double(shift),0,3)) & 0x7FF; + my $exp = hex(substr(binary64_convertToInternalHexString(shift),0,3)) & 0x7FF; return ($exp < 0x7FF) || 0; } @@ -725,7 +741,7 @@ Returns 1 if I is positive or negative zero; otherwise, returns 0. sub isZero { # it's zero if it's 0x[80]000000000000000 - my $str = substr(hexstr754_from_double(shift),1,15); + my $str = substr(binary64_convertToInternalHexString(shift),1,15); return ($str eq '0'x15) || 0; } @@ -737,7 +753,7 @@ Returns 1 if I is subnormal (not zero, normal, infinite, nor NaN); otherw sub isSubnormal { # it's subnormal if it's 0x[80]00___ and the last 13 digits are not all zero - my $h = hexstr754_from_double(shift); + my $h = binary64_convertToInternalHexString(shift); my $exp = substr($h,0,3); my $frc = substr($h,3,13); return ($exp eq '000' || $exp eq '800') && ($frc ne '0'x13) || 0; @@ -751,7 +767,7 @@ Returns 1 if I is positive or negative infinity (not zero, subnormal, nor sub isInfinite { # it's infinite if it's 0x[F7]FF_0000000000000 - my $h = hexstr754_from_double(shift); + my $h = binary64_convertToInternalHexString(shift); my $exp = substr($h,0,3); my $frc = substr($h,3,13); return ($exp eq '7FF' || $exp eq 'FFF') && ($frc eq '0'x13) || 0; @@ -765,7 +781,7 @@ Returns 1 if I is NaN (not zero, subnormal, normal, nor infinite); otherw sub isNaN { # it's infinite if it's 0x[F7]FF_0000000000000 - my $h = hexstr754_from_double(shift); + my $h = binary64_convertToInternalHexString(shift); my $exp = substr($h,0,3); my $frc = substr($h,3,13); return ($exp eq '7FF' || $exp eq 'FFF') && ($frc ne '0'x13) || 0; @@ -782,7 +798,7 @@ C might return only 0. sub isSignaling { # it's signaling if isNaN and MSB of fractional portion is 1 - my $h = hexstr754_from_double(shift); + my $h = binary64_convertToInternalHexString(shift); my $exp = substr($h,0,3); my $frc = substr($h,3,13); my $qbit = (0x8 && hex(substr($h,3,1))) >> 3; # 1: quiet, 0: signaling @@ -871,7 +887,7 @@ Special cases are ordered as below: sub totalOrder { my ($x, $y) = @_[0,1]; - my ($bx,$by) = map { binstr754_from_double($_) } $x, $y; # convert to binary strings + my ($bx,$by) = map { binary64_convertToInternalBinaryString($_) } $x, $y; # convert to binary strings my @xsegs = ($bx =~ /(.)(.{11})(.{20})(.{32})/); # split into sign, exponent, MSB, LSB my @ysegs = ($by =~ /(.)(.{11})(.{20})(.{32})/); # split into sign, exponent, MSB, LSB 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 @@ -880,7 +896,7 @@ sub totalOrder { # use a trick: the rules for both-NaN treat it as if it's just another floating point, # so lie about the exponent and do a normal comparison ($bx, $by) = map { $_->[1] = '1' . '0'x10; join '', @$_ } \@xsegs, \@ysegs; - ($x, $y) = map { binstr754_to_double($_) } $bx, $by; + ($x, $y) = map { binary64_convertFromInternalBinaryString($_) } $bx, $by; return (($x <= $y) || 0); } elsif ( $xin ) { # just x NaN: TRUE if x is NEG return ( ($xsegs[0]) || 0 ); @@ -909,8 +925,8 @@ Special cases are ordered as below: sub totalOrderMag { my ($x, $y) = @_[0,1]; - my ($bx,$by) = map { binstr754_from_double($_) } $x, $y; # convert to binary strings - ($x, $y) = map { substr $_, 0, 1, '0'; binstr754_to_double($_) } $bx, $by; # set sign bit to 0, and convert back to number + my ($bx,$by) = map { binary64_convertToInternalBinaryString($_) } $x, $y; # convert to binary strings + ($x, $y) = map { substr $_, 0, 1, '0'; binary64_convertFromInternalBinaryString($_) } $bx, $by; # set sign bit to 0, and convert back to number return totalOrder( $x, $y ); # compare normally } @@ -928,7 +944,7 @@ These are not in IEEE 754-2008, but are included as functions to replace the per sub compareFloatingValue { my ($x, $y) = @_[0,1]; - my ($bx,$by) = map { binstr754_from_double($_) } $x, $y; # convert to binary strings + my ($bx,$by) = map { binary64_convertToInternalBinaryString($_) } $x, $y; # convert to binary strings my @xsegs = ($bx =~ /(.)(.{11})(.{20})(.{32})/); # split into sign, exponent, MSB, LSB my @ysegs = ($by =~ /(.)(.{11})(.{20})(.{32})/); # split into sign, exponent, MSB, LSB 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 @@ -937,7 +953,7 @@ sub compareFloatingValue { # use a trick: the rules for both-NaN treat it as if it's just another floating point, # so lie about the exponent and do a normal comparison ($bx, $by) = map { $_->[1] = '1' . '0'x10; join '', @$_ } \@xsegs, \@ysegs; - ($x, $y) = map { binstr754_to_double($_) } $bx, $by; + ($x, $y) = map { binary64_convertFromInternalBinaryString($_) } $bx, $by; return ($x <=> $y); } elsif ( $xin ) { # just x NaN: if isNaN(x) && isNegative(x) THEN -1 (xy) return ( ($xsegs[0])*-1 || +1 ); @@ -953,8 +969,8 @@ sub compareFloatingValue { sub compareFloatingMag { my ($x, $y) = @_[0,1]; - my ($bx,$by) = map { binstr754_from_double($_) } $x, $y; # convert to binary strings - ($x, $y) = map { substr $_, 0, 1, '0'; binstr754_to_double($_) } $bx, $by; # set sign bit to 0, and convert back to number + my ($bx,$by) = map { binary64_convertToInternalBinaryString($_) } $x, $y; # convert to binary strings + ($x, $y) = map { substr $_, 0, 1, '0'; binary64_convertFromInternalBinaryString($_) } $bx, $by; # set sign bit to 0, and convert back to number return compareFloatingValue( $x, $y ); # compare normally } @@ -987,10 +1003,10 @@ signed zeroes, on infinities, and on NaNs.) =cut sub negate { - my $b = binstr754_from_double(shift); # convert to binary string + my $b = binary64_convertToInternalBinaryString(shift); # convert to binary string my $s = 1 - substr $b, 0, 1; # toggle sign substr $b, 0, 1, $s; # replace sign - return binstr754_to_double($b); # convert to floating-point + return binary64_convertFromInternalBinaryString($b); # convert to floating-point } =head3 abs( I ) @@ -1013,9 +1029,9 @@ the absolute value of a signed NaN), then you may call it as C. =cut sub abs { - my $b = binstr754_from_double(shift); # convert to binary string + my $b = binary64_convertToInternalBinaryString(shift); # convert to binary string substr $b, 0, 1, '0'; # replace sign - return binstr754_to_double($b); # convert to floating-point + return binary64_convertFromInternalBinaryString($b); # convert to floating-point } =head3 copySign( I, I ) @@ -1028,9 +1044,9 @@ Copies the sign from I, but uses the value from I. For example, sub copySign { my ($x, $y) = @_[0,1]; - my ($bx,$by) = map { binstr754_from_double($_) } $x, $y; # convert to binary strings + my ($bx,$by) = map { binary64_convertToInternalBinaryString($_) } $x, $y; # convert to binary strings substr($bx, 0, 1) = substr($by, 0, 1); # copy the sign bit from y to x - return binstr754_to_double($bx); # convert binary-x (with modified sign) back to double + return binary64_convertFromInternalBinaryString($bx); # convert binary-x (with modified sign) back to double } =head3 also exports C I C<)> (see :info) diff --git a/t/11-aliases.t b/t/11-aliases.t new file mode 100644 index 0000000..024ab6b --- /dev/null +++ b/t/11-aliases.t @@ -0,0 +1,27 @@ +######################################################################## +# Verifies aliased functions +######################################################################## +use 5.006; +use warnings; +use strict; +use Test::More; +use Data::IEEE754::Tools qw/:all/; + +# :raw754 +is( \&hexstr754_from_double , \&binary64_convertToInternalHexString , 'alias:hexstr754_from_double' ); +is( \&hexstr754_to_double , \&binary64_convertFromInternalHexString , 'alias:hexstr754_to_double' ); +is( \&binstr754_from_double , \&binary64_convertToInternalBinaryString , 'alias:binstr754_from_double' ); +is( \&binstr754_to_double , \&binary64_convertFromInternalBinaryString , 'alias:binstr754_to_double' ); + +# :internalstring +is( \&convertToInternalHexString , \&binary64_convertToInternalHexString , 'alias:convertToInternalHexString' ); +is( \&convertFromInternalHexString , \&binary64_convertFromInternalHexString , 'alias:convertFromInternalHexString' ); +is( \&convertToInternalBinaryString , \&binary64_convertToInternalBinaryString , 'alias:convertToInternalBinaryString' ); +is( \&convertFromInternalBinaryString , \&binary64_convertFromInternalBinaryString , 'alias:convertFromInternalBinaryString' ); + +done_testing;exit; + +plan tests => 555; + + +exit; From c4f77248cca008ce0ffa4ec04d8df28ab31a3f16 Mon Sep 17 00:00:00 2001 From: PeterCJ Date: Fri, 24 Mar 2017 14:59:08 -0700 Subject: [PATCH 7/8] v0.017_002 (cont): make raw754 etc, aliases to internalString etc; update aliases tests, add tags author-test; rename some of the test files based on the new nomenclature --- CHANGES | 15 +- MANIFEST | 7 +- MANIFEST.SKIP | 3 +- lib/Data/IEEE754/Tools.pm | 88 ++++++---- t/{01-raw754.t => 01-internalstring.t} | 0 t/{02-floatingpoint.t => 02-converttochar.t} | 0 t/03-ulp.t | 3 - t/11-aliases.t | 28 ++- xt/11-tags.t | 173 +++++++++++++++++++ 9 files changed, 263 insertions(+), 54 deletions(-) rename t/{01-raw754.t => 01-internalstring.t} (100%) rename t/{02-floatingpoint.t => 02-converttochar.t} (100%) create mode 100644 xt/11-tags.t diff --git a/CHANGES b/CHANGES index 3fbdcee..37400cb 100644 --- a/CHANGES +++ b/CHANGES @@ -5,12 +5,23 @@ v0.017 internal development version automatic signatures, etc. - v0.017_002_namingconvention: start changing names per the naming- convention issue#6 - - rename :floatingpoint, to_hex_floatingpoint(), to_dec_floatingpoint() - to :convertToCharacter, convertToHexCharacter(), convertToDecimalCharacter() + - make + :floatingpoint, to_hex_floatingpoint(), to_dec_floatingpoint() + aliases to + :convertToCharacter, convertToHexCharacter(), + convertToDecimalCharacter() + - make + :raw754, hexstr754_from_double(), binstr754_from_double(), + hexstr754_to_double(), binstr754_to_double() + aliases to + :internalString, convertToInternalHexString(), + convertToInternalBinaryString(), convertFromInternalHexString(), + convertFromInternalBinaryString() - figured out a framework for issue#7's multiple bitness, but disable for now - improve error messages, and stop module compile on mixed-endianness - add test coverage for aliases + - add author test coverage for import-tags v0.016 2016-Aug-29 - had a bug in v0.014 Makefile which caused CPAN to not diff --git a/MANIFEST b/MANIFEST index 912d2e0..523630a 100644 --- a/MANIFEST +++ b/MANIFEST @@ -4,9 +4,10 @@ Makefile.PL MANIFEST This list of files lib/Data/IEEE754/Tools.pm README +RELEASE.md t/00-load.t -t/01-raw754.t -t/02-floatingpoint.t +t/01-internalstring.t +t/02-converttochar.t t/03-ulp.t t/04-nextupdown.t t/05-nextafter.t @@ -15,5 +16,7 @@ t/07-info.t t/08-totalorder.t t/09-signbit.t t/10-copysign.t +t/11-aliases.t xt/00-sign.t +xt/11-tags.t TODO diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index 4f6a346..149532f 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -10,5 +10,4 @@ pod.css ^.svn/ ^MYMETA -.travis.yml$ -^RELEASE.md$ \ No newline at end of file +.travis.yml$ \ No newline at end of file diff --git a/lib/Data/IEEE754/Tools.pm b/lib/Data/IEEE754/Tools.pm index 408cd9a..7212630 100644 --- a/lib/Data/IEEE754/Tools.pm +++ b/lib/Data/IEEE754/Tools.pm @@ -152,6 +152,16 @@ a transition to v2. =item * C renamed to C +=item * C<:raw754> renamed to C<:internalString> + +=item * C renamed to C + +=item * C renamed to C + +=item * C renamed to C + +=item * C renamed to C + =back For backward compatibility, the old names are available, but the new names are recommended. @@ -198,6 +208,8 @@ my @EXPORT_BINARY64 = qw( binary64_convertFromInternalHexString binary64_convertToInternalBinaryString binary64_convertFromInternalBinaryString + binary64_convertToHexCharacter + binary64_convertToDecimalCharacter ); our @EXPORT = (); @@ -206,7 +218,7 @@ our %EXPORT_TAGS = ( convertToCharacter => [@EXPORT_CONVERT2CHAR], floating => [@EXPORT_FLOATING], # deprecated floatingpoint => [@EXPORT_FLOATING], # deprecated - internalstring => [@EXPORT_INTERNALS], + internalString => [@EXPORT_INTERNALS], raw754 => [@EXPORT_RAW754], # deprecated ulp => [@EXPORT_ULP], constants => [@EXPORT_CONST], @@ -216,23 +228,23 @@ our %EXPORT_TAGS = ( all => [@EXPORT_OK], ); -=head2 :raw754 +=head2 :internalString These are the functions to do raw conversion from a floating-point value to a hexadecimal or binary string of the underlying IEEE754 encoded value, and back. -=head3 binary64_convertToInternalHexString( I ) +=head3 convertToInternalHexString( I ) Converts the floating-point I into a big-endian hexadecimal representation of the underlying IEEE754 encoding. - binary64_convertToInternalHexString(12.875); # 4029C00000000000 - # ^^^ - # : ^^^^^^^^^^^^^ - # : : - # : `- fraction - # : - # `- sign+exponent + convertToInternalHexString(12.875); # 4029C00000000000 + # ^^^ + # : ^^^^^^^^^^^^^ + # : : + # : `- fraction + # : + # `- sign+exponent The first three nibbles (hexadecimal digits) encode the sign and the exponent. The sign is the most significant bit of the three nibbles (so AND the first nibble with 8; if it's true, @@ -246,45 +258,45 @@ by zero or the logarithm of a zero or negative value) (NaN). The final thirteen nibbles are the encoding of the fractional value (usually C<1 + thirteennibbles / 16**13>, unless it's zero, denormal, infinite, or not a number). -Of course, this is easier to decode using the L function, which interprets +Of course, this is easier to decode using the L function, which interprets the sign, fraction, and exponent for you. (See below for more details.) - convertToDecimalString(12.875); # +0d1.6093750000000000p+0003 + convertToDecimalCharacter(12.875); # +0d1.6093750000000000p+0003 # ^ ^^^^^^^^^^^^^^^^^^ ^^^^ # : : : # : `- coefficient `- exponent (power of 2) # : # `- sign -=head3 binary64_convertToInternalBinaryString( I ) +=head3 convertToInternalBinaryString( I ) Converts the floating-point I into a big-endian binary representation of the underlying IEEE754 encoding. - binary64_convertToInternalBinaryString(12.875); # 0100000000101001110000000000000000000000000000000000000000000000 - # ^ - # `- sign - # ^^^^^^^^^^^ - # `- exponent - # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - # `- fraction + convertToInternalBinaryString(12.875); # 0100000000101001110000000000000000000000000000000000000000000000 + # ^ + # `- sign + # ^^^^^^^^^^^ + # `- exponent + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + # `- fraction The first bit is the sign, the next 11 are the exponent's encoding -=head3 binary64_convertFromInternalHexString( I ) +=head3 convertFromInternalHexString( I ) -The inverse of C: it takes a string representing the 16 nibbles +The inverse of C: it takes a string representing the 16 nibbles of the IEEE754 double value, and converts it back to a perl floating-point value. - print binary64_convertFromInternalHexString('4029C00000000000'); + print convertFromInternalHexString('4029C00000000000'); 12.875 -=head3 binary64_convertFromInternalBinaryString( I ) +=head3 convertFromInternalBinaryString( I ) -The inverse of C: it takes a string representing the 64 bits +The inverse of C: it takes a string representing the 64 bits of the IEEE754 double value, and converts it back to a perl floating-point value. - print binary64_convertFromInternalBinaryString('0100000000101001110000000000000000000000000000000000000000000000'); + print convertFromInternalBinaryString('0100000000101001110000000000000000000000000000000000000000000000'); 12.875 =cut @@ -378,6 +390,10 @@ It displays the value as (sign)(0base)(implied).(fraction)p(exponent): =cut +# TODO = issue#6: might want to rename the exportable functions to convertToHexString, +# and alias _convertToHexCharacter() as the official IEEE-754 naming-scheme, but not exportable +# (so Data::IEEE754::Tools::_convertToHexCharacter(v) as the only calling mechanism) + sub binary64_convertToHexCharacter { # thanks to BrowserUK @ http://perlmonks.org/?node_id=1167146 for slighly better decision factors # I tweaked it to use the two 32bit words instead of one 64bit word (which wouldn't work on some systems) @@ -399,7 +415,7 @@ sub binary64_convertToHexCharacter { } sprintf '%s0x%1u.%13.13sp%+05d', $sign, $implied, $mant, $exp; } -*convertToHexCharacter = \*binary64_convertToHexCharacter; +*convertToHexCharacter = \&binary64_convertToHexCharacter; my $__glue_dispatch; # issue#7 TODO if(0) { # issue#7 TODO $__glue_dispatch = sub { # only use this subref in the glue code, not in any subroutine @@ -416,12 +432,12 @@ if(0) { # issue#7 TODO }; *convertToHexCharacter = $__glue_dispatch->( $Config{nvsize}, - 4 => \*binary32_convertToHexCharacter, - 8 => \*binary64_convertToHexCharacter, - 16 => \*binary128_convertToHexCharacter, + 4 => \&binary32_convertToHexCharacter, + 8 => \&binary64_convertToHexCharacter, + 16 => \&binary128_convertToHexCharacter, ); } -*to_hex_floatingpoint = \*convertToHexCharacter; +*to_hex_floatingpoint = \&convertToHexCharacter; sub binary64_convertToDecimalCharacter { # derived from binary64_convertToHexCharacter @@ -446,15 +462,15 @@ sub binary64_convertToDecimalCharacter { my $other = abs($v) / (2.0**$exp); sprintf '%s0d%.16fp%+05d', $sign, $other, $exp; } -*convertToDecimalCharacter = \*binary64_convertToDecimalCharacter; +*convertToDecimalCharacter = \&binary64_convertToDecimalCharacter; if(0) { # issue#7 TODO *convertToDecimalCharacter = $__glue_dispatch->( $Config{nvsize}, - 4 => \*binary32_convertToDecimalCharacter, - 8 => \*binary64_convertToDecimalCharacter, - 16 => \*binary128_convertToDecimalCharacter, + 4 => \&binary32_convertToDecimalCharacter, + 8 => \&binary64_convertToDecimalCharacter, + 16 => \&binary128_convertToDecimalCharacter, ); } -*to_dec_floatingpoint = \*convertToDecimalCharacter; +*to_dec_floatingpoint = \&convertToDecimalCharacter; =over diff --git a/t/01-raw754.t b/t/01-internalstring.t similarity index 100% rename from t/01-raw754.t rename to t/01-internalstring.t diff --git a/t/02-floatingpoint.t b/t/02-converttochar.t similarity index 100% rename from t/02-floatingpoint.t rename to t/02-converttochar.t diff --git a/t/03-ulp.t b/t/03-ulp.t index 9d7c06a..eab1879 100644 --- a/t/03-ulp.t +++ b/t/03-ulp.t @@ -24,8 +24,6 @@ sub fntest { my $n = shift || "$fn(0x$h => $v)"; my $tada = shift; my $r = undef; - note ''; - note "===== ${n} ====="; if($tada) { TODO: { local $TODO = $tada; @@ -50,7 +48,6 @@ sub fntest { diag sprintf "ANSWER: hex(%-30s) = %s", convertToDecimalCharacter($u), hexstr754_from_double($u); diag ''; } - note '-'x80; } my @tests = (); diff --git a/t/11-aliases.t b/t/11-aliases.t index 024ab6b..edddbbd 100644 --- a/t/11-aliases.t +++ b/t/11-aliases.t @@ -1,5 +1,9 @@ ######################################################################## # Verifies aliased functions +# This checks to make sure that the alias points to the same +# CODEREF as the original. This should guarantee that if an alias +# is invoked, it will call the same underlying code as if the +# original routine were invoked ######################################################################## use 5.006; use warnings; @@ -8,16 +12,22 @@ use Test::More; use Data::IEEE754::Tools qw/:all/; # :raw754 -is( \&hexstr754_from_double , \&binary64_convertToInternalHexString , 'alias:hexstr754_from_double' ); -is( \&hexstr754_to_double , \&binary64_convertFromInternalHexString , 'alias:hexstr754_to_double' ); -is( \&binstr754_from_double , \&binary64_convertToInternalBinaryString , 'alias:binstr754_from_double' ); -is( \&binstr754_to_double , \&binary64_convertFromInternalBinaryString , 'alias:binstr754_to_double' ); +is( \&hexstr754_from_double , \&binary64_convertToInternalHexString , 'alias:hexstr754_from_double '); +is( \&hexstr754_to_double , \&binary64_convertFromInternalHexString , 'alias:hexstr754_to_double '); +is( \&binstr754_from_double , \&binary64_convertToInternalBinaryString , 'alias:binstr754_from_double '); +is( \&binstr754_to_double , \&binary64_convertFromInternalBinaryString , 'alias:binstr754_to_double '); -# :internalstring -is( \&convertToInternalHexString , \&binary64_convertToInternalHexString , 'alias:convertToInternalHexString' ); -is( \&convertFromInternalHexString , \&binary64_convertFromInternalHexString , 'alias:convertFromInternalHexString' ); -is( \&convertToInternalBinaryString , \&binary64_convertToInternalBinaryString , 'alias:convertToInternalBinaryString' ); -is( \&convertFromInternalBinaryString , \&binary64_convertFromInternalBinaryString , 'alias:convertFromInternalBinaryString' ); +# :internalString +is( \&convertToInternalHexString , \&binary64_convertToInternalHexString , 'alias:convertToInternalHexString '); +is( \&convertFromInternalHexString , \&binary64_convertFromInternalHexString , 'alias:convertFromInternalHexString '); +is( \&convertToInternalBinaryString , \&binary64_convertToInternalBinaryString , 'alias:convertToInternalBinaryString '); +is( \&convertFromInternalBinaryString , \&binary64_convertFromInternalBinaryString , 'alias:convertFromInternalBinaryString '); + +# :floatingpoint & :convertToCharacter +is( \&to_hex_floatingpoint , \&convertToHexCharacter , 'alias:to_hex_floatingpoint '); +is( \&to_dec_floatingpoint , \&convertToDecimalCharacter , 'alias:to_dec_floatingpoint '); +is( \&convertToHexCharacter , \&binary64_convertToHexCharacter , 'alias:convertToHexCharacter '); +is( \&convertToDecimalCharacter , \&binary64_convertToDecimalCharacter , 'alias:convertToDecimalCharacter '); done_testing;exit; diff --git a/xt/11-tags.t b/xt/11-tags.t new file mode 100644 index 0000000..a8866d3 --- /dev/null +++ b/xt/11-tags.t @@ -0,0 +1,173 @@ +######################################################################## +# AuthorTest: Verifies each of the import tags are okay -- that +# they only import exactly what I expect, no more, no less +######################################################################## +use 5.006; +use strict; +use warnings; +use Test::More tests => 11; +use Config; +use Data::IEEE754::Tools (); + +my @SUBS = qw( + binary64_convertToInternalHexString convertToInternalHexString hexstr754_from_double + binary64_convertToInternalBinaryString convertToInternalBinaryString binstr754_from_double + binary64_convertFromInternalHexString convertFromInternalHexString hexstr754_to_double + binary64_convertFromInternalBinaryString convertFromInternalBinaryString binstr754_to_double + binary64_convertToHexCharacter convertToHexCharacter to_hex_floatingpoint + binary64_convertToDecimalCharacter convertToDecimalCharacter to_dec_floatingpoint + POS_ZERO + POS_DENORM_SMALLEST + POS_DENORM_BIGGEST + POS_NORM_SMALLEST + POS_NORM_BIGGEST + POS_INF + POS_SNAN_FIRST + POS_SNAN_LAST + POS_IND + POS_QNAN_FIRST + POS_QNAN_LAST + NEG_ZERO + NEG_DENORM_SMALLEST + NEG_DENORM_BIGGEST + NEG_NORM_SMALLEST + NEG_NORM_BIGGEST + NEG_INF + NEG_SNAN_FIRST + NEG_SNAN_LAST + NEG_IND + NEG_QNAN_FIRST + NEG_QNAN_LAST + ulp + toggle_ulp + nextUp + nextDown + nextAfter + isSignMinus + isNormal + isFinite + isZero + isSubnormal + isInfinite + isNaN + isSignaling + isSignalingConvertedToQuiet + isCanonical + class + radix + totalOrder + totalOrderMag + compareFloatingValue + compareFloatingMag + copy + negate + abs + copySign +); + +sub run_test { + my ($tag, $exp) = @_; + Data::IEEE754::Tools->import($tag); + my $got = []; + push @$got, grep { defined &{$_} } @SUBS; + $got = [sort @$got]; + is_deeply( $got, $exp, $tag ); + # { local $" = ","; diag ''; diag "$tag\n got(@$got)\n vs(@$exp)\n"; diag '';} + + # unimport the functions that were found in @$got (inspired by http://stackoverflow.com/a/10307113/5508606) + my $pkg = \%::; + delete $pkg->{$_} for @$got; +} + +my @tests = (); +push @tests, [':convertToCharacter' => [sort qw( + convertToHexCharacter + convertToDecimalCharacter +)]]; +push @tests, [':floating' => [sort qw( + to_hex_floatingpoint + to_dec_floatingpoint +)]]; +push @tests, [':floatingpoint' => [sort qw( + to_hex_floatingpoint + to_dec_floatingpoint +)]]; +push @tests, [':internalString' => [sort qw( + convertToInternalHexString + convertToInternalBinaryString + convertFromInternalHexString + convertFromInternalBinaryString +)]]; +push @tests, [':raw754' => [sort qw( + hexstr754_from_double + hexstr754_to_double + binstr754_from_double + binstr754_to_double +)]]; +push @tests, [':ulp' => [sort qw( + ulp + toggle_ulp + nextUp + nextDown + nextAfter +)]]; +push @tests, [':constants' => [sort qw( + POS_ZERO + POS_DENORM_SMALLEST + POS_DENORM_BIGGEST + POS_NORM_SMALLEST + POS_NORM_BIGGEST + POS_INF + POS_SNAN_FIRST + POS_SNAN_LAST + POS_IND + POS_QNAN_FIRST + POS_QNAN_LAST + NEG_ZERO + NEG_DENORM_SMALLEST + NEG_DENORM_BIGGEST + NEG_NORM_SMALLEST + NEG_NORM_BIGGEST + NEG_INF + NEG_SNAN_FIRST + NEG_SNAN_LAST + NEG_IND + NEG_QNAN_FIRST + NEG_QNAN_LAST +)]]; +push @tests, [':info' => [sort qw( + isSignMinus + isNormal + isFinite + isZero + isSubnormal + isInfinite + isNaN + isSignaling + isSignalingConvertedToQuiet + isCanonical + class + radix + totalOrder + totalOrderMag + compareFloatingValue + compareFloatingMag +)]]; +push @tests, [':signbit' => [sort qw( + copy + negate + abs + copySign + isSignMinus +)]]; +push @tests, [':binary64' => [sort qw( + binary64_convertToInternalHexString + binary64_convertFromInternalHexString + binary64_convertToInternalBinaryString + binary64_convertFromInternalBinaryString + binary64_convertToHexCharacter + binary64_convertToDecimalCharacter +)]]; +push @tests, [':all' => [sort @SUBS]]; + +run_test(@$_) foreach @tests; From 43922c4d486ed852273e8dec1fee6ea39badc18e Mon Sep 17 00:00:00 2001 From: PeterCJ Date: Mon, 27 Mar 2017 08:21:25 -0700 Subject: [PATCH 8/8] 754::Tools v0.017_002: rename from Character to String [Character is to c-centric, IMO]; update VERSION from object to plain STRING for {META_MERGE}{provides}{version}, in preparation for alpha release --- CHANGES | 7 +- MANIFEST | 2 +- Makefile.PL | 10 +- README | 95 +++++++++--------- RELEASE.md | 3 + lib/Data/IEEE754/Tools.pm | 106 +++++++++++--------- t/{02-converttochar.t => 02-converttostr.t} | 12 +-- t/03-ulp.t | 6 +- t/04-nextupdown.t | 16 +-- t/09-signbit.t | 4 +- t/10-copysign.t | 6 +- t/11-aliases.t | 26 ++--- xt/11-tags.t | 16 +-- 13 files changed, 167 insertions(+), 142 deletions(-) rename t/{02-converttochar.t => 02-converttostr.t} (94%) diff --git a/CHANGES b/CHANGES index 37400cb..b8c6c27 100644 --- a/CHANGES +++ b/CHANGES @@ -8,8 +8,8 @@ v0.017 internal development version - make :floatingpoint, to_hex_floatingpoint(), to_dec_floatingpoint() aliases to - :convertToCharacter, convertToHexCharacter(), - convertToDecimalCharacter() + :convertToString, convertToHexString(), + convertToDecimalString() - make :raw754, hexstr754_from_double(), binstr754_from_double(), hexstr754_to_double(), binstr754_to_double() @@ -22,6 +22,9 @@ v0.017 internal development version - improve error messages, and stop module compile on mixed-endianness - add test coverage for aliases - add author test coverage for import-tags + - change VERSION from a version.pm object to a plain old string '0.017_002', + which allows the Makefile.PL to properly extract the {provides}{version} + for META files v0.016 2016-Aug-29 - had a bug in v0.014 Makefile which caused CPAN to not diff --git a/MANIFEST b/MANIFEST index 523630a..2b5ebb2 100644 --- a/MANIFEST +++ b/MANIFEST @@ -7,7 +7,7 @@ README RELEASE.md t/00-load.t t/01-internalstring.t -t/02-converttochar.t +t/02-converttostr.t t/03-ulp.t t/04-nextupdown.t t/05-nextafter.t diff --git a/Makefile.PL b/Makefile.PL index 2420843..0e7d5ea 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -43,10 +43,16 @@ use 5.006; }, # automatically determine the versions for 'provides'; MM->parse_version exists as of MM v6.31, so not a problem with >= 6.46 # => this comes out right when printed... but MYMETA.* shows values that look wrong + #my $vstr = MM->parse_version( $mm_args{VERSION_FROM} ); + #print STDERR $vstr, $/; + #my $qstr = "'$vstr'"; + #print STDERR $qstr, $/; + #(my $novstr = $qstr) =~ s/v//; + #print STDERR $novstr, $/; $mm_args{META_MERGE}{provides} = { $mm_args{NAME} => { file => $mm_args{VERSION_FROM}, - version => ''.MM->parse_version( $mm_args{VERSION_FROM} ), + version => MM->parse_version( $mm_args{VERSION_FROM} ), } }; } @@ -89,7 +95,7 @@ sub MY::postamble { TEST_D = $(ABSPERLRUN) -MExtUtils::Command -e test_d -- # run a test coverage report -testcover :: lib/Math/PRBS.pm +testcover :: $(NOECHO) cover -test -report html # run author-tests on the original diff --git a/README b/README index 2cca755..97448b0 100644 --- a/README +++ b/README @@ -1,64 +1,61 @@ NAME - -Data::IEEE754::Tools - Various tools for understanding and manipulating the underlying IEEE-754 representation of floating point values + Data::IEEE754::Tools - Various tools for understanding and manipulating + the underlying IEEE-754 representation of floating point values DESCRIPTION - -These tools give access to the underlying IEEE 754 floating-point 64bit -representation used by many instances of Perl (see perlguts). They -include functions for converting from the 64bit internal representation -to a string that shows those bits (either as hexadecimal or binary) and -back, functions for converting that encoded value into a more -human-readable format to give insight into the meaning of the encoded -values, and functions to manipulate the smallest possible change for a -given floating-point value (which is the ULP - or "Unit in the -Last Place"). - -COMPATIBILITY - -Data::IEEE754::Tools works with 64bit floating-point representations. - -If you have a Perl setup which uses a larger representation (for -example, "use Config; print $Config{nvsize}; # 16 => 128bit"), values -reported by this module will be reduced in precision to fit the 64bit -representation. - -If you have a Perl setup which uses a smaller representation (for -example, "use Config; print $Config{nvsize}; # 4 => 32bit"), the -installation will likely fail, because the unit tests were not set up -for lower precision inputs. However, forcing the installation *might* -still allow coercion from the smaller Perl NV into a true IEEE 754 -double (64bit) floating-point, but there is no guarantee it will work. + These tools give access to the underlying IEEE 754 floating-point 64bit + representation used by many instances of Perl (see perlguts). They + include functions for converting from the 64bit internal representation + to a string that shows those bits (either as hexadecimal or binary) and + back, functions for converting that encoded value into a more + human-readable format to give insight into the meaning of the encoded + values, and functions to manipulate the smallest possible change for a + given floating-point value (which is the ULP + or "Unit in the + Last Place"). + + Compatibility + Data::IEEE754::Tools works with 64bit floating-point representations. + + If you have a Perl setup which uses a larger representation (for + example, "use Config; print $Config{nvsize}; # 16 => 128bit"), values + reported by this module will be reduced in precision to fit the 64bit + representation. + + If you have a Perl setup which uses a smaller representation (for + example, "use Config; print $Config{nvsize}; # 4 => 32bit"), the + installation will likely fail, because the unit tests were not set up + for lower precision inputs. However, forcing the installation *might* + still allow coercion from the smaller Perl NV into a true IEEE 754 + double (64bit) floating-point, but there is no guarantee it will work. INSTALLATION + To install this module, use your favorite CPAN client. -To install this module, use your favorite CPAN client. - -For a manual install, type the following: + For a manual install, type the following: - perl Makefile.PL - make - make test - make install + perl Makefile.PL + make + make test + make install -(On Windows machines, you may need to use "dmake" instead of "make".) + (On Windows machines, you may need to use "dmake" instead of "make".) AUTHOR + Peter C. Jones "" -Peter C. Jones - -Please report any bugs or feature requests emailing -or thru the web interface at + Please report any bugs or feature requests emailing + "" or thru the web interface at + , or + thru the repository's interface at + . COPYRIGHT + Copyright (C) 2016 Peter C. Jones -Copyright (C) 2016 Peter C. Jones - -LICENCE - -This program is free software; you can redistribute it and/or modify it -under the terms of either: the GNU General Public License as published -by the Free Software Foundation; or the Artistic License. +LICENSE + This program is free software; you can redistribute it and/or modify it + under the terms of either: the GNU General Public License as published + by the Free Software Foundation; or the Artistic License. -See for more information. + See for more information. diff --git a/RELEASE.md b/RELEASE.md index 5596d5d..19c6cae 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -28,6 +28,9 @@ I use a local svn client to checkout the GitHub repo. All these things can be d * **Verify Documentation:** * make sure versioning is correct * verify POD and README + * `pod2text lib/Data/IEEE754/Tools.pm README`, then edit so that only + NAME, DESCRIPTION, COMPATIBILITY, INSTALLATION, AUTHOR, COPYRIGHT, LICENSE + remain * verify HISTORY * **Build Distribution** diff --git a/lib/Data/IEEE754/Tools.pm b/lib/Data/IEEE754/Tools.pm index 7212630..8ede135 100644 --- a/lib/Data/IEEE754/Tools.pm +++ b/lib/Data/IEEE754/Tools.pm @@ -6,9 +6,10 @@ use Carp; use Exporter 'import'; # just use the import() function, without the rest of the overhead of ISA use Config; -use version 0.77; our $VERSION = version->declare('0.017_002'); +our $VERSION = '0.017_002'; +#use v------- 0.77; our $V------ = version->declare('0.017_002'); # part of 0.017_002 alpha release will be to see if a plain string works better: it works better for automating {provides}{version} # use rrr.mmm_aaa, where rrr is major revision, mmm is ODD minor revision, and aaa is alpha sub-revision (for ALPHA code) - # use rrr.mmm, where rrr is major revision, mmm is EVEN minor revision (for releases) + # use rrr.mmmsss, where rrr is major revision, mmm is EVEN minor revision, and sss is a sub-revision (usually sss=000) (for releases) =pod @@ -18,11 +19,11 @@ Data::IEEE754::Tools - Various tools for understanding and manipulating the unde =head1 SYNOPSIS - use Data::IEEE754::Tools qw/:convertToCharacter :ulp/; + use Data::IEEE754::Tools qw/:convertToString :ulp/; - # return -12.875 as decimal and hexadecimal floating point numbers ("convertToCharacter" in IEEE-754 parlance) - convertToDecimalCharacter(-12.875); # -0d1.6093750000000000p+0003 - convertToHexCharacter(-12.875); # -0x1.9c00000000000p+0003 + # return -12.875 as strings of decimal or hexadecimal floating point numbers ("convertTo*Character" in IEEE-754 parlance) + convertToDecimalString(-12.875); # -0d1.6093750000000000p+0003 + convertToHexString(-12.875); # -0x1.9c00000000000p+0003 # shows the smallest value you can add or subtract to 16.16 (ulp = "Unit in the Last Place") print ulp( 16.16 ); # 3.5527136788005e-015 @@ -30,8 +31,8 @@ Data::IEEE754::Tools - Various tools for understanding and manipulating the unde # toggles the ulp: returns a float that has the ULP of 16.16 toggled # (if it was a 1, it will be 0, and vice versa); # running it twice should give the original value - print $t16 = toggle_ulp( 16.16 ); # 16.159999999999997 - print $v16 = toggle_ulp( $t16 ); # 16.160000000000000 + print $t16 = toggle_ulp( 16.16 ); # 16.159999999999997 + print $v16 = toggle_ulp( $t16 ); # 16.160000000000000 =head1 DESCRIPTION @@ -146,11 +147,11 @@ a transition to v2. =over -=item * C<:floatingpoint> renamed to C<:convertToCharacter> +=item * C<:floatingpoint> renamed to C<:convertToString> -=item * C renamed to C +=item * C renamed to C (or C) -=item * C renamed to C +=item * C renamed to C (or C) =item * C<:raw754> renamed to C<:internalString> @@ -182,7 +183,7 @@ my @EXPORT_INTERNALS = qw( ); my @EXPORT_FLOATING = qw(to_hex_floatingpoint to_dec_floatingpoint); # deprecated -my @EXPORT_CONVERT2CHAR = qw(convertToHexCharacter convertToDecimalCharacter); +my @EXPORT_CONVERT2STR = qw(convertToHexString convertToDecimalString); my @EXPORT_ULP = qw(ulp toggle_ulp nextUp nextDown nextAfter); my @EXPORT_CONST = qw( POS_ZERO @@ -208,14 +209,14 @@ my @EXPORT_BINARY64 = qw( binary64_convertFromInternalHexString binary64_convertToInternalBinaryString binary64_convertFromInternalBinaryString - binary64_convertToHexCharacter - binary64_convertToDecimalCharacter + binary64_convertToHexString + binary64_convertToDecimalString ); our @EXPORT = (); -our @EXPORT_OK = (@EXPORT_FLOATING, @EXPORT_CONVERT2CHAR, @EXPORT_RAW754, @EXPORT_INTERNALS, @EXPORT_ULP, @EXPORT_CONST, @EXPORT_INFO, @EXPORT_SIGNBIT, @EXPORT_BINARY64); +our @EXPORT_OK = (@EXPORT_FLOATING, @EXPORT_CONVERT2STR, @EXPORT_RAW754, @EXPORT_INTERNALS, @EXPORT_ULP, @EXPORT_CONST, @EXPORT_INFO, @EXPORT_SIGNBIT, @EXPORT_BINARY64); our %EXPORT_TAGS = ( - convertToCharacter => [@EXPORT_CONVERT2CHAR], + convertToString => [@EXPORT_CONVERT2STR], floating => [@EXPORT_FLOATING], # deprecated floatingpoint => [@EXPORT_FLOATING], # deprecated internalString => [@EXPORT_INTERNALS], @@ -258,15 +259,15 @@ by zero or the logarithm of a zero or negative value) (NaN). The final thirteen nibbles are the encoding of the fractional value (usually C<1 + thirteennibbles / 16**13>, unless it's zero, denormal, infinite, or not a number). -Of course, this is easier to decode using the L function, which interprets +Of course, this is easier to decode using the L function, which interprets the sign, fraction, and exponent for you. (See below for more details.) - convertToDecimalCharacter(12.875); # +0d1.6093750000000000p+0003 - # ^ ^^^^^^^^^^^^^^^^^^ ^^^^ - # : : : - # : `- coefficient `- exponent (power of 2) - # : - # `- sign + convertToDecimalString(12.875); # +0d1.6093750000000000p+0003 + # ^ ^^^^^^^^^^^^^^^^^^ ^^^^ + # : : : + # : `- coefficient `- exponent (power of 2) + # : + # `- sign =head3 convertToInternalBinaryString( I ) @@ -373,18 +374,18 @@ if( $] lt '5.010' ) { *hexstr754_to_double = \&convertFromInternalHexString; *binstr754_to_double = \&convertFromInternalBinaryString; -=head2 :convertToCharacter +=head2 :convertToString -=head3 convertToHexCharacter( I ) +=head3 convertToHexString( I ) -=head3 convertToDecimalCharacter( I ) +=head3 convertToDecimalString( I ) Converts value to a hexadecimal or decimal floating-point notation that indicates the sign and the coefficient and the power of two, with the coefficient either in hexadecimal or decimal notation. - convertToHexCharacter(-3.9999999999999996) # -0x1.fffffffffffffp+0001 - convertToDecimalCharacter(-3.9999999999999996) # -0d1.9999999999999998p+0001 + convertToHexString(-3.9999999999999996) # -0x1.fffffffffffffp+0001 + convertToDecimalString(-3.9999999999999996) # -0d1.9999999999999998p+0001 It displays the value as (sign)(0base)(implied).(fraction)p(exponent): @@ -394,7 +395,7 @@ It displays the value as (sign)(0base)(implied).(fraction)p(exponent): # and alias _convertToHexCharacter() as the official IEEE-754 naming-scheme, but not exportable # (so Data::IEEE754::Tools::_convertToHexCharacter(v) as the only calling mechanism) -sub binary64_convertToHexCharacter { +sub binary64_convertToHexString { # thanks to BrowserUK @ http://perlmonks.org/?node_id=1167146 for slighly better decision factors # I tweaked it to use the two 32bit words instead of one 64bit word (which wouldn't work on some systems) my $v = shift; @@ -415,7 +416,7 @@ sub binary64_convertToHexCharacter { } sprintf '%s0x%1u.%13.13sp%+05d', $sign, $implied, $mant, $exp; } -*convertToHexCharacter = \&binary64_convertToHexCharacter; +*convertToHexString = \&binary64_convertToHexString; my $__glue_dispatch; # issue#7 TODO if(0) { # issue#7 TODO $__glue_dispatch = sub { # only use this subref in the glue code, not in any subroutine @@ -431,16 +432,16 @@ if(0) { # issue#7 TODO return $h{$arg}; }; - *convertToHexCharacter = $__glue_dispatch->( $Config{nvsize}, - 4 => \&binary32_convertToHexCharacter, - 8 => \&binary64_convertToHexCharacter, - 16 => \&binary128_convertToHexCharacter, + *convertToHexString = $__glue_dispatch->( $Config{nvsize}, + 4 => \&binary32_convertToHexString, + 8 => \&binary64_convertToHexString, + 16 => \&binary128_convertToHexString, ); } -*to_hex_floatingpoint = \&convertToHexCharacter; +*to_hex_floatingpoint = \&convertToHexString; -sub binary64_convertToDecimalCharacter { - # derived from binary64_convertToHexCharacter +sub binary64_convertToDecimalString { + # derived from binary64_convertToHexString my $v = shift; my ($msb,$lsb) = $_helper64_arr2x32b->($v); my $sbit = ($msb & 0x80000000) >> 31; @@ -462,15 +463,15 @@ sub binary64_convertToDecimalCharacter { my $other = abs($v) / (2.0**$exp); sprintf '%s0d%.16fp%+05d', $sign, $other, $exp; } -*convertToDecimalCharacter = \&binary64_convertToDecimalCharacter; +*convertToDecimalString = \&binary64_convertToDecimalString; if(0) { # issue#7 TODO - *convertToDecimalCharacter = $__glue_dispatch->( $Config{nvsize}, - 4 => \&binary32_convertToDecimalCharacter, - 8 => \&binary64_convertToDecimalCharacter, - 16 => \&binary128_convertToDecimalCharacter, + *convertToDecimalString = $__glue_dispatch->( $Config{nvsize}, + 4 => \&binary32_convertToDecimalString, + 8 => \&binary64_convertToDecimalString, + 16 => \&binary128_convertToDecimalString, ); } -*to_dec_floatingpoint = \&convertToDecimalCharacter; +*to_dec_floatingpoint = \&convertToDecimalString; =over @@ -520,6 +521,19 @@ they are really multiples of 2**-1022, not 2**-1023. For backward compatibility, if you use the older tag C<:floatingpoint>, you can refer to these functions as C and C. +=head3 Data::IEEE754::Tools::binary64_convertToHexCharacter( I ) + +=head3 Data::IEEE754::Tools::binary64_convertToDecimalCharacter( I ) + +These are the same functions, but under the official IEEE 754 nomenclature of +CtypeE_convertTo*Character()>. These are included for the "canonical" +naming convention, but are not exportable. + +=cut + +*binary64_convertToHexCharacter = \&binary64_convertToHexString; +*binary64_convertToDecimalCharacter = \&binary64_convertToDecimalString; + =head2 :constants These can be useful as references for the specialty values, and include the positive and negative @@ -1060,9 +1074,9 @@ Copies the sign from I, but uses the value from I. For example, sub copySign { my ($x, $y) = @_[0,1]; - my ($bx,$by) = map { binary64_convertToInternalBinaryString($_) } $x, $y; # convert to binary strings + my ($bx,$by) = map { binary64_convertToInternalBinaryString($_) } $x, $y; # convert to binary strings substr($bx, 0, 1) = substr($by, 0, 1); # copy the sign bit from y to x - return binary64_convertFromInternalBinaryString($bx); # convert binary-x (with modified sign) back to double + return binary64_convertFromInternalBinaryString($bx); # convert binary-x (with modified sign) back to double } =head3 also exports C I C<)> (see :info) @@ -1101,7 +1115,7 @@ signaling and quiet L. =item * L: I really wanted to use this module, but it didn't get me very far down the "Tools" track, and included a lot of overhead modules for its install/test that I didn't want to require for B. -However, I was inspired by his byteorder-dependent anonymous subs (which were in turn derived from L); +However, I was inspired by its byteorder-dependent anonymous subs (which were in turn derived from L); they were more efficient, on a per-call-to-subroutine basis, than my original inclusion of the if(byteorder) in every call to the sub. diff --git a/t/02-converttochar.t b/t/02-converttostr.t similarity index 94% rename from t/02-converttochar.t rename to t/02-converttostr.t index 29d9c76..d1bda20 100644 --- a/t/02-converttochar.t +++ b/t/02-converttostr.t @@ -1,14 +1,14 @@ ######################################################################## # Verifies the following functions: -# :convertToCharacter -# convertToHexCharacter(v) -# convertToDecimalCharacter(v) +# :convertToString +# convertToHexString(v) +# convertToDecimalString(v) ######################################################################## use 5.006; use warnings; use strict; use Test::More; -use Data::IEEE754::Tools qw/:raw754 :convertToCharacter/; +use Data::IEEE754::Tools qw/:raw754 :convertToString/; sub fptest { local $\ = "\n"; @@ -17,11 +17,11 @@ sub fptest { my ($got, $exp, $name); $exp = quotemeta( $h->{exp_hex} ); $exp =~ s/SNAN/[SQ]NAN/; - like( $got = convertToHexCharacter($val), qr/$exp/, $name = sprintf('convertToHexCharacter(ieee754(%-16.16s) = %-+24.16e)', $h->{src}, $val) ); + like( $got = convertToHexString($val), qr/$exp/, $name = sprintf('convertToHexString(ieee754(%-16.16s) = %-+24.16e)', $h->{src}, $val) ); print( "$name() = $got" ); $exp = quotemeta( $h->{exp_dec} ); $exp =~ s/SNAN/[SQ]NAN/; - like( $got = convertToDecimalCharacter($val), qr/$exp/, $name = sprintf('convertToDecimalCharacter(ieee754(%-16.16s) = %-+24.16e)', $h->{src}, $val) ); + like( $got = convertToDecimalString($val), qr/$exp/, $name = sprintf('convertToDecimalString(ieee754(%-16.16s) = %-+24.16e)', $h->{src}, $val) ); print( "$name() = $got" ); } diff --git a/t/03-ulp.t b/t/03-ulp.t index eab1879..54b828a 100644 --- a/t/03-ulp.t +++ b/t/03-ulp.t @@ -43,9 +43,9 @@ sub fntest { unless($r) { diag ''; diag "$n:"; - diag sprintf "ORIGINAL: hex(%-30s) = %s", convertToDecimalCharacter($v), $h; - diag sprintf "EXPECT: hex(%-30s) = %s", convertToDecimalCharacter($x), hexstr754_from_double($x); - diag sprintf "ANSWER: hex(%-30s) = %s", convertToDecimalCharacter($u), hexstr754_from_double($u); + diag sprintf "ORIGINAL: hex(%-30s) = %s", convertToDecimalString($v), $h; + diag sprintf "EXPECT: hex(%-30s) = %s", convertToDecimalString($x), hexstr754_from_double($x); + diag sprintf "ANSWER: hex(%-30s) = %s", convertToDecimalString($u), hexstr754_from_double($u); diag ''; } } diff --git a/t/04-nextupdown.t b/t/04-nextupdown.t index bcb3d68..b8ac961 100644 --- a/t/04-nextupdown.t +++ b/t/04-nextupdown.t @@ -9,7 +9,7 @@ use 5.006; use warnings; use strict; use Test::More; -use Data::IEEE754::Tools qw/:raw754 :ulp :convertToCharacter/; +use Data::IEEE754::Tools qw/:raw754 :ulp :convertToString/; my ($h,$u,$v); @@ -45,17 +45,17 @@ sub fntest { unless($r) { diag ''; diag "$n:"; - diag sprintf "ORIGINAL: hex(%-30s) = %s", convertToDecimalCharacter($v), $h; - diag sprintf "EXPECT: hex(%-30s) = %s", convertToDecimalCharacter($x), hexstr754_from_double($x); - diag sprintf "ANSWER: hex(%-30s) = %s", convertToDecimalCharacter($u), hexstr754_from_double($u); + diag sprintf "ORIGINAL: hex(%-30s) = %s", convertToDecimalString($v), $h; + diag sprintf "EXPECT: hex(%-30s) = %s", convertToDecimalString($x), hexstr754_from_double($x); + diag sprintf "ANSWER: hex(%-30s) = %s", convertToDecimalString($u), hexstr754_from_double($u); diag ''; SWITCHFUNCTION: foreach ($fn) { my $val = /^nextDown$/ ? - $v : $v; # choose nextUp or nextDown if( $val != $val ) { # NAN - diag( "DEBUG($fn): IS NAN\t" . convertToDecimalCharacter($val) ); + diag( "DEBUG($fn): IS NAN\t" . convertToDecimalString($val) ); last SWITCHFUNCTION; } else { - diag( "DEBUG($fn): ISN'T NAN\t" . convertToDecimalCharacter($val) ); + diag( "DEBUG($fn): ISN'T NAN\t" . convertToDecimalString($val) ); } my $h754 = hexstr754_from_double($val); diag( "DEBUG($fn): h754 = $h754" ); @@ -79,8 +79,8 @@ sub fntest { $lsb &= 0xFFFFFFFF; # v0.011_001: potential bugfix: ensure 32bit MSB diag( "DEBUG($fn): MASKED msb,lsb = $msb,$lsb" ); diag( "DEBUG($fn): FINAL HEXSTR = " .sprintf('%08X%08X', $msb, $lsb )); - diag( "DEBUG($fn): FINAL DOUBLE = " .convertToDecimalCharacter(hexstr754_to_double( sprintf '%08X%08X', $msb, $lsb ))); - diag( "DEBUG($fn): FINAL NEG DOUBLE = " .convertToDecimalCharacter(-hexstr754_to_double( sprintf '%08X%08X', $msb, $lsb ))) + diag( "DEBUG($fn): FINAL DOUBLE = " .convertToDecimalString(hexstr754_to_double( sprintf '%08X%08X', $msb, $lsb ))); + diag( "DEBUG($fn): FINAL NEG DOUBLE = " .convertToDecimalString(-hexstr754_to_double( sprintf '%08X%08X', $msb, $lsb ))) if (/^nextDown$/); last SWITCHFUNCTION; } diff --git a/t/09-signbit.t b/t/09-signbit.t index 9ae6d66..ee3c23d 100644 --- a/t/09-signbit.t +++ b/t/09-signbit.t @@ -11,7 +11,7 @@ use 5.006; use warnings; use strict; use Test::More; -use Data::IEEE754::Tools qw/:raw754 :convertToCharacter :constants :signbit/; +use Data::IEEE754::Tools qw/:raw754 :convertToString :constants :signbit/; my @tests = (); # [CONSTANT , 'NAME ', CONSTANT , negate() , abs() ]; @@ -50,7 +50,7 @@ foreach my $t ( @tests ) { my $xi = $x[$i]; my $f = \&{$fn}; is( ($f->($c)), ($xi), sprintf('%-20.20s(%-20.20s)', $fn, $name ) ); - is( convertToHexCharacter($f->($c)), convertToHexCharacter($xi), sprintf('%-20.20s(%-20.20s)', $fn, $name ) ); + is( convertToHexString($f->($c)), convertToHexString($xi), sprintf('%-20.20s(%-20.20s)', $fn, $name ) ); } } diff --git a/t/10-copysign.t b/t/10-copysign.t index c1acde1..d5463cc 100644 --- a/t/10-copysign.t +++ b/t/10-copysign.t @@ -8,7 +8,7 @@ use 5.006; use warnings; use strict; use Test::More; -use Data::IEEE754::Tools qw/:raw754 :convertToCharacter :constants :info :signbit/; +use Data::IEEE754::Tools qw/:raw754 :convertToString :constants :info :signbit/; my @constants = ( NEG_QNAN_LAST , @@ -45,10 +45,10 @@ foreach my $x (@constants) { my $z = copySign($x, $y); my $zsign = isSignMinus($z); - my $pre = sprintf('copySign(%-25.25s,%-25.25s): ', convertToHexCharacter($x), convertToHexCharacter($y)); + my $pre = sprintf('copySign(%-25.25s,%-25.25s): ', convertToHexString($x), convertToHexString($y)); is( $zsign , $ysign , $pre . 'sign compare' ); - is( convertToHexCharacter(abs($z)), convertToHexCharacter(abs($x)), $pre . 'abs compare' ); + is( convertToHexString(abs($z)), convertToHexString(abs($x)), $pre . 'abs compare' ); } } diff --git a/t/11-aliases.t b/t/11-aliases.t index edddbbd..9a84d3b 100644 --- a/t/11-aliases.t +++ b/t/11-aliases.t @@ -12,22 +12,24 @@ use Test::More; use Data::IEEE754::Tools qw/:all/; # :raw754 -is( \&hexstr754_from_double , \&binary64_convertToInternalHexString , 'alias:hexstr754_from_double '); -is( \&hexstr754_to_double , \&binary64_convertFromInternalHexString , 'alias:hexstr754_to_double '); -is( \&binstr754_from_double , \&binary64_convertToInternalBinaryString , 'alias:binstr754_from_double '); -is( \&binstr754_to_double , \&binary64_convertFromInternalBinaryString , 'alias:binstr754_to_double '); +is( \&hexstr754_from_double , \&binary64_convertToInternalHexString , 'alias:hexstr754_from_double '); +is( \&hexstr754_to_double , \&binary64_convertFromInternalHexString , 'alias:hexstr754_to_double '); +is( \&binstr754_from_double , \&binary64_convertToInternalBinaryString , 'alias:binstr754_from_double '); +is( \&binstr754_to_double , \&binary64_convertFromInternalBinaryString , 'alias:binstr754_to_double '); # :internalString -is( \&convertToInternalHexString , \&binary64_convertToInternalHexString , 'alias:convertToInternalHexString '); -is( \&convertFromInternalHexString , \&binary64_convertFromInternalHexString , 'alias:convertFromInternalHexString '); -is( \&convertToInternalBinaryString , \&binary64_convertToInternalBinaryString , 'alias:convertToInternalBinaryString '); -is( \&convertFromInternalBinaryString , \&binary64_convertFromInternalBinaryString , 'alias:convertFromInternalBinaryString '); +is( \&convertToInternalHexString , \&binary64_convertToInternalHexString , 'alias:convertToInternalHexString '); +is( \&convertFromInternalHexString , \&binary64_convertFromInternalHexString , 'alias:convertFromInternalHexString '); +is( \&convertToInternalBinaryString , \&binary64_convertToInternalBinaryString , 'alias:convertToInternalBinaryString '); +is( \&convertFromInternalBinaryString , \&binary64_convertFromInternalBinaryString , 'alias:convertFromInternalBinaryString '); # :floatingpoint & :convertToCharacter -is( \&to_hex_floatingpoint , \&convertToHexCharacter , 'alias:to_hex_floatingpoint '); -is( \&to_dec_floatingpoint , \&convertToDecimalCharacter , 'alias:to_dec_floatingpoint '); -is( \&convertToHexCharacter , \&binary64_convertToHexCharacter , 'alias:convertToHexCharacter '); -is( \&convertToDecimalCharacter , \&binary64_convertToDecimalCharacter , 'alias:convertToDecimalCharacter '); +is( \&to_hex_floatingpoint , \&convertToHexString , 'alias:to_hex_floatingpoint '); +is( \&to_dec_floatingpoint , \&convertToDecimalString , 'alias:to_dec_floatingpoint '); +is( \&convertToHexString , \&binary64_convertToHexString , 'alias:convertToHexString '); +is( \&convertToDecimalString , \&binary64_convertToDecimalString , 'alias:convertToDecimalString '); +is( \&Data::IEEE754::Tools::binary64_convertToHexCharacter , \&binary64_convertToHexString , 'alias:convertToHexCharacter '); +is( \&Data::IEEE754::Tools::binary64_convertToDecimalCharacter , \&binary64_convertToDecimalString , 'alias:convertToDecimalCharacter '); done_testing;exit; diff --git a/xt/11-tags.t b/xt/11-tags.t index a8866d3..c4f5ec1 100644 --- a/xt/11-tags.t +++ b/xt/11-tags.t @@ -14,8 +14,8 @@ my @SUBS = qw( binary64_convertToInternalBinaryString convertToInternalBinaryString binstr754_from_double binary64_convertFromInternalHexString convertFromInternalHexString hexstr754_to_double binary64_convertFromInternalBinaryString convertFromInternalBinaryString binstr754_to_double - binary64_convertToHexCharacter convertToHexCharacter to_hex_floatingpoint - binary64_convertToDecimalCharacter convertToDecimalCharacter to_dec_floatingpoint + binary64_convertToHexString convertToHexString to_hex_floatingpoint + binary64_convertToDecimalString convertToDecimalString to_dec_floatingpoint POS_ZERO POS_DENORM_SMALLEST POS_DENORM_BIGGEST @@ -80,9 +80,9 @@ sub run_test { } my @tests = (); -push @tests, [':convertToCharacter' => [sort qw( - convertToHexCharacter - convertToDecimalCharacter +push @tests, [':convertToString' => [sort qw( + convertToHexString + convertToDecimalString )]]; push @tests, [':floating' => [sort qw( to_hex_floatingpoint @@ -165,9 +165,9 @@ push @tests, [':binary64' => [sort qw( binary64_convertFromInternalHexString binary64_convertToInternalBinaryString binary64_convertFromInternalBinaryString - binary64_convertToHexCharacter - binary64_convertToDecimalCharacter + binary64_convertToHexString + binary64_convertToDecimalString )]]; -push @tests, [':all' => [sort @SUBS]]; +push @tests, [':all' => [grep {!/::/} sort @SUBS]]; run_test(@$_) foreach @tests;