Safe Haskell | Trustworthy |
---|
Floating-point decimals.
This uses the decNumber C library, so you will want to read the documentation about it to fully understand this module:
http://speleotrove.com/decimal/decnumber.html
http://speleotrove.com/decimal/decarith.html
http://speleotrove.com/decimal/
Many of the comments on what these functions do are taken directly from the documentation for the decNumber C library.
In particular, this module implements the decQuad type. decQuad supports up to 34 digits of precision and exponents between -6176 and 6111. It doesn't silently round, overflow, or underflow; rather, the library will notify you if these things happen.
Many functions in this module clash with Prelude names, so you might want to do
import qualified Data.Deka.Quad as Q
- data Quad
- data Round
- roundCeiling :: Round
- roundUp :: Round
- roundHalfUp :: Round
- roundHalfEven :: Round
- roundHalfDown :: Round
- roundDown :: Round
- roundFloor :: Round
- round05Up :: Round
- data Flag
- divisionUndefined :: Flag
- divisionByZero :: Flag
- divisionImpossible :: Flag
- invalidOperation :: Flag
- inexact :: Flag
- underflow :: Flag
- overflow :: Flag
- conversionSyntax :: Flag
- data Flags
- unFlags :: Flags -> [Flag]
- setFlag :: Flag -> Flags -> Flags
- clearFlag :: Flag -> Flags -> Flags
- checkFlag :: Flag -> Flags -> Bool
- emptyFlags :: Flags
- data Ctx a
- getStatus :: Ctx Flags
- setStatus :: Flags -> Ctx ()
- mapStatus :: (Flags -> Flags) -> Ctx ()
- getRound :: Ctx Round
- setRound :: Round -> Ctx ()
- runCtx :: Ctx a -> (a, Flags)
- evalCtx :: Ctx a -> a
- data DecClass
- sNan :: DecClass
- qNan :: DecClass
- negInf :: DecClass
- negNormal :: DecClass
- negSubnormal :: DecClass
- negZero :: DecClass
- posZero :: DecClass
- posSubnormal :: DecClass
- posNormal :: DecClass
- posInf :: DecClass
- decClass :: Quad -> DecClass
- fromByteString :: ByteString -> Ctx Quad
- toByteString :: Quad -> ByteString
- toEngByteString :: Quad -> ByteString
- type C'int32_t = Int32
- type C'uint32_t = Word32
- fromInt32 :: C'int32_t -> Quad
- fromUInt32 :: C'uint32_t -> Quad
- toInt32 :: Round -> Quad -> Ctx C'int32_t
- toInt32Exact :: Round -> Quad -> Ctx C'int32_t
- toUInt32 :: Round -> Quad -> Ctx C'uint32_t
- toUInt32Exact :: Round -> Quad -> Ctx C'uint32_t
- add :: Quad -> Quad -> Ctx Quad
- subtract :: Quad -> Quad -> Ctx Quad
- multiply :: Quad -> Quad -> Ctx Quad
- fma :: Quad -> Quad -> Quad -> Ctx Quad
- divide :: Quad -> Quad -> Ctx Quad
- divideInteger :: Quad -> Quad -> Ctx Quad
- remainder :: Quad -> Quad -> Ctx Quad
- remainderNear :: Quad -> Quad -> Ctx Quad
- quantize :: Quad -> Quad -> Ctx Quad
- reduce :: Quad -> Ctx Quad
- compare :: Quad -> Quad -> Ctx Quad
- compareOrd :: Quad -> Quad -> Maybe Ordering
- compareSignal :: Quad -> Quad -> Ctx Quad
- compareTotal :: Quad -> Quad -> Ordering
- compareTotalMag :: Quad -> Quad -> Ordering
- max :: Quad -> Quad -> Ctx Quad
- maxMag :: Quad -> Quad -> Ctx Quad
- min :: Quad -> Quad -> Ctx Quad
- minMag :: Quad -> Quad -> Ctx Quad
- sameQuantum :: Quad -> Quad -> Bool
- isFinite :: Quad -> Bool
- isInfinite :: Quad -> Bool
- isInteger :: Quad -> Bool
- isLogical :: Quad -> Bool
- isNaN :: Quad -> Bool
- isNegative :: Quad -> Bool
- isNormal :: Quad -> Bool
- isPositive :: Quad -> Bool
- isSignaling :: Quad -> Bool
- isSigned :: Quad -> Bool
- isSubnormal :: Quad -> Bool
- isZero :: Quad -> Bool
- plus :: Quad -> Ctx Quad
- minus :: Quad -> Ctx Quad
- abs :: Quad -> Ctx Quad
- copySign :: Quad -> Quad -> Quad
- nextMinus :: Quad -> Ctx Quad
- nextPlus :: Quad -> Ctx Quad
- nextToward :: Quad -> Quad -> Ctx Quad
- and :: Quad -> Quad -> Ctx Quad
- or :: Quad -> Quad -> Ctx Quad
- xor :: Quad -> Quad -> Ctx Quad
- invert :: Quad -> Ctx Quad
- shift :: Quad -> Quad -> Ctx Quad
- rotate :: Quad -> Quad -> Ctx Quad
- logB :: Quad -> Ctx Quad
- scaleB :: Quad -> Quad -> Ctx Quad
- digits :: Quad -> Int
- toIntegralExact :: Quad -> Ctx Quad
- toIntegralValue :: Round -> Quad -> Ctx Quad
- zero :: Quad
- one :: Quad
- version :: ByteString
- data Digit
- digitToInt :: Integral a => Digit -> a
- intToDigit :: Integral a => a -> Digit
- digitToChar :: Digit -> Char
- digitsToInteger :: [Digit] -> Integer
- integralToDigits :: Integral a => a -> [Digit]
- coefficientLen :: Int
- payloadLen :: Int
- data Coefficient
- coefficient :: [Digit] -> Maybe Coefficient
- unCoefficient :: Coefficient -> [Digit]
- zeroCoefficient :: Coefficient
- oneCoefficient :: Coefficient
- data Payload
- payload :: [Digit] -> Maybe Payload
- unPayload :: Payload -> [Digit]
- zeroPayload :: Payload
- data Exponent
- exponent :: Int -> Maybe Exponent
- unExponent :: Exponent -> Int
- zeroExponent :: Exponent
- minMaxExp :: (Int, Int)
- data AdjustedExp
- adjustedExp :: Coefficient -> Exponent -> AdjustedExp
- unAdjustedExp :: AdjustedExp -> Int
- minNormalAdj :: AdjustedExp
- minNormalExp :: Coefficient -> Exponent
- adjustedToExponent :: Coefficient -> AdjustedExp -> Exponent
- data Sign
- data NaN
- data Value
- data Decoded = Decoded {}
- fromBCD :: Decoded -> Quad
- toBCD :: Quad -> Decoded
- scientific :: Decoded -> String
- ordinary :: Decoded -> String
- decodedToRational :: Decoded -> Maybe Rational
- dIsFinite :: Decoded -> Bool
- dIsInfinite :: Decoded -> Bool
- dIsInteger :: Decoded -> Bool
- dIsLogical :: Decoded -> Bool
- dIsNaN :: Decoded -> Bool
- dIsNegative :: Decoded -> Bool
- dIsNormal :: Decoded -> Bool
- dIsPositive :: Decoded -> Bool
- dIsSignaling :: Decoded -> Bool
- dIsSigned :: Decoded -> Bool
- dIsSubnormal :: Decoded -> Bool
- dIsZero :: Decoded -> Bool
- dDigits :: Coefficient -> Int
- dIsSNaN :: Decoded -> Bool
- dIsQNaN :: Decoded -> Bool
- dIsNegInf :: Decoded -> Bool
- dIsNegNormal :: Decoded -> Bool
- dIsNegSubnormal :: Decoded -> Bool
- dIsNegZero :: Decoded -> Bool
- dIsPosZero :: Decoded -> Bool
- dIsPosSubnormal :: Decoded -> Bool
- dIsPosNormal :: Decoded -> Bool
- dIsPosInf :: Decoded -> Bool
Quad
Decimal number. As indicated in the General Decimal
Arithmetic specification, a Quad
might be a finite number
(perhaps the most common type) or it might be infinite or a
not-a-number. decClass
will tell you a little more about a
particular Quad
.
Rounding
For more on the rounding algorithms, see
Round toward positive infinity.
0.5
rounds up
0.5
rounds to nearest even
0.5
rounds down
Round toward negative infinity.
Flags
For more on possible flags, see
A single error or warning condition that may be set in the
Ctx
.
divisionUndefined :: FlagSource
0/0
is undefined. It sets this flag and returns a quiet NaN.
A non-zero dividend is divided by zero. Unlike 0/0
, it has a
defined result (a signed Infinity).
divisionImpossible :: FlagSource
Sometimes raised by divideInteger
and remainder
.
invalidOperation :: FlagSource
Raised on a variety of invalid operations, such as an attempt
to use compareSignal
on an operand that is an NaN.
conversionSyntax :: FlagSource
A source string (for instance, in fromByteString
) contained
errors.
Ctx monad
The Ctx monad
The General Decimal Arithmetic specification states that most
computations occur within a context
, which affects the manner
in which computations are done (for instance, the context
determines the rounding algorithm). The context also carries
the flags that computations can set (for instance, a computation might
set a flag to indicate that the result is rounded or inexact or
was a division by zero.) The Ctx monad carries this context.
The current status flags, which indicate results from previous computations.
runCtx :: Ctx a -> (a, Flags)Source
By default, rounding is set to roundHalfEven
. No status flags are set
initially. Returns the final status flags along with the result
of the computation.
Class
negSubnormal :: DecClassSource
Negative subnormal number
posSubnormal :: DecClassSource
A positive subnormal number
Converting to and from strings
fromByteString :: ByteString -> Ctx QuadSource
Reads a ByteString, which can be in scientific, engineering, or
"regular" decimal notation. Also reads NaN, Infinity, etc.
Will return a signaling NaN and set invalidOperation
if the
string given is invalid.
In the decNumber C library, this function was called
fromString
; the name was changed here because it doesn't take a
regular Haskell String
.
toByteString :: Quad -> ByteStringSource
toEngByteString :: Quad -> ByteStringSource
Returns a string in engineering notation.
In the decNumber C library, this is called toEngString
; the
name is changed here because the function does not return a
regular Haskell String
.
Converting to and from integers
type C'uint32_t = Word32Source
fromUInt32 :: C'uint32_t -> QuadSource
toInt32 :: Round -> Quad -> Ctx C'int32_tSource
Uses the rounding method given rather than the one in the
Ctx
. If the operand is infinite, an NaN, or if the result of
rounding is outside the range of a C'int32_t
, then
invalidOperation
is set. inexact
is not set even if rounding
occurred.
toUInt32 :: Round -> Quad -> Ctx C'uint32_tSource
toUInt32 r x
returns the value of x
, rounded to an integer
if necessary using the rounding mode r
rather than the one
given in the Ctx
. If x
is infinite, or outside of the range
of a C'uint32_t
, then invalidOperation
is set. inexact
is
not set even if rounding occurs.
The negative zero converts to 0 and is valid, but negative numbers are not valid.
toUInt32Exact :: Round -> Quad -> Ctx C'uint32_tSource
Arithmetic
fma :: Quad -> Quad -> Quad -> Ctx QuadSource
Fused multiply add; fma x y z
calculates x * y + z
. The
multiply is carried out first and is exact, so the result has
only one final rounding.
divideInteger :: Quad -> Quad -> Ctx QuadSource
divideInteger x y
returns the integer part of the result
(rounded toward zero), with an exponent of 0. If the the result
would not fit because it has too many digits,
divisionImpossible
is set.
remainder :: Quad -> Quad -> Ctx QuadSource
Remainder from integer division. If the intermediate integer
does not fit within a Quad, divisionImpossible
is raised.
remainderNear :: Quad -> Quad -> Ctx QuadSource
Like remainder
but the nearest integer is used for for the
intermediate result instead of the result from divideInteger
.
Exponent and coefficient adjustment
quantize :: Quad -> Quad -> Ctx QuadSource
quantize x y
returns z
which is x
set to have the same
quantum as y
; that is, numerically the same value but rounded
or padded if necessary to have the same exponent as y
. Useful
for rounding monetary quantities.
reduce :: Quad -> Ctx QuadSource
Reduces coefficient to its shortest possible form without changing the value of the result by removing all possible trailing zeroes.
Comparisons
compareSignal :: Quad -> Quad -> Ctx QuadSource
Same as compare
, but a quietNaN is treated like a signaling
NaN (sets invalidOperation
).
compareTotal :: Quad -> Quad -> OrderingSource
Compares using an IEEE 754 total ordering, which takes into
account the exponent. IEEE 754 says that this function might
return different results depending upon whether the operands are
canonical; Quad
are always canonical so you don't need to worry
about that here.
compareTotalMag :: Quad -> Quad -> OrderingSource
Same as compareTotal
but compares the absolute value of the
two arguments.
max :: Quad -> Quad -> Ctx QuadSource
max x y
returns the larger argument; if either (but not both)
x
or y
is a quiet NaN then the other argument is the result;
otherwise, NaNs, are handled as for arithmetic operations.
min :: Quad -> Quad -> Ctx QuadSource
min x y
returns the smaller argument; if either (but not both)
x
or y
is a quiet NaN then the other argument is the result;
otherwise, NaNs, are handled as for arithmetic operations.
sameQuantum :: Quad -> Quad -> BoolSource
True only if both operands have the same exponent or are both NaNs (quiet or signaling) or both infinite.
Tests
isInfinite :: Quad -> BoolSource
True for infinities.
isInteger :: Quad -> BoolSource
True if x
is finite and has exponent of 0
; False otherwise.
This tests the exponent, not the adjusted exponent. This can
lead to results you may not expect:
>>>
isInteger . evalCtx . fromByteString . pack $ "3.00e2"
True
>>>
isInteger . evalCtx . fromByteString . pack $ "3e2"
False
>>>
isInteger . evalCtx . fromByteString . pack $ "3.00e0"
False
isLogical :: Quad -> BoolSource
True only if x
is zero or positive, an integer (finite with
exponent of 0), and the coefficient is only zeroes and/or ones.
isNegative :: Quad -> BoolSource
True only if x
is less than zero and is not an NaN.
isPositive :: Quad -> BoolSource
True only if x
is greater than zero and is not an NaN.
isSignaling :: Quad -> BoolSource
True only if x
is a signaling NaN.
isSigned :: Quad -> BoolSource
True only if x
has a sign of 1. Note that zeroes and NaNs
may have sign of 1.
isSubnormal :: Quad -> BoolSource
True only if x
is subnormal - that is, finite, non-zero, and
with a magnitude less than 10 ^ emin.
Signs
plus :: Quad -> Ctx QuadSource
Same effect as 0 + x
where the exponent of the zero is the
same as that of x
if x
is finite). NaNs are handled as for
arithmetic operations.
minus :: Quad -> Ctx QuadSource
Negation. Result has the same effect as 0 - x
when the
exponent of the zero is the same as that of x
, if x
is
finite.
Absolute value. NaNs are handled normally (the sign of an NaN
is not affected, and an sNaN sets invalidOperation
.
copySign :: Quad -> Quad -> QuadSource
copySign x y
returns z
, which is a copy of x
but has the
sign of y
. This function never raises any signals.
Increment and decrement
nextToward :: Quad -> Quad -> Ctx QuadSource
nextToward x y
returns the next Quad
in the direction of
y
.
Digit-wise
and :: Quad -> Quad -> Ctx QuadSource
Digit-wise logical and. Operands must be:
- zero or positive
- integers
- comprise only zeroes and/or ones
If not, invalidOperation
is set.
or :: Quad -> Quad -> Ctx QuadSource
Digit wise logical inclusive Or. Operands must be:
- zero or positive
- integers
- comprise only zeroes and/or ones
If not, invalidOperation
is set.
xor :: Quad -> Quad -> Ctx QuadSource
Digit-wise logical exclusive or. Operands must be:
- zero or positive
- integers
- comprise only zeroes and/or ones
If not, invalidOperation
is set.
invert :: Quad -> Ctx QuadSource
Digit-wise logical inversion. The operand must be:
- zero or positive
- integers
- comprise only zeroes and/or ones
If not, invalidOperation
is set.
shift :: Quad -> Quad -> Ctx QuadSource
shift x y
shifts digits the digits of x to the left (if y
is positive) or right (if y
is negative) without adjusting the
exponent or sign of x
. Any digits shifted in from the left or
right will be 0.
y
is a count of positions to shift; it must be a finite
integer in the range negate
to
coefficientLen
coefficientLen
. NaNs propagate as usual. If x
is infinite
the result is an infinity of the same sign. No status is set
unless y is invalid or the operand is an NaN.
rotate :: Quad -> Quad -> Ctx QuadSource
rotate x y
rotates the digits of x to the left (if y
is
positive) or right (if y
is negative) without adjusting the
exponent or sign of x
. y
is the number of positions to
rotate and must be in the range negate
to
coefficientLen
.
coefficentLen
NaNs are propagated as usual. No status is set unless y
is
invalid or an operand is an NaN.
log and scale
logB :: Quad -> Ctx QuadSource
logB x
Returns the adjusted exponent of x, according to IEEE
754 rules. If x
is infinite, returns +Infinity. If x
is
zero, the result is -Infinity, and divisionByZero
is set. If
x
is less than zero, the absolute value of x
is used. If x
is one, the result is 0. NaNs are propagated as for arithmetic
operations.
scaleB :: Quad -> Quad -> Ctx QuadSource
scaleB x y
calculates x * 10 ^ y
. y
must be an integer
(finite with exponent of 0) in the range of plus or minus 2 *
, typically resulting from
coefficientLen
+ coefficientLen
)logB
. Underflow and overflow might occur; NaNs propagate as
usual.
Attributes
Number of significant digits. If zero or infinite, returns 1. If NaN, returns number of digits in the payload.
Integral rounding
If you want to round but not to an integral value (e.g. round
to two decimal places), see quantize
.
toIntegralExact :: Quad -> Ctx QuadSource
Constants
Identifies the version of the decNumber C library.
Complete encoding and decoding
These convert a Quad
to a Decoded
, which is a pure
Haskell type containing all the information in the Quad
.
Digits
A single decimal digit.
digitToInt :: Integral a => Digit -> aSource
intToDigit :: Integral a => a -> DigitSource
digitToChar :: Digit -> CharSource
digitsToInteger :: [Digit] -> IntegerSource
The most significant digit is at the head of the list.
integralToDigits :: Integral a => a -> [Digit]Source
The most significant digit is at the head of the list. Sign of number is not relevant.
Coefficients
Maximum number of digits in a coefficient.
Maximum number of digits in a payload.
data Coefficient Source
A list of digits, less than or equal to coefficientLen
long.
Corresponds only to finite numbers.
coefficient :: [Digit] -> Maybe CoefficientSource
Creates a Coefficient
. Checks to ensure it is not null and
that it is not longer than coefficientLen
and that it does not
have leading zeroes (if it is 0, a single D0
is allowed).
unCoefficient :: Coefficient -> [Digit]Source
zeroCoefficient :: CoefficientSource
Coefficient of D0
oneCoefficient :: CoefficientSource
Coefficient of D1
A list of digits, less than or equal to payloadLen
long. Accompanies an NaN, potentially with diagnostic
information (I do not know if decNumber actually makes use of
this.)
payload :: [Digit] -> Maybe PayloadSource
Creates a Payload
. Checks to ensure it is not null, not
longer than payloadLen
and that it does not have leading zeroes
(if it is 0, a single D0
is allowed).
Payload of [D0]
Exponents
The signed integer which indicates the power of ten by which the coefficient is multiplied.
exponent :: Int -> Maybe ExponentSource
Ensures that the exponent is within the range allowed by
minMaxExp
.
unExponent :: Exponent -> IntSource
zeroExponent :: ExponentSource
An Exponent whose value is 0.
data AdjustedExp Source
An adjusted exponent is the value of an exponent of a number when that number is expressed as though in scientific notation with one digit before any decimal point. This is the finite exponent + (number of significant digits - 1).
adjustedExp :: Coefficient -> Exponent -> AdjustedExpSource
minNormalAdj :: AdjustedExpSource
The smallest possible adjusted exponent that is still normal. Adjusted exponents smaller than this are subnormal.
minNormalExp :: Coefficient -> ExponentSource
Like minNormalAdj
, but returns the size of the regular exponent
rather than the adjusted exponent.
Sign, NaN, Value, Decoded
A pure Haskell type which holds information identical to that
in a Quad
.
toBCD :: Quad -> DecodedSource
Decodes a Quad
to a pure Haskell type which holds identical
information.
scientific :: Decoded -> StringSource
Converts a Decoded to scientific notation. Unlike
toByteString
this will always use scientific notation. For
NaNs and infinities, the notation is identical to that of
decNumber (see Decimal Arithmetic Specification page 19). This
means that a quiet NaN is NaN
while a signaling NaN is sNaN
,
and infinity is Infinity
.
Like decQuadToString, the payload of an NaN is not shown if it is zero.
ordinary :: Decoded -> StringSource
Converts Decoded to ordinary decimal notation. For NaNs and
infinities, the notation is identical to that of scientific
.
Unlike scientific
, though the result can always be converted back
to a Quad
using fromByteString
, the number of significant
digits might change. For example, though 1.2E3
has two
significant digits, using ordinary
on this value and then
reading it back in with fromByteString
will give you 1200E0
,
which has four significant digits.
decodedToRational :: Decoded -> Maybe RationalSource
Converts a Decoded to a Rational. Returns Nothing if the Decoded is not finite.
Decoded predicates
Duplicates of Quad tests that return Bool
These duplicate the tests that are available for the Quad type directly.
dIsInfinite :: Decoded -> BoolSource
dIsInteger :: Decoded -> BoolSource
dIsLogical :: Decoded -> BoolSource
True only if x
is zero or positive, an integer (finite with
exponent of 0), and the coefficient is only zeroes and/or ones.
The sign must be Sign0 (that is, you cannot have a negative
zero.)
dIsNegative :: Decoded -> BoolSource
True only if x
is less than zero and is not an NaN. It's not
enough for the sign to be Sign1; the coefficient (if finite) must
be greater than zero.
dIsPositive :: Decoded -> BoolSource
dIsSignaling :: Decoded -> BoolSource
dIsSubnormal :: Decoded -> BoolSource
dDigits :: Coefficient -> IntSource
The number of significant digits. Zero returns 1.
Duplicates of Quad tests that return DecClass
dIsNegNormal :: Decoded -> BoolSource
dIsNegSubnormal :: Decoded -> BoolSource
dIsNegZero :: Decoded -> BoolSource
dIsPosZero :: Decoded -> BoolSource
dIsPosSubnormal :: Decoded -> BoolSource
dIsPosNormal :: Decoded -> BoolSource