floatshow-0.2.0: Alternative faster String representations for Double and Float, String representations for more general numeric types.

Portabilitynon-portable (GHC extensions)
Stabilityexperimental
MaintainerDaniel Fischer <daniel.is.fischer@googlemail.com>

Text.FShow.Raw

Contents

Description

Lower level conversion of base-2 numbers to base-10 representations. These functions can be used to define Show instances for types which don't support the full RealFloat interface but have an analogue to decodeFloat (and maybe to isNaN, isInfinite and isNegativeZero).

Synopsis

Classes

class BinDecode a whereSource

Class for types whose values can be decoded into the form m * 2^e with an Integer mantissa m and an Int exponent e.

Minimal complete definition: one of decode and decodeL.

It is strongly recommended to override the default implementation of showDigits if the datatype allows distinguishing values without using an exact representation.

Methods

decode :: a -> (Integer, Int)Source

decode is analogous to decodeFloat.

decodeL :: a -> (Int, Integer, Int)Source

decodeL gives the integer base-2 logarithm of the mantissa in addition to the result of decode. If the absolute value of the mantissa always has the same highest set bit (excepting 0), specifying that as a constant will be faster than calculating the logarithm for each individual mantissa. If x = m*2^e with m /= 0, then decodeL x == (integerLog2 (abs m), m, e) must hold.

showDigits :: a -> IntSource

The number of significant digits needed to uniquely determine the value (or however many digits are desired). Usually, showDigits will be a constant function, but that is not necessary. However, all values of showDigits must be positive.

If the mantissa always has the same highest bit, highBit, set when it is nonzero,

   showDigits _ = 2 + floor ((highBit+1) * 'logBase 10 2)

is sufficient to make the values and formatted Strings uniquely determine each other and in general this is the smallest number to achieve that (calculate the number once and supply the result as a constant).

If the highest set bit of nonzero mantissae varies, things are not so easy. If the width of mantissae is bounded, plugging the largest possible value into the above formula works, but may yield an unduly large number for common cases. Using the formula with highBit determined by the mantissa almost works, but if the representation is rounded at all, with sufficiently many bits in the mantissa, there will be values between the original and the representation. So, with mantissae of width varying over a large range, the only feasible way of obtaining a bijection between values and their decimal representations is printing to full precision in general, optionally capping atthe upper limit.

The default implementation prints values exactly, which in general is undesirable because it involves huge Integers and long representations.

class (Num a, Ord a, BinDecode a) => DecimalFormat a whereSource

Class for types whose values may be NaN or infinite and can otherwise be decoded into the form m * 2^e.

Methods

nanTest :: a -> BoolSource

nanTest defaults to const False

infTest :: a -> BoolSource

infTest defaults to const False

negTest :: a -> BoolSource

negTest x defaults to x < 0, it must be overridden if negative zero has to be accounted for.

Format type

data FormatStyle Source

The Style in which to format the display String

Constructors

Exponent

Display in scientific notation, e.g. 1.234e-5

Fixed

Display in standard decimal notation, e.g. 0.0123 or 123.456

Generic (Maybe (Int, Int))

Use Fixed for numbers with magnitude close enough to 1, Exponent otherwise. The default range for using Fixed is 0.1 <= |x| < 10^7, corresponding to Generic (Just (-1,7)).

Functions

Medium level

decimalFormat :: DecimalFormat a => FormatStyle -> Maybe Int -> a -> StringSource

decimalFormat is a slightly higher-level formatter, treating the special cases of NaN and infinities.

binDecFormat :: BinDecode a => FormatStyle -> Maybe Int -> a -> StringSource

binDecFormat is the formatter for instances of the BinDecode class. Any special values must be processed before it is called. It fills in the missing arguments before calling rawFormat.

Low level

rawFormatSource

Arguments

:: (a -> (Int, Integer, Int))

decoder, same restrictions as decodeL

-> Int

number of significant digits

-> FormatStyle

formatting style

-> Maybe Int

desired precision

-> a

value to be displayed

-> String 

rawFormat is a low-level formatter. The sign is determined from the sign of the mantissa.

fullRawFormatSource

Arguments

:: (a -> (Int, Integer, Int))

decoder, same restriction as decodeL

-> FormatStyle

formatting style

-> a

value to be displayed

-> String 

fullRawFormat is a low-level formatter producing an exact representation of a value which can be decoded into the form m * 2^e.

formatDigitsSource

Arguments

:: FormatStyle

formatting style

-> Int

number of significant digits required

-> Maybe Int

desired precision

-> [Int]

list of significant digits

-> Int

base-10 logarithm

-> String 

formatDigits builds the display String from the digits and the exponent of a nonnegative number.

Dangerous

posToDigitsSource

Arguments

:: Int

number of digits required

-> Int

base 2 logarithm of the mantissa

-> Integer

mantissa

-> Int

scaling exponent

-> ([Int], Int) 

posToDigits converts a positive number into a list of digits and an exponent. If x = 10^e*d_1.d_2...d_m... with d_1 /= 0 and 0 <= d_i <= 9, the result is ([d_1,d_2,...,d_m],e), where m is one or two larger than the number of requested digits, provided that 2^(-70776) <= x < 2^248236 (with 64-bit Ints, the upper bound is about 2^1.3e9).

The number x is (indirectly) given in the form mantissa * 2^exponent, similar to encodeFloat, as the final two arguments. The second argument is the base-2 logarithm of the mantissa and the first is the number of decimal digits needed to discriminate between different numbers.

In posToDigits digs mlog mant exp, it is assumed that

  • digs > 0, mlog >= 0,
  • 2^mlog <= mant < 2^(mlog+1).

These assumptions are not checked, and if they're not satisfied, wrong results or worse are the consequences. You have been warned.

The digits argument may be smaller than would be necessary to uniquely determine each value if that is not required. As a rule of thumb, requiring fewer significant digits means faster generation of the representation.

Auxiliary

fullDecimalDigits :: Int -> Int -> IntSource

fullDecimalDigits a e calculates the number of decimal digits that may be required to exactly display a value x = m * 2^e where m is an Integer satisfying 2^a <= m < 2^(a+1). Usually, the calculated value is not much larger than the actual number of digits in the exact decimal representation, but it will be if the exponent e is negative and has large absolute value and the mantissa is divisible by a large power of 2.

integerLog2 :: Integer -> IntSource

Integer base-2 logarithm of a positive Integer.