double-conversion 0.2.0.1 → 0.2.0.3
raw patch · 8 files changed
+77/−145 lines, 8 filesdep +double-conversiondep +test-frameworkdep +test-framework-quickcheck2dep ~basedep ~textPVP ok
version bump matches the API change (PVP)
Dependencies added: double-conversion, test-framework, test-framework-quickcheck2
Dependency ranges changed: base, text
API changes (from Hackage documentation)
Files
- Data/Double/Conversion/ByteString.hs +1/−1
- Data/Double/Conversion/FFI.hs +6/−2
- Data/Double/Conversion/Text.hs +1/−1
- README.markdown +4/−4
- double-conversion.cabal +19/−7
- double-conversion/src/fast-dtoa.cc +33/−110
- tests/Properties.hs +13/−5
- tests/double-conversion-tests.cabal +0/−15
Data/Double/Conversion/ByteString.hs view
@@ -3,7 +3,7 @@ -- Copyright : (c) 2011 MailRank, Inc. -- -- License : BSD-style--- Maintainer : bos@mailrank.com+-- Maintainer : bos@serpentine.com -- Stability : experimental -- Portability : GHC --
Data/Double/Conversion/FFI.hs view
@@ -1,11 +1,11 @@-{-# LANGUAGE ForeignFunctionInterface, MagicHash, UnliftedFFITypes #-}+{-# LANGUAGE CPP, ForeignFunctionInterface, MagicHash, UnliftedFFITypes #-} -- | -- Module : Data.Double.Conversion.FFI -- Copyright : (c) 2011 MailRank, Inc. -- -- License : BSD-style--- Maintainer : bos@mailrank.com+-- Maintainer : bos@serpentine.com -- Stability : experimental -- Portability : GHC --@@ -29,7 +29,11 @@ ) where import Data.Word (Word8)+#if __GLASGOW_HASKELL__ >= 703+import Foreign.C.Types (CDouble(CDouble), CInt(CInt))+#else import Foreign.C.Types (CDouble, CInt)+#endif import Foreign.Ptr (Ptr) import GHC.Prim (MutableByteArray#)
Data/Double/Conversion/Text.hs view
@@ -5,7 +5,7 @@ -- Copyright : (c) 2011 MailRank, Inc. -- -- License : BSD-style--- Maintainer : bos@mailrank.com+-- Maintainer : bos@serpentine.com -- Stability : experimental -- Portability : GHC --
README.markdown view
@@ -11,11 +11,11 @@ and other improvements. Please report bugs via the-[github issue tracker](https://github.com/mailrank/double-conversion/issues).+[github issue tracker](https://github.com/bos/double-conversion/issues). -Master [git repository](https://github.com/mailrank/double-conversion):+Master [git repository](https://github.com/bos/double-conversion): -* `git clone git://github.com/mailrank/double-conversion.git`+* `git clone git://github.com/bos/double-conversion.git` There's also a [Mercurial mirror](https://bitbucket.org/bos/double-conversion): @@ -27,4 +27,4 @@ ------- This library is written and maintained by Bryan O'Sullivan,-<bos@mailrank.com>.+<bos@serpentine.com>.
double-conversion.cabal view
@@ -1,12 +1,12 @@ name: double-conversion-version: 0.2.0.1+version: 0.2.0.3 license: BSD3 license-file: LICENSE-homepage: https://github.com/mailrank/double-conversion-bug-reports: https://github.com/mailrank/double-conversion/issues+homepage: https://github.com/bos/double-conversion+bug-reports: https://github.com/bos/double-conversion/issues category: Text-author: Bryan O'Sullivan <bos@mailrank.com>-maintainer: Bryan O'Sullivan <bos@mailrank.com>+author: Bryan O'Sullivan <bos@serpentine.com>+maintainer: Bryan O'Sullivan <bos@serpentine.com> stability: experimental tested-with: GHC == 7.0.3 synopsis: Fast conversion between double precision floating point and text@@ -46,7 +46,6 @@ double-conversion/test/cctest/*.h double-conversion/test/cctest/SConscript include/*.h- tests/*.cabal tests/*.hs flag developer@@ -100,9 +99,22 @@ if impl(ghc >= 6.9) && impl(ghc < 6.11) build-depends: integer >= 0.1 && < 0.2 +test-suite tests+ type: exitcode-stdio-1.0+ hs-source-dirs: tests+ main-is: Properties.hs+ ghc-options: -Wall+ build-depends:+ base,+ bytestring,+ double-conversion,+ test-framework,+ test-framework-quickcheck2,+ text+ source-repository head type: git- location: https://github.com/mailrank/double-conversion+ location: https://github.com/bos/double-conversion source-repository head type: mercurial
double-conversion/src/fast-dtoa.cc view
@@ -31,6 +31,8 @@ #include "diy-fp.h" #include "double.h" +#include <stdio.h>+ namespace double_conversion { // The minimal and maximal target exponent define the range of w's binary@@ -222,121 +224,42 @@ return false; } --static const uint32_t kTen4 = 10000;-static const uint32_t kTen5 = 100000;-static const uint32_t kTen6 = 1000000;-static const uint32_t kTen7 = 10000000;-static const uint32_t kTen8 = 100000000;-static const uint32_t kTen9 = 1000000000;- // Returns the biggest power of ten that is less than or equal to the given // number. We furthermore receive the maximum number of bits 'number' has.-// If number_bits == 0 then 0^-1 is returned+//+// Returns power == 10^(exponent_plus_one-1) such that+// power <= number < power * 10.+// If number_bits == 0 then 0^(0-1) is returned. // The number of bits must be <= 32. // Precondition: number < (1 << (number_bits + 1)).++// Inspired by the method for finding an integer log base 10 from here:+// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10+static unsigned int const kSmallPowersOfTen[] =+ {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000,+ 1000000000};+ static void BiggestPowerTen(uint32_t number, int number_bits, uint32_t* power,- int* exponent) {+ int* exponent_plus_one) { ASSERT(number < (1 << (number_bits + 1)));-- switch (number_bits) {- case 32:- case 31:- case 30:- if (kTen9 <= number) {- *power = kTen9;- *exponent = 9;- break;- } // else fallthrough- case 29:- case 28:- case 27:- if (kTen8 <= number) {- *power = kTen8;- *exponent = 8;- break;- } // else fallthrough- case 26:- case 25:- case 24:- if (kTen7 <= number) {- *power = kTen7;- *exponent = 7;- break;- } // else fallthrough- case 23:- case 22:- case 21:- case 20:- if (kTen6 <= number) {- *power = kTen6;- *exponent = 6;- break;- } // else fallthrough- case 19:- case 18:- case 17:- if (kTen5 <= number) {- *power = kTen5;- *exponent = 5;- break;- } // else fallthrough- case 16:- case 15:- case 14:- if (kTen4 <= number) {- *power = kTen4;- *exponent = 4;- break;- } // else fallthrough- case 13:- case 12:- case 11:- case 10:- if (1000 <= number) {- *power = 1000;- *exponent = 3;- break;- } // else fallthrough- case 9:- case 8:- case 7:- if (100 <= number) {- *power = 100;- *exponent = 2;- break;- } // else fallthrough- case 6:- case 5:- case 4:- if (10 <= number) {- *power = 10;- *exponent = 1;- break;- } // else fallthrough- case 3:- case 2:- case 1:- if (1 <= number) {- *power = 1;- *exponent = 0;- break;- } // else fallthrough- case 0:- *power = 0;- *exponent = -1;- break;- default:- // Following assignments are here to silence compiler warnings.- *power = 0;- *exponent = 0;- UNREACHABLE();+ // 1233/4096 is approximately 1/lg(10).+ int exponent_plus_one_guess = ((number_bits + 1) * 1233 >> 12);+ // We increment to skip over the first entry in the kPowersOf10 table.+ // Note: kPowersOf10[i] == 10^(i-1).+ exponent_plus_one_guess++;+ // We don't have any guarantees that 2^number_bits <= number.+ // TODO(floitsch): can we change the 'while' into an 'if'? We definitely see+ // number < (2^number_bits - 1), but I haven't encountered+ // number < (2^number_bits - 2) yet.+ while (number < kSmallPowersOfTen[exponent_plus_one_guess]) {+ exponent_plus_one_guess--; }+ *power = kSmallPowersOfTen[exponent_plus_one_guess];+ *exponent_plus_one = exponent_plus_one_guess; } - // Generates the digits of input number w. // w is a floating-point number (DiyFp), consisting of a significand and an // exponent. Its exponent is bounded by kMinimalTargetExponent and@@ -418,10 +341,10 @@ // Modulo by one is an and. uint64_t fractionals = too_high.f() & (one.f() - 1); uint32_t divisor;- int divisor_exponent;+ int divisor_exponent_plus_one; BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),- &divisor, &divisor_exponent);- *kappa = divisor_exponent + 1;+ &divisor, &divisor_exponent_plus_one);+ *kappa = divisor_exponent_plus_one; *length = 0; // Loop invariant: buffer = too_high / 10^kappa (integer division) // The invariant holds for the first iteration: kappa has been initialized@@ -526,10 +449,10 @@ // Modulo by one is an and. uint64_t fractionals = w.f() & (one.f() - 1); uint32_t divisor;- int divisor_exponent;+ int divisor_exponent_plus_one; BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),- &divisor, &divisor_exponent);- *kappa = divisor_exponent + 1;+ &divisor, &divisor_exponent_plus_one);+ *kappa = divisor_exponent_plus_one; *length = 0; // Loop invariant: buffer = w / 10^kappa (integer division)
tests/Properties.hs view
@@ -1,11 +1,19 @@-import Data.Double.Conversion-import Test.QuickCheck-import Test.Framework (defaultMain, testGroup)+import Test.Framework (defaultMain) import Test.Framework.Providers.QuickCheck2 (testProperty)+import qualified Data.ByteString.Char8 as B+import qualified Data.Double.Conversion.ByteString as B+import qualified Data.Double.Conversion.Text as T import qualified Data.Text as T -shortest a = (read . T.unpack . toShortest) a == a+shortest :: (Double -> String) -> Double -> Double -> Bool+shortest f a b = case read (f ab) of+ ba | isNaN ba -> isNaN ab+ | isInfinite ba -> isInfinite ab && signum ba == signum ab+ | otherwise -> ba == ab+ where ab = a / b +main :: IO () main = defaultMain [- testProperty "shortest" shortest+ testProperty "b_shortest" $ shortest (B.unpack . B.toShortest)+ , testProperty "t_shortest" $ shortest (T.unpack . T.toShortest) ]
− tests/double-conversion-tests.cabal
@@ -1,15 +0,0 @@-name: double-conversion-tests-version: 0-cabal-version: >= 1.8-build-type: Simple--executable qc- main-is: Properties.hs-- build-depends:- QuickCheck,- base,- double-conversion,- test-framework,- test-framework-quickcheck2,- text >= 0.11.0.8