Commits

dafis  committed 864e67b

Version 0.1 of the floatshow package

floatshow provides faster conversions to String for Double and Float than the Show instances.

  • Participants

Comments (0)

Files changed (8)

+0.1:    First release
+
+The Glasgow Haskell Compiler License
+
+Copyright 2004, The University Court of the University of Glasgow.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+- Neither name of the University nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF
+GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+Copyright (c)2011, Daniel Fischer
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Daniel Fischer nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+The Show instances for RealFloat types provided in base are very elegant, as they produce the shortest string
+import Distribution.Simple
+main = defaultMain

File Text/FShow/RealFloat.hs

+-- |
+-- Module:      Text.FShow.RealFloat
+-- Copyright:   (c) 2011 Daniel Fischer
+-- Licence:     BSD3
+-- Maintainer:  Daniel Fischer
+-- Stability:   experimental
+-- Portability: non-portable (GHC extensions)
+--
+-- Faster 'String' representations for floating point types.
+-- The code is largely taken from code in "GHC.Float" and the 'Show'
+-- instance of 'Integer' in "GHC.Num" to get the sequence of digits.
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module Text.FShow.RealFloat
+    ( FShow(..)
+    , fshows
+    , DispFloat(..)
+    , fshowFloat
+    , fshowEFloat
+    , fshowFFloat
+    , fshowGFloat
+    , Double7(..)
+    , Float7(..)
+    ) where
+
+import GHC.Show
+import GHC.Float (showSignedFloat)
+import Text.FShow.RealFloat.Internals
+
+-- | Class for specifying display parameters. The type @a@
+--   is supposed to be an IEEE-ish (real) floating-point
+--   type with floating-point radix 2, such that the mantissa
+--   returned by 'decodeFloat' satisfies
+--
+-- > 2^(binExp x) <= fst (decodeFloat x) < 2^(binExp x + 1)
+--
+--   for @x > 0@, so @'binExp' x = 'floatDigits' x - 1@.
+--   The number of decimal digits that may be required is calculated
+--   with the formula
+--
+-- > decDigits x = 2 + floor (floatDigits x * logBase 10 2).
+--
+--   The default implementation uses an approximation of
+--   @'logBase' 10 2@ sufficient for mantissae of up to
+--   several thousand bits. Nevertheless, hardcoding
+--   the values in instance declarations may yield
+--   better performance.
+class (RealFloat a) => DispFloat a where
+  -- | The number of decimal digits that may be needed to
+  --   uniquely determine a value of type @a@.
+  --   For faster conversions which need not satisfy
+  --
+  -- > x == read (fshow x)
+  --
+  --   a smaller value can be given.
+  decDigits     :: a -> Int
+  decDigits x   = 2 + (8651*(floatDigits x)) `quot` 28738
+  -- | The base 2 logarithm of the mantissa returned by
+  --   @'decodeFloat' x@ for @x > 0@.
+  binExp        :: a -> Int
+  binExp x      = floatDigits x - 1
+
+instance DispFloat Double where
+  decDigits _   = 17
+  binExp _      = 52
+
+instance DispFloat Float where
+  decDigits _   = 9
+  binExp _      = 23
+
+-- | newtype wrapper for 'Double'. The 'Show' (and 'FShow') instance
+--   displays numbers rounded to seven significant digits.
+newtype Double7 = D7 Double
+  deriving (Eq, Ord, Num, Fractional, Real, RealFrac, Floating, RealFloat)
+
+instance DispFloat Double7 where
+  decDigits _ = 7
+  binExp    _ = 52
+
+instance Show Double7 where
+  showsPrec p   = showSignedFloat fshowFloat p
+
+instance FShow Double7 where
+  fshowsPrec p  = showSignedFloat fshowFloat p
+  fshowList     = showList__ (fshowsPrec 0)
+
+-- | newtype wrapper for 'Float'. The 'Show' (and 'FShow') instance
+--   displays numbers rounded to seven significant digits.
+newtype Float7 = F7 Float
+  deriving (Eq, Ord, Num, Fractional, Real, RealFrac, Floating, RealFloat)
+
+instance DispFloat Float7 where
+  decDigits _ = 7
+  binExp    _ = 23
+
+instance Show Float7 where
+  showsPrec p   = showSignedFloat fshowFloat p
+
+instance FShow Float7 where
+  fshowsPrec p  = showSignedFloat fshowFloat p
+  fshowList     = showList__ (fshowsPrec 0)
+
+{-
+    The code below is a minor modification of code from GHC.Float
+    and Numeric from the base package. The GHC Licence is included
+    in the package root.
+-}
+
+-- | A duplicate of the 'Show' class.
+class FShow a where
+  fshow             :: a -> String
+  fshowsPrec        :: Int -> a -> ShowS
+  fshowList         :: [a] -> ShowS
+  fshow x           = fshowsPrec 0 x ""
+  fshowsPrec _ x s  = fshow x ++ s
+  fshowList xs s    = showList__ fshows xs s
+
+-- | Same as @'shows'@, but using an 'FShow' instance.
+fshows :: FShow a => a -> ShowS
+fshows x = showString (fshow x)
+
+instance FShow Double where
+  fshowsPrec p  = showSignedFloat fshowFloat p
+  fshowList     = showList__ (fshowsPrec 0)
+
+instance FShow Float where
+  fshowsPrec p  = showSignedFloat fshowFloat p
+  fshowList     = showList__ (fshowsPrec 0)
+
+instance (FShow a) => FShow [a] where
+  fshowsPrec _ = fshowList
+
+{-# SPECIALISE fshowFloat ::
+        Float   -> ShowS,
+        Float7  -> ShowS,
+        Double7 -> ShowS,
+        Double  -> ShowS #-}
+-- | Show a signed 'DispFloat' value to full precision
+-- using standard decimal notation for arguments whose absolute value lies
+-- between @0.1@ and @9,999,999@, and scientific notation otherwise.
+-- Analogous to @'showFloat'@ from "GHC.Float".
+fshowFloat :: (DispFloat a) => a -> ShowS
+fshowFloat x  =  showString (formatFloat FFGeneric Nothing x)
+
+{-# SPECIALISE fshowEFloat ::
+        Maybe Int -> Float   -> ShowS,
+        Maybe Int -> Float7  -> ShowS,
+        Maybe Int -> Double7 -> ShowS,
+        Maybe Int -> Double  -> ShowS #-}
+{-# SPECIALISE fshowFFloat ::
+        Maybe Int -> Float   -> ShowS,
+        Maybe Int -> Float7  -> ShowS,
+        Maybe Int -> Double7 -> ShowS,
+        Maybe Int -> Double  -> ShowS #-}
+{-# SPECIALISE fshowGFloat ::
+        Maybe Int -> Float   -> ShowS,
+        Maybe Int -> Float7  -> ShowS,
+        Maybe Int -> Double7 -> ShowS,
+        Maybe Int -> Double  -> ShowS #-}
+
+-- | Show a signed 'DispFloat' value
+-- using scientific (exponential) notation (e.g. @2.45e2@, @1.5e-3@).
+--
+-- In the call @'fshowEFloat' digs val@, if @digs@ is 'Nothing',
+-- the value is shown to full precision; if @digs@ is @'Just' d@,
+-- then @'max' 1 d@ digits after the decimal point are shown.
+-- Analogous to @'showEFloat'@ from "Numeric".
+fshowEFloat    :: (DispFloat a) => Maybe Int -> a -> ShowS
+fshowEFloat d x =  showString (formatFloat FFExponent d x)
+
+-- | Show a signed 'DispFloat' value
+-- using standard decimal notation (e.g. @245000@, @0.0015@).
+--
+-- In the call @'fshowFFloat' digs val@, if @digs@ is 'Nothing',
+-- the value is shown to full precision; if @digs@ is @'Just' d@,
+-- then @'max' 0 d@ digits after the decimal point are shown.
+-- Analogous to @'showFFloat'@ from "Numeric".
+fshowFFloat    :: (DispFloat a) => Maybe Int -> a -> ShowS
+fshowFFloat d x =  showString (formatFloat FFFixed d x)
+
+-- | Show a signed 'DispFloat' value
+-- using standard decimal notation for arguments whose absolute value lies
+-- between @0.1@ and @9,999,999@, and scientific notation otherwise.
+--
+-- In the call @'fshowGFloat' digs val@, if @digs@ is 'Nothing',
+-- the value is shown to full precision; if @digs@ is @'Just' d@,
+-- then @'max' 1 d@ digits after the decimal point are shown.
+-- Analogous to @'showGFloat'@ from "Numeric".
+fshowGFloat    :: (DispFloat a) => Maybe Int -> a -> ShowS
+fshowGFloat d x =  showString (formatFloat FFGeneric d x)
+
+data FFFormat = FFExponent | FFFixed | FFGeneric
+
+{-# SPECIALISE formatFloat :: FFFormat -> Maybe Int -> Double -> String,
+                              FFFormat -> Maybe Int -> Float -> String,
+                              FFFormat -> Maybe Int -> Double7 -> String,
+                              FFFormat -> Maybe Int -> Float7 -> String
+  #-}
+formatFloat :: DispFloat a => FFFormat -> Maybe Int -> a -> String
+formatFloat fmt decs x
+    | isNaN x                   = "NaN"
+    | isInfinite x              = if x < 0 then "-Infinity" else "Infinity"
+    | x < 0 || isNegativeZero x = '-':doFmt fmt (fltDigs (-x))
+    | otherwise                 = doFmt fmt (fltDigs x)
+      where
+        fltDigs 0 = ([0],0)
+        fltDigs y = uncurry (posToDigits (decDigits y) (binExp y)) (decodeFloat y)
+        fluff :: [Int] -> [Int]
+        fluff [] = [0]
+        fluff xs = xs
+
+        doFmt format (is, e) =
+          case format of
+            FFGeneric ->
+              doFmt (if e < 0 || e > 7 then FFExponent else FFFixed) (is,e)
+            FFExponent ->
+              case decs of
+                Nothing ->
+                  let show_e' = if ei == 0 then show (e-1) else show e
+                      (ei,(d:ds)) = roundToS (decDigits x) is
+                  in case is of
+                       [0] -> "0.0e0"
+                       _ -> i2D d : '.' : map i2D (fluff ds) ++ ('e' : show_e')
+                Just dec ->
+                  let dec' = max dec 1 in
+                  case is of
+                    [0] -> '0' :'.' : take dec' (repeat '0') ++ "e0"
+                    _ -> let (ei,is') = roundTo (dec'+1) is
+                             (d:ds') = map i2D (if ei > 0 then init is' else is')
+                         in d:'.':ds' ++ 'e':show (e-1+ei)
+            FFFixed ->
+              let mk0 ls = case ls of { "" -> "0" ; _ -> ls} in
+              case decs of
+                Nothing ->
+                  let (ei, is') = roundToS (decDigits x) is
+                      e' = e+ei
+                      ds = map i2D is'
+                  in case is of
+                       [0] -> "0.0"
+                       _ | e' <= 0 -> "0." ++ replicate (-e') '0' ++ map i2D is'
+                         | otherwise ->
+                           let f 0 s    rs  = mk0 (reverse s) ++ '.':mk0 rs
+                               f n s    ""  = f (n-1) ('0':s) ""
+                               f n s (r:rs) = f (n-1) (r:s) rs
+                           in f e' "" ds
+                Just dec ->
+                  let dec' = max dec 0 in
+                  if e >= 0 then
+                     let (ei,is') = roundTo (dec' + e) is
+                         (ls,rs)  = splitAt (e+ei) (map i2D is')
+                     in mk0 ls ++ (if null rs then "" else '.':rs)
+                  else
+                     let (ei,is') = roundTo dec' (replicate (-e) 0 ++ is)
+                         d:ds' = map i2D (if ei > 0 then is' else 0:is')
+                     in d : (if null ds' then "" else '.':ds')
+
+roundToS :: Int -> [Int] -> (Int,[Int])
+roundToS d is =
+    case f d is of
+      x@(0,_) -> x
+      (1,xs)  -> (1, 1:xs)
+      _       -> error "roundToS: bad Value"
+  where
+    f _ []          = (0, [])
+    f 0 (x:_)       = (if x >= 5 then 1 else 0, [])
+    f n (i:xs)
+      | i' == 10    = (1,prep 0 ds)
+      | otherwise   = (0,prep i' ds)
+        where
+          prep 0 [] = []
+          prep a bs = a:bs
+          (c,ds)    = f (n-1) xs
+          i'        = c + i
+
+roundTo :: Int -> [Int] -> (Int,[Int])
+roundTo d is =
+    case f d is of
+      x@(0,_) -> x
+      (1,xs)  -> (1, 1:xs)
+      _       -> error "roundTo: bad Value"
+  where
+    f n []          = (0, replicate n 0)
+    f 0 (x:_)       = (if x >= 5 then 1 else 0, [])
+    f n (i:xs)
+      | i' == 10    = (1,0:ds)
+      | otherwise   = (0,i':ds)
+        where
+          (c,ds)    = f (n-1) xs
+          i'        = c + i

File Text/FShow/RealFloat/Internals.hs

+-- |
+-- Module:          Text.FShow.RealFloat.Internals
+-- Copyright:       (c) 2011 Daniel Fischer
+-- Licence:         BSD3
+-- Maintainer:      Daniel Fischer <daniel.is.fischer@googlemail.com>
+-- Stability:       experimental
+-- Portability:     non-portable (GHC extensions)
+--
+-- Faster digit string generation for floating point numbers.
+-- Uses a modification of the Integer showing code from "GHC.Num".
+{-# LANGUAGE CPP, BangPatterns, MagicHash, UnboxedTuples #-}
+{-# OPTIONS_HADDOCK hide #-}
+module Text.FShow.RealFloat.Internals
+    ( posToDigits
+    , i2D
+    ) where
+
+#include "MachDeps.h"
+
+import GHC.Base
+import GHC.Num (quotRemInt)
+import GHC.Integer
+import Data.Array.Base (unsafeAt)
+import Data.Array.IArray
+
+
+#if WORD_SIZE_IN_BITS == 32
+#define DIGITS       9
+#define BASE         1000000000
+#else
+#define DIGITS       18
+#define BASE         1000000000000000000
+#endif
+
+-- unsafe Int -> Char conversion for decimal digits
+{-# INLINE i2D #-}
+i2D :: Int -> Char
+i2D (I# i#) = C# (chr# (ord# '0'# +# i#))
+
+-- digits and exponent for a floating point number.
+-- floatRadix is assumed to be 2, decodeFloat to return
+-- a mantissa 2^(floatDigits-1) <= mantissa < 2^floatDigits
+posToDigits :: Int -> Int -> Integer -> Int -> ([Int],Int)
+posToDigits showDigs mantExp mant scaleExp@(I# e#) = (integerToDigits decMant, e10)
+  where
+    !rex = mantExp + scaleExp
+    !l0 = (8651*rex) `quot` 28738
+    !l10 = if rex < 0 then l0-1 else l0
+    -- 10^l10 <= x < 10^(l10+2)
+    !decshift@(I# d#) = showDigs - l10
+    !binshift = e# +# d#
+    !decMant
+        | d# <# 0# =
+            shiftLInteger mant binshift `quot` expt5 (I# (negateInt# d#))
+        | binshift <# 0# =
+            shiftRInteger (mant * expt5 decshift) (negateInt# binshift)
+        | otherwise = shiftLInteger (mant * expt5 decshift) binshift
+    !e10 = if decMant < expt10 (showDigs+1) then l10+1 else l10+2
+
+expt5 :: Int -> Integer
+expt5 k = if k <= maxEx5 && k >= 0 then unsafeAt expts5 k else 5^k
+
+expt10 :: Int -> Integer
+expt10 k = if k <= maxEx10 && k >= 0 then unsafeAt expts10 k else 10^k
+
+maxEx5 :: Int
+maxEx5 = 349
+
+maxEx10 :: Int
+maxEx10 = 25
+
+expts5 :: Array Int Integer
+expts5 = array (0, maxEx5) [(k,5^k) | k <- [0 .. maxEx5]]
+
+expts10 :: Array Int Integer
+expts10 = array (0,maxEx10) [(k,10^k) | k <- [0 .. maxEx10]]
+
+------------------------------------------------------------------------------
+--  The code to show Integers, modified to produce [Int] instead of [Char]
+--  Taken from GHC.Num and modified to suit our needs
+--  The GHC Licence is reproduced in the package root
+
+-- Divide and conquer implementation
+-- generate the sequence of digits of a positive Integer
+integerToDigits :: Integer -> [Int]
+integerToDigits nm
+    | nm < BASE = jhead (fromInteger nm) []
+    | otherwise = jprinth (jsplitf (BASE*BASE) nm) []
+      where
+
+        -- Split n into digits in base p. We first split n into digits
+        -- in base p*p and then split each of these digits into two.
+        -- Note that the first 'digit' modulo p*p may have a leading zero
+        -- in base p that we need to drop - this is what jsplith takes care of.
+        -- jsplitb the handles the remaining digits.
+        jsplitf :: Integer -> Integer -> [Integer]
+        jsplitf p n
+            | p > n     = [n]
+            | otherwise = jsplith p (jsplitf (p*p) n)
+
+        jsplith :: Integer -> [Integer] -> [Integer]
+        jsplith p (n:ns) =
+            case n `quotRemInteger` p of
+            (# q, r #) ->
+                if q > 0 then q : r : jsplitb p ns
+                        else     r : jsplitb p ns
+        jsplith _ [] = error "jsplith: []"
+
+        jsplitb :: Integer -> [Integer] -> [Integer]
+        jsplitb _ []     = []
+        jsplitb p (n:ns) = case n `quotRemInteger` p of
+                        (# q, r #) ->
+                            q : r : jsplitb p ns
+
+        -- Convert a number that has been split into digits in base BASE^2
+        -- this includes a last splitting step and then conversion of digits
+        -- that all fit into a machine word.
+        jprinth :: [Integer] -> [Int] -> [Int]
+        jprinth (n:ns) cs =
+            case n `quotRemInteger` BASE of
+            (# q', r' #) ->
+                let q = fromInteger q'
+                    r = fromInteger r'
+                in if q > 0 then jhead q $ jblock r $ jprintb ns cs
+                            else jhead r $ jprintb ns cs
+        jprinth [] _ = error "jprinth []"
+
+        jprintb :: [Integer] -> [Int] -> [Int]
+        jprintb []     cs = cs
+        jprintb (n:ns) cs = case n `quotRemInteger` BASE of
+                            (# q', r' #) ->
+                                let q = fromInteger q'
+                                    r = fromInteger r'
+                                in jblock q $ jblock r $ jprintb ns cs
+
+        -- Convert an integer that fits into a machine word. Again, we have two
+        -- functions, one that drops leading zeros (jhead) and one that doesn't
+        -- (jblock)
+        jhead :: Int -> [Int] -> [Int]
+        jhead n cs
+            | n < 10    = n:cs
+            | otherwise = jhead q (r : cs)
+            where
+            (q, r) = n `quotRemInt` 10
+
+        jblock = jblock' {- ' -} DIGITS     -- bloody CPP
+
+        jblock' :: Int -> Int -> [Int] -> [Int]
+        jblock' d n cs
+            | d == 1    = n : cs
+            | otherwise = jblock' (d - 1) q (r : cs)
+            where
+            (q, r) = n `quotRemInt` 10

File floatshow.cabal

+-- floatshow.cabal auto-generated by cabal init. For additional
+-- options, see
+-- http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#pkg-descr.
+-- The name of the package.
+Name:                floatshow
+
+-- The package version. See the Haskell package versioning policy
+-- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for
+-- standards guiding when and how versions should be incremented.
+Version:             0.1
+
+-- Constraint on the version of Cabal needed to build this package.
+Cabal-version:       >=1.6
+
+-- A short (one-line) description of the package.
+Synopsis:            Alternative faster String representations for Double and Float
+
+-- A longer description of the package.
+Description:         The String representations provided by this package
+                     are generally longer than show's output, which constructs
+                     the shortest string that is parsed as the original
+                     number by read. This requires some time-consuming checks,
+                     so show is slow for floating-point numbers. By producing
+                     a digit-string guaranteed to be long enough to uniquely
+                     determine the number without caring whether there's a
+                     shorter representation, the display functions of this
+                     package can be faster. However, the longer representaions
+                     mean that reading is slower.
+
+                     The bulk of the code is a minor modification of code from
+                     the base package, whence the GHC License is included as
+                     an extra-source-file.
+
+-- URL for the project homepage or repository.
+Homepage:            https://bitbucket.org/dafis/floatshow
+Bug-reports:         https://bitbucket.org/dafis/floatshow/issues
+
+-- The license under which the package is released.
+License:             BSD3
+
+-- The file containing the license text.
+License-file:        LICENSE
+
+-- The package author(s).
+Author:              Daniel Fischer
+
+-- An email address to which users can send suggestions, bug reports,
+-- and patches.
+Maintainer:          daniel.is.fischer@googlemail.com
+
+-- A copyright notice.
+Copyright:           (c) 2011 Daniel Fischer
+
+Category:            Text
+
+Build-type:          Simple
+
+-- Extra files to be distributed with the package, such as examples or
+-- a README.
+Extra-source-files:  GHC_LICENCE
+                     README
+                     Changes
+
+Flag gmp
+  Description:       Use integer-gmp
+  Default:           True
+
+Library
+  -- Modules exported by the library.
+  Exposed-modules:   Text.FShow.RealFloat
+
+  -- Packages needed in order to build this package.
+  Build-depends:     base >= 4 && < 5, array >= 0.1 && < 0.4
+  if flag(gmp)
+    Build-depends:   integer-gmp
+  else
+    Build-depends:   integer-simple
+
+  -- Modules not exported by this package.
+  Other-modules:     Text.FShow.RealFloat.Internals
+
+  -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.
+  -- Build-tools:
+  -- Extensions:        CPP, MagicHash, UnboxedTuples, BangPatterns
+  ghc-options:       -O2 -fspec-constr-count=5 -Wall
+
+source-repository head
+  type:     mercurial
+  location: https://bitbucket.org/dafis/floatshow