From 9f919823fe3cc0443ed3b33e3fdcbdf59fe77c77 Mon Sep 17 00:00:00 2001 From: Joel Maslak Date: Sun, 19 Jul 2015 01:31:43 -0600 Subject: [PATCH] Fix bug where Solaris 80 bit long doubles on x86 hardware causes 10**11 to not equal 10E10. Modified PPI::Token::Number::Exp to match what the Perl interpreter does internally when parsing scientific notation. --- lib/PPI/Token/Number/Exp.pm | 24 ++++++++++++++++++++++-- t/07_token.t | 2 +- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/PPI/Token/Number/Exp.pm b/lib/PPI/Token/Number/Exp.pm index 74161ef0..241ce16c 100644 --- a/lib/PPI/Token/Number/Exp.pm +++ b/lib/PPI/Token/Number/Exp.pm @@ -52,8 +52,28 @@ sub literal { my $neg = $mantissa =~ s/^\-//; $mantissa =~ s/^\./0./; $exponent =~ s/^\+//; - my $val = $mantissa * 10 ** $exponent; - return $neg ? -$val : $val; + + # This algorithm is reasonably close to the S_mulexp10() + # algorithm from the Perl source code, so it should arrive + # at the same answer as Perl most of the time. + my $negpow = 0; + if ($exponent < 0) { + $negpow = 1; + $exponent *= -1; + } + + my $result = 1; + my $power = 10; + for (my $bit = 1; $exponent; $bit = $bit << 1) { + if ($exponent & $bit) { + $exponent = $exponent ^ $bit; + $result *= $power; + } + $power *= $power; + } + + my $val = $neg ? 0 - $mantissa : $mantissa; + return $negpow ? $val / $result : $val * $result; } diff --git a/t/07_token.t b/t/07_token.t index 155fbddc..76f6f971 100644 --- a/t/07_token.t +++ b/t/07_token.t @@ -55,7 +55,7 @@ SCOPE: { '0.0e-10' => '10e', '0.0e+10' => '10e', '0.0e100' => '10e', - '1_0e1_0' => '10e', # Known to fail on 5.6.2 + '1_0e1_0' => '10e', '0b' => 2, '0b0' => 2, '0b10' => 2,