{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
module Numeric.Decimal.Internal
  ( Decimal(..)
  , Round(..)
  , wrapDecimal
  , unwrapDecimal
  , splitDecimal
  , decimalNumerator
  , decimalDenominator
  , getScale
  , scaleUp
  , scaleUpBounded
  , castRounding
  , parseDecimalBounded
  -- * Decimal Arithmetic
  -- ** Integer
  , absDecimal
  , signumDecimal
  , plusDecimal
  , minusDecimal
  , timesDecimal
  , timesDecimalWithoutLoss
  , timesDecimalWithRounding
  , divideDecimalWithoutLoss
  , divideDecimalWithRounding

  , fromIntegerDecimal
  , fromRationalDecimalWithoutLoss
  , fromRationalDecimalWithRounding
  , toRationalDecimal
  -- ** Bounded Integral
  , absDecimalBounded
  , signumDecimalBounded
  , plusDecimalBounded
  , minusDecimalBounded
  , timesDecimalBounded
  , timesDecimalBoundedWithoutLoss
  , timesDecimalBoundedWithRounding

  , divideDecimalBoundedWithoutLoss
  , divideDecimalBoundedWithRounding

  , fromIntegralDecimalBounded
  , integralDecimalToDecimalBounded
  , quotRemDecimalBounded
  , fromIntegerDecimalBounded
  , fromIntegerDecimalBoundedIntegral
  , fromRationalDecimalBoundedWithoutLoss
  , fromRationalDecimalBoundedWithRounding
  , bindM2Decimal
  , bindM2
  -- ** Evaluation failure
  , MonadThrow(..)
  , ArithException(..)
  , SomeException
  , arithD
  , arithMD
  , arithMaybeD
  , arithEitherD
  , arithRoundD
  ) where

import Control.Applicative
import Control.DeepSeq
import Control.Exception
import Control.Monad
import Control.Monad.Catch
import Data.Char
import Data.Coerce
import Data.Foldable as F
import Data.Int
import Data.List
import Data.Proxy
import Data.Ratio
import Data.Word
import Numeric.Decimal.BoundedArithmetic
import GHC.Generics (Generic)
import GHC.TypeLits
import Text.Printf

-- | Decimal number with custom precision (@p@) and type level scaling (@s@) parameter (i.e. number
-- of digits after the decimal point). As well as the rounding (@r@) strategy to use.
newtype Decimal r (s :: Nat) p = Decimal p
  deriving (Eq (Decimal r s p)
Eq (Decimal r s p)
-> (Decimal r s p -> Decimal r s p -> Ordering)
-> (Decimal r s p -> Decimal r s p -> Bool)
-> (Decimal r s p -> Decimal r s p -> Bool)
-> (Decimal r s p -> Decimal r s p -> Bool)
-> (Decimal r s p -> Decimal r s p -> Bool)
-> (Decimal r s p -> Decimal r s p -> Decimal r s p)
-> (Decimal r s p -> Decimal r s p -> Decimal r s p)
-> Ord (Decimal r s p)
Decimal r s p -> Decimal r s p -> Bool
Decimal r s p -> Decimal r s p -> Ordering
Decimal r s p -> Decimal r s p -> Decimal r s p
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall r (s :: Nat) p. Ord p => Eq (Decimal r s p)
forall r (s :: Nat) p.
Ord p =>
Decimal r s p -> Decimal r s p -> Bool
forall r (s :: Nat) p.
Ord p =>
Decimal r s p -> Decimal r s p -> Ordering
forall r (s :: Nat) p.
Ord p =>
Decimal r s p -> Decimal r s p -> Decimal r s p
min :: Decimal r s p -> Decimal r s p -> Decimal r s p
$cmin :: forall r (s :: Nat) p.
Ord p =>
Decimal r s p -> Decimal r s p -> Decimal r s p
max :: Decimal r s p -> Decimal r s p -> Decimal r s p
$cmax :: forall r (s :: Nat) p.
Ord p =>
Decimal r s p -> Decimal r s p -> Decimal r s p
>= :: Decimal r s p -> Decimal r s p -> Bool
$c>= :: forall r (s :: Nat) p.
Ord p =>
Decimal r s p -> Decimal r s p -> Bool
> :: Decimal r s p -> Decimal r s p -> Bool
$c> :: forall r (s :: Nat) p.
Ord p =>
Decimal r s p -> Decimal r s p -> Bool
<= :: Decimal r s p -> Decimal r s p -> Bool
$c<= :: forall r (s :: Nat) p.
Ord p =>
Decimal r s p -> Decimal r s p -> Bool
< :: Decimal r s p -> Decimal r s p -> Bool
$c< :: forall r (s :: Nat) p.
Ord p =>
Decimal r s p -> Decimal r s p -> Bool
compare :: Decimal r s p -> Decimal r s p -> Ordering
$ccompare :: forall r (s :: Nat) p.
Ord p =>
Decimal r s p -> Decimal r s p -> Ordering
$cp1Ord :: forall r (s :: Nat) p. Ord p => Eq (Decimal r s p)
Ord, Decimal r s p -> Decimal r s p -> Bool
(Decimal r s p -> Decimal r s p -> Bool)
-> (Decimal r s p -> Decimal r s p -> Bool) -> Eq (Decimal r s p)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall r (s :: Nat) p.
Eq p =>
Decimal r s p -> Decimal r s p -> Bool
/= :: Decimal r s p -> Decimal r s p -> Bool
$c/= :: forall r (s :: Nat) p.
Eq p =>
Decimal r s p -> Decimal r s p -> Bool
== :: Decimal r s p -> Decimal r s p -> Bool
$c== :: forall r (s :: Nat) p.
Eq p =>
Decimal r s p -> Decimal r s p -> Bool
Eq, Decimal r s p -> ()
(Decimal r s p -> ()) -> NFData (Decimal r s p)
forall a. (a -> ()) -> NFData a
forall r (s :: Nat) p. NFData p => Decimal r s p -> ()
rnf :: Decimal r s p -> ()
$crnf :: forall r (s :: Nat) p. NFData p => Decimal r s p -> ()
NFData, a -> Decimal r s b -> Decimal r s a
(a -> b) -> Decimal r s a -> Decimal r s b
(forall a b. (a -> b) -> Decimal r s a -> Decimal r s b)
-> (forall a b. a -> Decimal r s b -> Decimal r s a)
-> Functor (Decimal r s)
forall a b. a -> Decimal r s b -> Decimal r s a
forall a b. (a -> b) -> Decimal r s a -> Decimal r s b
forall r (s :: Nat) a b. a -> Decimal r s b -> Decimal r s a
forall r (s :: Nat) a b. (a -> b) -> Decimal r s a -> Decimal r s b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Decimal r s b -> Decimal r s a
$c<$ :: forall r (s :: Nat) a b. a -> Decimal r s b -> Decimal r s a
fmap :: (a -> b) -> Decimal r s a -> Decimal r s b
$cfmap :: forall r (s :: Nat) a b. (a -> b) -> Decimal r s a -> Decimal r s b
Functor, (forall x. Decimal r s p -> Rep (Decimal r s p) x)
-> (forall x. Rep (Decimal r s p) x -> Decimal r s p)
-> Generic (Decimal r s p)
forall x. Rep (Decimal r s p) x -> Decimal r s p
forall x. Decimal r s p -> Rep (Decimal r s p) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall r (s :: Nat) p x. Rep (Decimal r s p) x -> Decimal r s p
forall r (s :: Nat) p x. Decimal r s p -> Rep (Decimal r s p) x
$cto :: forall r (s :: Nat) p x. Rep (Decimal r s p) x -> Decimal r s p
$cfrom :: forall r (s :: Nat) p x. Decimal r s p -> Rep (Decimal r s p) x
Generic)

instance Applicative (Decimal r s) where
  pure :: a -> Decimal r s a
pure = a -> Decimal r s a
forall r (s :: Nat) a. a -> Decimal r s a
Decimal
  {-# INLINABLE pure #-}
  <*> :: Decimal r s (a -> b) -> Decimal r s a -> Decimal r s b
(<*>) (Decimal a -> b
f) (Decimal a
x) = b -> Decimal r s b
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (a -> b
f a
x)
  {-# INLINABLE (<*>) #-}


-- | A way to type restrict a polymorphic computation.
--
-- >>> import Numeric.Decimal
-- >>> arithRoundD @1 @RoundDown @2 @Word (123.05 + 1.1)
-- Arith 124.1
--
-- @since 0.2.0
arithRoundD ::
     forall s' r s p k. (Round r p, KnownNat k, s ~ (s' + k))
  => Arith (Decimal r s p)
  -> Arith (Decimal r s' p)
arithRoundD :: Arith (Decimal r s p) -> Arith (Decimal r s' p)
arithRoundD = (Decimal r s p -> Decimal r s' p)
-> Arith (Decimal r s p) -> Arith (Decimal r s' p)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Decimal r s p -> Decimal r s' p
forall r p (k :: Nat) (n :: Nat).
(Round r p, KnownNat k) =>
Decimal r (n + k) p -> Decimal r n p
roundDecimal

-- | A way to type restrict a polymorphic computation.
--
-- `arithD` provide an easy way to use @TypeApplications@ to supply a type of Decimal:
--
-- >>> import Numeric.Decimal
-- >>> :set -XDataKinds -XTypeApplications
-- >>> arithMD @RoundDown @3 @Word (1.1 + 123)
-- 124.100
-- >>> arithMD @RoundDown @3 @Word (1.1 - 123)
-- *** Exception: arithmetic underflow
--
-- @since 0.2.0
arithMD :: forall r s p m . MonadThrow m => Arith (Decimal r s p) -> m (Decimal r s p)
arithMD :: Arith (Decimal r s p) -> m (Decimal r s p)
arithMD = Arith (Decimal r s p) -> m (Decimal r s p)
forall (m :: * -> *) a. MonadThrow m => Arith a -> m a
arithM

-- | A way to type restrict a polymorphic computation.
--
-- `arithD` provide an easy way to use @TypeApplications@ to supply a type of Decimal:
--
-- >>> import Numeric.Decimal
-- >>> :set -XTypeApplications
-- >>> arithM $ arithD @RoundDown @3 @Word (1.1 + 123)
-- 124.100
-- >>> arithM $ arithD @RoundDown @3 @Word (1.1 - 123)
-- *** Exception: arithmetic underflow
--
-- @since 0.2.0
arithD :: forall r s p . Arith (Decimal r s p) -> Arith (Decimal r s p)
arithD :: Arith (Decimal r s p) -> Arith (Decimal r s p)
arithD = Arith (Decimal r s p) -> Arith (Decimal r s p)
forall a. a -> a
id

-- | A version of `arithD` that converts to `Maybe`
--
-- >>> import Numeric.Decimal
-- >>> :set -XTypeApplications
-- >>> arithMaybeD @RoundDown @3 @Word (1.1 + 123)
-- Just 124.100
-- >>> arithMaybeD @RoundDown @3 @Word (1.1 - 123)
-- Nothing
--
-- @since 0.2.0
arithMaybeD :: forall r s p . Arith (Decimal r s p) -> Maybe (Decimal r s p)
arithMaybeD :: Arith (Decimal r s p) -> Maybe (Decimal r s p)
arithMaybeD = Arith (Decimal r s p) -> Maybe (Decimal r s p)
forall (m :: * -> *) a. MonadThrow m => Arith a -> m a
arithM

-- | A version of `arithD` that converts to `Either`
--
-- @since 0.2.0
arithEitherD :: forall r s p . Arith (Decimal r s p) -> Either SomeException (Decimal r s p)
arithEitherD :: Arith (Decimal r s p) -> Either SomeException (Decimal r s p)
arithEitherD = Arith (Decimal r s p) -> Either SomeException (Decimal r s p)
forall (m :: * -> *) a. MonadThrow m => Arith a -> m a
arithM


-- | Rounding strategy to be used with decimal numbers.
--
-- @since 0.1.0
class Integral p => Round r p where

  -- | Reduce the scale of a number by @k@ decimal places using rounding strategy @r@
  --
  -- @since 0.1.0
  roundDecimal :: KnownNat k => Decimal r (n + k) p -> Decimal r n p

-- | Change the rounding strategy of a `Decimal`
--
-- >>> import Numeric.Decimal
-- >>> :set -XDataKinds -XTypeApplications
-- >>> d <- arithMD @RoundHalfUp @3 @Int 123.45
-- >>> roundDecimal d :: Decimal RoundHalfUp 1 Int
-- 123.5
-- >>> :t castRounding @RoundDown d
-- castRounding @RoundDown d :: Decimal RoundDown 3 Int
-- >>> roundDecimal (castRounding d) :: Decimal RoundDown 1 Int
-- 123.4
--
-- @since 0.2.0
castRounding :: forall r' r s p . Decimal r s p -> Decimal r' s p
castRounding :: Decimal r s p -> Decimal r' s p
castRounding = Decimal r s p -> Decimal r' s p
coerce

-- | Exception thrown whenever operation cannot be performed withou loosing information
--
-- @since 0.2.0
data PrecisionLoss = PrecisionLoss !Rational !Integer
  deriving PrecisionLoss -> PrecisionLoss -> Bool
(PrecisionLoss -> PrecisionLoss -> Bool)
-> (PrecisionLoss -> PrecisionLoss -> Bool) -> Eq PrecisionLoss
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PrecisionLoss -> PrecisionLoss -> Bool
$c/= :: PrecisionLoss -> PrecisionLoss -> Bool
== :: PrecisionLoss -> PrecisionLoss -> Bool
$c== :: PrecisionLoss -> PrecisionLoss -> Bool
Eq

instance Show PrecisionLoss where
  show :: PrecisionLoss -> String
show (PrecisionLoss Rational
r Integer
s) = String
"PrecisionLoss (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Rational -> String
forall a. Show a => a -> String
show Rational
r String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") to " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
s String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" decimal spaces"

instance Exception PrecisionLoss

-- | Get the scale of a `Decimal`. Argument is not evaluated.
--
-- >>> import Numeric.Decimal
-- >>> d <- arithM (36 :: Arith (Decimal RoundHalfUp 5 Int))
-- >>> d
-- 36.00000
-- >>> getScale d
-- 5
--
-- @since 0.1.0
getScale :: forall r s p . KnownNat s => Decimal r s p -> Integer
getScale :: Decimal r s p -> Integer
getScale Decimal r s p
_ = Proxy s -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy s
forall k (t :: k). Proxy t
Proxy :: Proxy s)


-- | Increase the precision of a `Decimal`, use `roundDecimal` if inverse is desired.
--
-- >>> import Numeric.Decimal
-- >>> d2 <- arithM (1.65 :: Arith (Decimal RoundHalfUp 2 Integer))
-- >>> d2
-- 1.65
-- >>> scaleUp d2 :: Decimal RoundHalfUp 50 Integer
-- 1.65000000000000000000000000000000000000000000000000
--
-- @since 0.2.0
scaleUp ::
     forall k r n. KnownNat k
  => Decimal r n Integer
  -> Decimal r (n + k) Integer
scaleUp :: Decimal r n Integer -> Decimal r (n + k) Integer
scaleUp (Decimal Integer
d) = Integer -> Decimal r (n + k) Integer
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (Integer
d Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* (Integer
10 Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Proxy k -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy k
forall k (t :: k). Proxy t
Proxy :: Proxy k)))

-- | Increase the precision of a `Decimal` backed by a bounded type, use `roundDecimal` if
-- inverse is desired.
--
-- >>> import Numeric.Decimal
-- >>> d2 <- arithM (1.65 :: Arith (Decimal RoundHalfUp 2 Int16))
-- >>> scaleUpBounded d2 :: IO (Decimal RoundHalfUp 3 Int16)
-- 1.650
-- >>> scaleUpBounded d2 :: IO (Decimal RoundHalfUp 4 Int16)
-- 1.6500
-- >>> scaleUpBounded d2 :: IO (Decimal RoundHalfUp 5 Int16)
-- *** Exception: arithmetic overflow
--
-- @since 0.1.1
scaleUpBounded ::
     forall k r n p m. (MonadThrow m, Integral p, Bounded p, KnownNat k)
  => Decimal r n p
  -> m (Decimal r (n + k) p)
scaleUpBounded :: Decimal r n p -> m (Decimal r (n + k) p)
scaleUpBounded (Decimal p
d) = do
  p
i <- Integer -> m p
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Bounded a) =>
Integer -> m a
fromIntegerBounded (Integer
10 Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Proxy k -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy k
forall k (t :: k). Proxy t
Proxy :: Proxy k))
  p -> Decimal r (n + k) p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (p -> Decimal r (n + k) p) -> m p -> m (Decimal r (n + k) p)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> p -> p -> m p
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Bounded a) =>
a -> a -> m a
timesBounded p
d p
i

-- | Split the number at the decimal point, i.e. whole number and the fraction
--
-- >>> import Numeric.Decimal
-- >>> splitDecimal <$> (12.34 :: Arith (Decimal RoundHalfUp 2 Int))
-- Arith (12,34)
--
-- @since 0.1.0
splitDecimal :: (Integral p, KnownNat s) => Decimal r s p -> (p, p)
splitDecimal :: Decimal r s p -> (p, p)
splitDecimal d :: Decimal r s p
d@(Decimal p
v) = p
v p -> p -> (p, p)
forall a. Integral a => a -> a -> (a, a)
`quotRem` (p
10 p -> Integer -> p
forall a b. (Num a, Integral b) => a -> b -> a
^ Decimal r s p -> Integer
forall r (s :: Nat) p. KnownNat s => Decimal r s p -> Integer
getScale Decimal r s p
d)

-- | Get the numerator. Same as @`toInteger` . `unwrapDecimal`@
--
-- >>> import Numeric.Decimal
-- >>> :set -XDataKinds -XTypeApplications
-- >>> decimalNumerator <$> arithD @RoundHalfEven @3 @Int 123.45
-- Arith 123450
--
-- @since 0.2.0
decimalNumerator :: Integral p => Decimal r s p -> Integer
decimalNumerator :: Decimal r s p -> Integer
decimalNumerator (Decimal p
i) = p -> Integer
forall a. Integral a => a -> Integer
toInteger p
i

-- | Get the decimal denominator. Always will be a multiple of @10@. Does not evaluate the
-- argument.
--
-- >>> import Numeric.Decimal
-- >>> :set -XDataKinds -XTypeApplications
-- >>> decimalDenominator <$> arithD @RoundHalfEven @3 @Int 123.45
-- Arith 1000
--
-- @since 0.2.0
decimalDenominator :: KnownNat s => Decimal r s p -> Integer
decimalDenominator :: Decimal r s p -> Integer
decimalDenominator Decimal r s p
d = Integer
10 Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Decimal r s p -> Integer
forall r (s :: Nat) p. KnownNat s => Decimal r s p -> Integer
getScale Decimal r s p
d


-- | Wrap an `Integral` as a `Decimal`. No scaling will be done.
--
-- >>> import Numeric.Decimal
-- >>> wrapDecimal 1234 :: Decimal RoundHalfUp 4 Int
-- 0.1234
-- >>> wrapDecimal 1234 :: Decimal RoundHalfUp 2 Int
-- 12.34
--
-- @since 0.1.0
wrapDecimal :: Integral p => p -> Decimal r s p
wrapDecimal :: p -> Decimal r s p
wrapDecimal = p -> Decimal r s p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal

-- | Get out the underlying representation for the decimal number. No scaling will be done.
--
-- >>> import Numeric.Decimal
-- >>> unwrapDecimal (wrapDecimal 1234 :: Decimal RoundHalfUp 4 Int)
-- 1234
--
-- @since 0.1.0
unwrapDecimal :: Decimal r s p -> p
unwrapDecimal :: Decimal r s p -> p
unwrapDecimal (Decimal p
p) = p
p

-- | Convert an `Integer` while performing the necessary scaling
--
-- >>> import Numeric.Decimal
-- >>> fromIntegerDecimal 1234 :: Decimal RoundHalfUp 4 Integer
-- 1234.0000
--
-- @since 0.2.0
fromIntegerDecimal :: forall r s . KnownNat s => Integer -> Decimal r s Integer
fromIntegerDecimal :: Integer -> Decimal r s Integer
fromIntegerDecimal Integer
x = Integer -> Decimal r s Integer
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* (Integer
10 Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
s))
  where
    s :: Integer
s = Proxy s -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy s
forall k (t :: k). Proxy t
Proxy :: Proxy s)
{-# INLINABLE fromIntegerDecimal #-}

-- | Convert a bounded integeral into a decimal, while performing the necessary scaling
--
-- >>> import Numeric.Decimal
-- >>> fromIntegralDecimalBounded 1234 :: IO (Decimal RoundHalfUp 4 Int)
-- 1234.0000
-- >>> fromIntegralDecimalBounded 1234 :: IO (Decimal RoundHalfUp 4 Int16)
-- *** Exception: arithmetic overflow
--
-- @since 0.2.0
fromIntegralDecimalBounded ::
     (Integral p, Bounded p, KnownNat s, MonadThrow m) => p -> m (Decimal r s p)
fromIntegralDecimalBounded :: p -> m (Decimal r s p)
fromIntegralDecimalBounded = Decimal r s Integer -> m (Decimal r s p)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p) =>
Decimal r s Integer -> m (Decimal r s p)
fromIntegerDecimalBounded (Decimal r s Integer -> m (Decimal r s p))
-> (p -> Decimal r s Integer) -> p -> m (Decimal r s p)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Decimal r s Integer
forall r (s :: Nat). KnownNat s => Integer -> Decimal r s Integer
fromIntegerDecimal (Integer -> Decimal r s Integer)
-> (p -> Integer) -> p -> Decimal r s Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. p -> Integer
forall a. Integral a => a -> Integer
toInteger
{-# INLINABLE fromIntegralDecimalBounded #-}

-- | Convert a decimal backed by an integral to another decimal backed by a bounded
-- integeral, while checking for `Overflow`/`Underflow`
--
-- >>> import Numeric.Decimal
-- >>> fromIntegralDecimalBounded 1234 :: IO (Decimal RoundHalfUp 4 Int)
-- 1234.0000
-- >>> fromIntegralDecimalBounded 1234 :: IO (Decimal RoundHalfUp 4 Int16)
-- *** Exception: arithmetic overflow
--
-- @since 0.2.0
integralDecimalToDecimalBounded ::
     (Integral p', Integral p, Bounded p, KnownNat s, MonadThrow m)
  => Decimal r s p'
  -> m (Decimal r s p)
integralDecimalToDecimalBounded :: Decimal r s p' -> m (Decimal r s p)
integralDecimalToDecimalBounded = Decimal r s Integer -> m (Decimal r s p)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p) =>
Decimal r s Integer -> m (Decimal r s p)
fromIntegerDecimalBounded (Decimal r s Integer -> m (Decimal r s p))
-> (Decimal r s p' -> Decimal r s Integer)
-> Decimal r s p'
-> m (Decimal r s p)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (p' -> Integer) -> Decimal r s p' -> Decimal r s Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap p' -> Integer
forall a. Integral a => a -> Integer
toInteger
{-# INLINABLE integralDecimalToDecimalBounded #-}


bindM2Decimal ::
     Monad m
  => (p1 -> p2 -> m p)
  -> m (Decimal r1 s1 p1)
  -> m (Decimal r2 s2 p2)
  -> m (Decimal r s p)
bindM2Decimal :: (p1 -> p2 -> m p)
-> m (Decimal r1 s1 p1)
-> m (Decimal r2 s2 p2)
-> m (Decimal r s p)
bindM2Decimal p1 -> p2 -> m p
f m (Decimal r1 s1 p1)
dx m (Decimal r2 s2 p2)
dy = do
  Decimal p1
x <- m (Decimal r1 s1 p1)
dx
  Decimal p2
y <- m (Decimal r2 s2 p2)
dy
  p -> Decimal r s p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (p -> Decimal r s p) -> m p -> m (Decimal r s p)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> p1 -> p2 -> m p
f p1
x p2
y
{-# INLINABLE bindM2Decimal #-}


bindM2 :: Monad m => (a -> b -> m c) -> m a -> m b -> m c
bindM2 :: (a -> b -> m c) -> m a -> m b -> m c
bindM2 a -> b -> m c
f m a
mx m b
my = do
  a
x <- m a
mx
  b
y <- m b
my
  a -> b -> m c
f a
x b
y
{-# INLINABLE bindM2 #-}


instance Bounded p => Bounded (Decimal r s p) where
  minBound :: Decimal r s p
minBound = p -> Decimal r s p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal p
forall a. Bounded a => a
minBound
  maxBound :: Decimal r s p
maxBound = p -> Decimal r s p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal p
forall a. Bounded a => a
maxBound

-----------------------------------
-- Integer instances --------------
-----------------------------------


instance (Round r Integer, KnownNat s) => Num (Decimal r s Integer) where
  + :: Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
(+) = Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
forall r (s :: Nat).
Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
plusDecimal
  {-# INLINABLE (+) #-}
  (-) = Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
forall r (s :: Nat).
Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
minusDecimal
  {-# INLINABLE (-) #-}
  * :: Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
(*) = Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
forall (s :: Nat) r.
(KnownNat s, Round r Integer) =>
Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
timesDecimalWithRounding
  {-# INLINABLE (*) #-}
  signum :: Decimal r s Integer -> Decimal r s Integer
signum = Decimal r s Integer -> Decimal r s Integer
forall (s :: Nat) r.
KnownNat s =>
Decimal r s Integer -> Decimal r s Integer
signumDecimal
  {-# INLINABLE signum #-}
  abs :: Decimal r s Integer -> Decimal r s Integer
abs = Decimal r s Integer -> Decimal r s Integer
forall (s :: Nat) r.
KnownNat s =>
Decimal r s Integer -> Decimal r s Integer
absDecimal
  {-# INLINABLE abs #-}
  fromInteger :: Integer -> Decimal r s Integer
fromInteger = Integer -> Decimal r s Integer
forall r (s :: Nat). KnownNat s => Integer -> Decimal r s Integer
fromIntegerDecimal
  {-# INLINABLE fromInteger #-}


instance (KnownNat s) => Num (Arith (Decimal r s Integer)) where
  + :: Arith (Decimal r s Integer)
-> Arith (Decimal r s Integer) -> Arith (Decimal r s Integer)
(+) = (Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer)
-> Arith (Decimal r s Integer)
-> Arith (Decimal r s Integer)
-> Arith (Decimal r s Integer)
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
forall r (s :: Nat).
Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
plusDecimal
  {-# INLINABLE (+) #-}
  (-) = (Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer)
-> Arith (Decimal r s Integer)
-> Arith (Decimal r s Integer)
-> Arith (Decimal r s Integer)
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
forall r (s :: Nat).
Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
minusDecimal
  {-# INLINABLE (-) #-}
  * :: Arith (Decimal r s Integer)
-> Arith (Decimal r s Integer) -> Arith (Decimal r s Integer)
(*) = (Decimal r s Integer
 -> Decimal r s Integer -> Arith (Decimal r s Integer))
-> Arith (Decimal r s Integer)
-> Arith (Decimal r s Integer)
-> Arith (Decimal r s Integer)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Integer
-> Decimal r s Integer -> Arith (Decimal r s Integer)
forall r (s :: Nat) (m :: * -> *).
(KnownNat s, MonadThrow m) =>
Decimal r s Integer
-> Decimal r s Integer -> m (Decimal r s Integer)
timesDecimalWithoutLoss
  {-# INLINABLE (*) #-}
  signum :: Arith (Decimal r s Integer) -> Arith (Decimal r s Integer)
signum = (Decimal r s Integer -> Decimal r s Integer)
-> Arith (Decimal r s Integer) -> Arith (Decimal r s Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Decimal r s Integer -> Decimal r s Integer
forall (s :: Nat) r.
KnownNat s =>
Decimal r s Integer -> Decimal r s Integer
signumDecimal
  {-# INLINABLE signum #-}
  abs :: Arith (Decimal r s Integer) -> Arith (Decimal r s Integer)
abs = (Decimal r s Integer -> Decimal r s Integer)
-> Arith (Decimal r s Integer) -> Arith (Decimal r s Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Decimal r s Integer -> Decimal r s Integer
forall (s :: Nat) r.
KnownNat s =>
Decimal r s Integer -> Decimal r s Integer
absDecimal
  {-# INLINABLE abs #-}
  fromInteger :: Integer -> Arith (Decimal r s Integer)
fromInteger = Decimal r s Integer -> Arith (Decimal r s Integer)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Decimal r s Integer -> Arith (Decimal r s Integer))
-> (Integer -> Decimal r s Integer)
-> Integer
-> Arith (Decimal r s Integer)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Decimal r s Integer
forall r (s :: Nat). KnownNat s => Integer -> Decimal r s Integer
fromIntegerDecimal
  {-# INLINABLE fromInteger #-}

instance (KnownNat s) => Fractional (Arith (Decimal r s Integer)) where
  / :: Arith (Decimal r s Integer)
-> Arith (Decimal r s Integer) -> Arith (Decimal r s Integer)
(/) = (Decimal r s Integer
 -> Decimal r s Integer -> Arith (Decimal r s Integer))
-> Arith (Decimal r s Integer)
-> Arith (Decimal r s Integer)
-> Arith (Decimal r s Integer)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Integer
-> Decimal r s Integer -> Arith (Decimal r s Integer)
forall r (s :: Nat) (m :: * -> *).
(KnownNat s, MonadThrow m) =>
Decimal r s Integer
-> Decimal r s Integer -> m (Decimal r s Integer)
divideDecimalWithoutLoss
  {-# INLINABLE (/) #-}
  fromRational :: Rational -> Arith (Decimal r s Integer)
fromRational = Rational -> Arith (Decimal r s Integer)
forall (m :: * -> *) r (s :: Nat).
(MonadThrow m, KnownNat s) =>
Rational -> m (Decimal r s Integer)
fromRationalDecimalWithoutLoss
  {-# INLINABLE fromRational #-}



-----------------------------------
-- Bounded Integral instances -----
-----------------------------------


instance (KnownNat s) => Num (Arith (Decimal r s Int)) where
  + :: Arith (Decimal r s Int)
-> Arith (Decimal r s Int) -> Arith (Decimal r s Int)
(+) = (Decimal r s Int -> Decimal r s Int -> Arith (Decimal r s Int))
-> Arith (Decimal r s Int)
-> Arith (Decimal r s Int)
-> Arith (Decimal r s Int)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int -> Decimal r s Int -> Arith (Decimal r s Int)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
plusDecimalBounded
  {-# INLINABLE (+) #-}
  (-) = (Decimal r s Int -> Decimal r s Int -> Arith (Decimal r s Int))
-> Arith (Decimal r s Int)
-> Arith (Decimal r s Int)
-> Arith (Decimal r s Int)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int -> Decimal r s Int -> Arith (Decimal r s Int)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
minusDecimalBounded
  {-# INLINABLE (-) #-}
  * :: Arith (Decimal r s Int)
-> Arith (Decimal r s Int) -> Arith (Decimal r s Int)
(*) = (Decimal r s Int -> Decimal r s Int -> Arith (Decimal r s Int))
-> Arith (Decimal r s Int)
-> Arith (Decimal r s Int)
-> Arith (Decimal r s Int)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int -> Decimal r s Int -> Arith (Decimal r s Int)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
timesDecimalBoundedWithoutLoss
  {-# INLINABLE (*) #-}
  signum :: Arith (Decimal r s Int) -> Arith (Decimal r s Int)
signum = (Arith (Decimal r s Int)
-> (Decimal r s Int -> Arith (Decimal r s Int))
-> Arith (Decimal r s Int)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Int -> Arith (Decimal r s Int)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
signumDecimalBounded)
  {-# INLINABLE signum #-}
  abs :: Arith (Decimal r s Int) -> Arith (Decimal r s Int)
abs = (Arith (Decimal r s Int)
-> (Decimal r s Int -> Arith (Decimal r s Int))
-> Arith (Decimal r s Int)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Int -> Arith (Decimal r s Int)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
absDecimalBounded)
  {-# INLINABLE abs #-}
  fromInteger :: Integer -> Arith (Decimal r s Int)
fromInteger = Integer -> Arith (Decimal r s Int)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p, KnownNat s) =>
Integer -> m (Decimal r s p)
fromIntegerDecimalBoundedIntegral
  {-# INLINABLE fromInteger #-}

instance (KnownNat s) => Num (Arith (Decimal r s Int8)) where
  + :: Arith (Decimal r s Int8)
-> Arith (Decimal r s Int8) -> Arith (Decimal r s Int8)
(+) = (Decimal r s Int8 -> Decimal r s Int8 -> Arith (Decimal r s Int8))
-> Arith (Decimal r s Int8)
-> Arith (Decimal r s Int8)
-> Arith (Decimal r s Int8)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int8 -> Decimal r s Int8 -> Arith (Decimal r s Int8)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
plusDecimalBounded
  {-# INLINABLE (+) #-}
  (-) = (Decimal r s Int8 -> Decimal r s Int8 -> Arith (Decimal r s Int8))
-> Arith (Decimal r s Int8)
-> Arith (Decimal r s Int8)
-> Arith (Decimal r s Int8)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int8 -> Decimal r s Int8 -> Arith (Decimal r s Int8)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
minusDecimalBounded
  {-# INLINABLE (-) #-}
  * :: Arith (Decimal r s Int8)
-> Arith (Decimal r s Int8) -> Arith (Decimal r s Int8)
(*) = (Decimal r s Int8 -> Decimal r s Int8 -> Arith (Decimal r s Int8))
-> Arith (Decimal r s Int8)
-> Arith (Decimal r s Int8)
-> Arith (Decimal r s Int8)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int8 -> Decimal r s Int8 -> Arith (Decimal r s Int8)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
timesDecimalBoundedWithoutLoss
  {-# INLINABLE (*) #-}
  signum :: Arith (Decimal r s Int8) -> Arith (Decimal r s Int8)
signum = (Arith (Decimal r s Int8)
-> (Decimal r s Int8 -> Arith (Decimal r s Int8))
-> Arith (Decimal r s Int8)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Int8 -> Arith (Decimal r s Int8)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
signumDecimalBounded)
  {-# INLINABLE signum #-}
  abs :: Arith (Decimal r s Int8) -> Arith (Decimal r s Int8)
abs = (Arith (Decimal r s Int8)
-> (Decimal r s Int8 -> Arith (Decimal r s Int8))
-> Arith (Decimal r s Int8)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Int8 -> Arith (Decimal r s Int8)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
absDecimalBounded)
  {-# INLINABLE abs #-}
  fromInteger :: Integer -> Arith (Decimal r s Int8)
fromInteger = Integer -> Arith (Decimal r s Int8)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p, KnownNat s) =>
Integer -> m (Decimal r s p)
fromIntegerDecimalBoundedIntegral
  {-# INLINABLE fromInteger #-}

instance (KnownNat s) => Num (Arith (Decimal r s Int16)) where
  + :: Arith (Decimal r s Int16)
-> Arith (Decimal r s Int16) -> Arith (Decimal r s Int16)
(+) = (Decimal r s Int16
 -> Decimal r s Int16 -> Arith (Decimal r s Int16))
-> Arith (Decimal r s Int16)
-> Arith (Decimal r s Int16)
-> Arith (Decimal r s Int16)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int16 -> Decimal r s Int16 -> Arith (Decimal r s Int16)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
plusDecimalBounded
  {-# INLINABLE (+) #-}
  (-) = (Decimal r s Int16
 -> Decimal r s Int16 -> Arith (Decimal r s Int16))
-> Arith (Decimal r s Int16)
-> Arith (Decimal r s Int16)
-> Arith (Decimal r s Int16)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int16 -> Decimal r s Int16 -> Arith (Decimal r s Int16)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
minusDecimalBounded
  {-# INLINABLE (-) #-}
  * :: Arith (Decimal r s Int16)
-> Arith (Decimal r s Int16) -> Arith (Decimal r s Int16)
(*) = (Decimal r s Int16
 -> Decimal r s Int16 -> Arith (Decimal r s Int16))
-> Arith (Decimal r s Int16)
-> Arith (Decimal r s Int16)
-> Arith (Decimal r s Int16)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int16 -> Decimal r s Int16 -> Arith (Decimal r s Int16)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
timesDecimalBoundedWithoutLoss
  {-# INLINABLE (*) #-}
  signum :: Arith (Decimal r s Int16) -> Arith (Decimal r s Int16)
signum = (Arith (Decimal r s Int16)
-> (Decimal r s Int16 -> Arith (Decimal r s Int16))
-> Arith (Decimal r s Int16)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Int16 -> Arith (Decimal r s Int16)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
signumDecimalBounded)
  {-# INLINABLE signum #-}
  abs :: Arith (Decimal r s Int16) -> Arith (Decimal r s Int16)
abs = (Arith (Decimal r s Int16)
-> (Decimal r s Int16 -> Arith (Decimal r s Int16))
-> Arith (Decimal r s Int16)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Int16 -> Arith (Decimal r s Int16)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
absDecimalBounded)
  {-# INLINABLE abs #-}
  fromInteger :: Integer -> Arith (Decimal r s Int16)
fromInteger = Integer -> Arith (Decimal r s Int16)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p, KnownNat s) =>
Integer -> m (Decimal r s p)
fromIntegerDecimalBoundedIntegral
  {-# INLINABLE fromInteger #-}

instance (KnownNat s) => Num (Arith (Decimal r s Int32)) where
  + :: Arith (Decimal r s Int32)
-> Arith (Decimal r s Int32) -> Arith (Decimal r s Int32)
(+) = (Decimal r s Int32
 -> Decimal r s Int32 -> Arith (Decimal r s Int32))
-> Arith (Decimal r s Int32)
-> Arith (Decimal r s Int32)
-> Arith (Decimal r s Int32)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int32 -> Decimal r s Int32 -> Arith (Decimal r s Int32)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
plusDecimalBounded
  {-# INLINABLE (+) #-}
  (-) = (Decimal r s Int32
 -> Decimal r s Int32 -> Arith (Decimal r s Int32))
-> Arith (Decimal r s Int32)
-> Arith (Decimal r s Int32)
-> Arith (Decimal r s Int32)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int32 -> Decimal r s Int32 -> Arith (Decimal r s Int32)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
minusDecimalBounded
  {-# INLINABLE (-) #-}
  * :: Arith (Decimal r s Int32)
-> Arith (Decimal r s Int32) -> Arith (Decimal r s Int32)
(*) = (Decimal r s Int32
 -> Decimal r s Int32 -> Arith (Decimal r s Int32))
-> Arith (Decimal r s Int32)
-> Arith (Decimal r s Int32)
-> Arith (Decimal r s Int32)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int32 -> Decimal r s Int32 -> Arith (Decimal r s Int32)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
timesDecimalBoundedWithoutLoss
  {-# INLINABLE (*) #-}
  signum :: Arith (Decimal r s Int32) -> Arith (Decimal r s Int32)
signum = (Arith (Decimal r s Int32)
-> (Decimal r s Int32 -> Arith (Decimal r s Int32))
-> Arith (Decimal r s Int32)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Int32 -> Arith (Decimal r s Int32)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
signumDecimalBounded)
  {-# INLINABLE signum #-}
  abs :: Arith (Decimal r s Int32) -> Arith (Decimal r s Int32)
abs = (Arith (Decimal r s Int32)
-> (Decimal r s Int32 -> Arith (Decimal r s Int32))
-> Arith (Decimal r s Int32)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Int32 -> Arith (Decimal r s Int32)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
absDecimalBounded)
  {-# INLINABLE abs #-}
  fromInteger :: Integer -> Arith (Decimal r s Int32)
fromInteger = Integer -> Arith (Decimal r s Int32)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p, KnownNat s) =>
Integer -> m (Decimal r s p)
fromIntegerDecimalBoundedIntegral
  {-# INLINABLE fromInteger #-}

instance (KnownNat s) => Num (Arith (Decimal r s Int64)) where
  + :: Arith (Decimal r s Int64)
-> Arith (Decimal r s Int64) -> Arith (Decimal r s Int64)
(+) = (Decimal r s Int64
 -> Decimal r s Int64 -> Arith (Decimal r s Int64))
-> Arith (Decimal r s Int64)
-> Arith (Decimal r s Int64)
-> Arith (Decimal r s Int64)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int64 -> Decimal r s Int64 -> Arith (Decimal r s Int64)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
plusDecimalBounded
  {-# INLINABLE (+) #-}
  (-) = (Decimal r s Int64
 -> Decimal r s Int64 -> Arith (Decimal r s Int64))
-> Arith (Decimal r s Int64)
-> Arith (Decimal r s Int64)
-> Arith (Decimal r s Int64)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int64 -> Decimal r s Int64 -> Arith (Decimal r s Int64)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
minusDecimalBounded
  {-# INLINABLE (-) #-}
  * :: Arith (Decimal r s Int64)
-> Arith (Decimal r s Int64) -> Arith (Decimal r s Int64)
(*) = (Decimal r s Int64
 -> Decimal r s Int64 -> Arith (Decimal r s Int64))
-> Arith (Decimal r s Int64)
-> Arith (Decimal r s Int64)
-> Arith (Decimal r s Int64)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int64 -> Decimal r s Int64 -> Arith (Decimal r s Int64)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
timesDecimalBoundedWithoutLoss
  {-# INLINABLE (*) #-}
  signum :: Arith (Decimal r s Int64) -> Arith (Decimal r s Int64)
signum = (Arith (Decimal r s Int64)
-> (Decimal r s Int64 -> Arith (Decimal r s Int64))
-> Arith (Decimal r s Int64)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Int64 -> Arith (Decimal r s Int64)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
signumDecimalBounded)
  {-# INLINABLE signum #-}
  abs :: Arith (Decimal r s Int64) -> Arith (Decimal r s Int64)
abs = (Arith (Decimal r s Int64)
-> (Decimal r s Int64 -> Arith (Decimal r s Int64))
-> Arith (Decimal r s Int64)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Int64 -> Arith (Decimal r s Int64)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
absDecimalBounded)
  {-# INLINABLE abs #-}
  fromInteger :: Integer -> Arith (Decimal r s Int64)
fromInteger = Integer -> Arith (Decimal r s Int64)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p, KnownNat s) =>
Integer -> m (Decimal r s p)
fromIntegerDecimalBoundedIntegral
  {-# INLINABLE fromInteger #-}

instance (KnownNat s) => Num (Arith (Decimal r s Word)) where
  + :: Arith (Decimal r s Word)
-> Arith (Decimal r s Word) -> Arith (Decimal r s Word)
(+) = (Decimal r s Word -> Decimal r s Word -> Arith (Decimal r s Word))
-> Arith (Decimal r s Word)
-> Arith (Decimal r s Word)
-> Arith (Decimal r s Word)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word -> Decimal r s Word -> Arith (Decimal r s Word)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
plusDecimalBounded
  {-# INLINABLE (+) #-}
  (-) = (Decimal r s Word -> Decimal r s Word -> Arith (Decimal r s Word))
-> Arith (Decimal r s Word)
-> Arith (Decimal r s Word)
-> Arith (Decimal r s Word)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word -> Decimal r s Word -> Arith (Decimal r s Word)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
minusDecimalBounded
  {-# INLINABLE (-) #-}
  * :: Arith (Decimal r s Word)
-> Arith (Decimal r s Word) -> Arith (Decimal r s Word)
(*) = (Decimal r s Word -> Decimal r s Word -> Arith (Decimal r s Word))
-> Arith (Decimal r s Word)
-> Arith (Decimal r s Word)
-> Arith (Decimal r s Word)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word -> Decimal r s Word -> Arith (Decimal r s Word)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
timesDecimalBoundedWithoutLoss
  {-# INLINABLE (*) #-}
  signum :: Arith (Decimal r s Word) -> Arith (Decimal r s Word)
signum = (Arith (Decimal r s Word)
-> (Decimal r s Word -> Arith (Decimal r s Word))
-> Arith (Decimal r s Word)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Word -> Arith (Decimal r s Word)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
signumDecimalBounded)
  {-# INLINABLE signum #-}
  abs :: Arith (Decimal r s Word) -> Arith (Decimal r s Word)
abs = Arith (Decimal r s Word) -> Arith (Decimal r s Word)
forall a. a -> a
id
  {-# INLINABLE abs #-}
  fromInteger :: Integer -> Arith (Decimal r s Word)
fromInteger = Integer -> Arith (Decimal r s Word)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p, KnownNat s) =>
Integer -> m (Decimal r s p)
fromIntegerDecimalBoundedIntegral
  {-# INLINABLE fromInteger #-}

instance (KnownNat s) => Num (Arith (Decimal r s Word8)) where
  + :: Arith (Decimal r s Word8)
-> Arith (Decimal r s Word8) -> Arith (Decimal r s Word8)
(+) = (Decimal r s Word8
 -> Decimal r s Word8 -> Arith (Decimal r s Word8))
-> Arith (Decimal r s Word8)
-> Arith (Decimal r s Word8)
-> Arith (Decimal r s Word8)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word8 -> Decimal r s Word8 -> Arith (Decimal r s Word8)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
plusDecimalBounded
  {-# INLINABLE (+) #-}
  (-) = (Decimal r s Word8
 -> Decimal r s Word8 -> Arith (Decimal r s Word8))
-> Arith (Decimal r s Word8)
-> Arith (Decimal r s Word8)
-> Arith (Decimal r s Word8)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word8 -> Decimal r s Word8 -> Arith (Decimal r s Word8)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
minusDecimalBounded
  {-# INLINABLE (-) #-}
  * :: Arith (Decimal r s Word8)
-> Arith (Decimal r s Word8) -> Arith (Decimal r s Word8)
(*) = (Decimal r s Word8
 -> Decimal r s Word8 -> Arith (Decimal r s Word8))
-> Arith (Decimal r s Word8)
-> Arith (Decimal r s Word8)
-> Arith (Decimal r s Word8)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word8 -> Decimal r s Word8 -> Arith (Decimal r s Word8)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
timesDecimalBoundedWithoutLoss
  {-# INLINABLE (*) #-}
  signum :: Arith (Decimal r s Word8) -> Arith (Decimal r s Word8)
signum = (Arith (Decimal r s Word8)
-> (Decimal r s Word8 -> Arith (Decimal r s Word8))
-> Arith (Decimal r s Word8)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Word8 -> Arith (Decimal r s Word8)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
signumDecimalBounded)
  {-# INLINABLE signum #-}
  abs :: Arith (Decimal r s Word8) -> Arith (Decimal r s Word8)
abs = Arith (Decimal r s Word8) -> Arith (Decimal r s Word8)
forall a. a -> a
id
  {-# INLINABLE abs #-}
  fromInteger :: Integer -> Arith (Decimal r s Word8)
fromInteger = Integer -> Arith (Decimal r s Word8)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p, KnownNat s) =>
Integer -> m (Decimal r s p)
fromIntegerDecimalBoundedIntegral
  {-# INLINABLE fromInteger #-}

instance (KnownNat s) => Num (Arith (Decimal r s Word16)) where
  + :: Arith (Decimal r s Word16)
-> Arith (Decimal r s Word16) -> Arith (Decimal r s Word16)
(+) = (Decimal r s Word16
 -> Decimal r s Word16 -> Arith (Decimal r s Word16))
-> Arith (Decimal r s Word16)
-> Arith (Decimal r s Word16)
-> Arith (Decimal r s Word16)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word16
-> Decimal r s Word16 -> Arith (Decimal r s Word16)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
plusDecimalBounded
  {-# INLINABLE (+) #-}
  (-) = (Decimal r s Word16
 -> Decimal r s Word16 -> Arith (Decimal r s Word16))
-> Arith (Decimal r s Word16)
-> Arith (Decimal r s Word16)
-> Arith (Decimal r s Word16)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word16
-> Decimal r s Word16 -> Arith (Decimal r s Word16)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
minusDecimalBounded
  {-# INLINABLE (-) #-}
  * :: Arith (Decimal r s Word16)
-> Arith (Decimal r s Word16) -> Arith (Decimal r s Word16)
(*) = (Decimal r s Word16
 -> Decimal r s Word16 -> Arith (Decimal r s Word16))
-> Arith (Decimal r s Word16)
-> Arith (Decimal r s Word16)
-> Arith (Decimal r s Word16)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word16
-> Decimal r s Word16 -> Arith (Decimal r s Word16)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
timesDecimalBoundedWithoutLoss
  {-# INLINABLE (*) #-}
  signum :: Arith (Decimal r s Word16) -> Arith (Decimal r s Word16)
signum = (Arith (Decimal r s Word16)
-> (Decimal r s Word16 -> Arith (Decimal r s Word16))
-> Arith (Decimal r s Word16)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Word16 -> Arith (Decimal r s Word16)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
signumDecimalBounded)
  {-# INLINABLE signum #-}
  abs :: Arith (Decimal r s Word16) -> Arith (Decimal r s Word16)
abs = Arith (Decimal r s Word16) -> Arith (Decimal r s Word16)
forall a. a -> a
id
  {-# INLINABLE abs #-}
  fromInteger :: Integer -> Arith (Decimal r s Word16)
fromInteger = Integer -> Arith (Decimal r s Word16)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p, KnownNat s) =>
Integer -> m (Decimal r s p)
fromIntegerDecimalBoundedIntegral
  {-# INLINABLE fromInteger #-}

instance (KnownNat s) => Num (Arith (Decimal r s Word32)) where
  + :: Arith (Decimal r s Word32)
-> Arith (Decimal r s Word32) -> Arith (Decimal r s Word32)
(+) = (Decimal r s Word32
 -> Decimal r s Word32 -> Arith (Decimal r s Word32))
-> Arith (Decimal r s Word32)
-> Arith (Decimal r s Word32)
-> Arith (Decimal r s Word32)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word32
-> Decimal r s Word32 -> Arith (Decimal r s Word32)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
plusDecimalBounded
  {-# INLINABLE (+) #-}
  (-) = (Decimal r s Word32
 -> Decimal r s Word32 -> Arith (Decimal r s Word32))
-> Arith (Decimal r s Word32)
-> Arith (Decimal r s Word32)
-> Arith (Decimal r s Word32)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word32
-> Decimal r s Word32 -> Arith (Decimal r s Word32)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
minusDecimalBounded
  {-# INLINABLE (-) #-}
  * :: Arith (Decimal r s Word32)
-> Arith (Decimal r s Word32) -> Arith (Decimal r s Word32)
(*) = (Decimal r s Word32
 -> Decimal r s Word32 -> Arith (Decimal r s Word32))
-> Arith (Decimal r s Word32)
-> Arith (Decimal r s Word32)
-> Arith (Decimal r s Word32)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word32
-> Decimal r s Word32 -> Arith (Decimal r s Word32)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
timesDecimalBoundedWithoutLoss
  {-# INLINABLE (*) #-}
  signum :: Arith (Decimal r s Word32) -> Arith (Decimal r s Word32)
signum = (Arith (Decimal r s Word32)
-> (Decimal r s Word32 -> Arith (Decimal r s Word32))
-> Arith (Decimal r s Word32)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Word32 -> Arith (Decimal r s Word32)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
signumDecimalBounded)
  {-# INLINABLE signum #-}
  abs :: Arith (Decimal r s Word32) -> Arith (Decimal r s Word32)
abs = Arith (Decimal r s Word32) -> Arith (Decimal r s Word32)
forall a. a -> a
id
  {-# INLINABLE abs #-}
  fromInteger :: Integer -> Arith (Decimal r s Word32)
fromInteger = Integer -> Arith (Decimal r s Word32)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p, KnownNat s) =>
Integer -> m (Decimal r s p)
fromIntegerDecimalBoundedIntegral
  {-# INLINABLE fromInteger #-}

instance (KnownNat s) => Num (Arith (Decimal r s Word64)) where
  + :: Arith (Decimal r s Word64)
-> Arith (Decimal r s Word64) -> Arith (Decimal r s Word64)
(+) = (Decimal r s Word64
 -> Decimal r s Word64 -> Arith (Decimal r s Word64))
-> Arith (Decimal r s Word64)
-> Arith (Decimal r s Word64)
-> Arith (Decimal r s Word64)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word64
-> Decimal r s Word64 -> Arith (Decimal r s Word64)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
plusDecimalBounded
  {-# INLINABLE (+) #-}
  (-) = (Decimal r s Word64
 -> Decimal r s Word64 -> Arith (Decimal r s Word64))
-> Arith (Decimal r s Word64)
-> Arith (Decimal r s Word64)
-> Arith (Decimal r s Word64)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word64
-> Decimal r s Word64 -> Arith (Decimal r s Word64)
forall (m :: * -> *) p r (s :: Nat).
(MonadThrow m, Eq p, Ord p, Num p, Bounded p) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
minusDecimalBounded
  {-# INLINABLE (-) #-}
  * :: Arith (Decimal r s Word64)
-> Arith (Decimal r s Word64) -> Arith (Decimal r s Word64)
(*) = (Decimal r s Word64
 -> Decimal r s Word64 -> Arith (Decimal r s Word64))
-> Arith (Decimal r s Word64)
-> Arith (Decimal r s Word64)
-> Arith (Decimal r s Word64)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word64
-> Decimal r s Word64 -> Arith (Decimal r s Word64)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
timesDecimalBoundedWithoutLoss
  {-# INLINABLE (*) #-}
  signum :: Arith (Decimal r s Word64) -> Arith (Decimal r s Word64)
signum = (Arith (Decimal r s Word64)
-> (Decimal r s Word64 -> Arith (Decimal r s Word64))
-> Arith (Decimal r s Word64)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Word64 -> Arith (Decimal r s Word64)
forall (s :: Nat) (m :: * -> *) p r.
(KnownNat s, MonadThrow m, Integral p, Bounded p) =>
Decimal r s p -> m (Decimal r s p)
signumDecimalBounded)
  {-# INLINABLE signum #-}
  abs :: Arith (Decimal r s Word64) -> Arith (Decimal r s Word64)
abs = Arith (Decimal r s Word64) -> Arith (Decimal r s Word64)
forall a. a -> a
id
  {-# INLINABLE abs #-}
  fromInteger :: Integer -> Arith (Decimal r s Word64)
fromInteger = Integer -> Arith (Decimal r s Word64)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p, KnownNat s) =>
Integer -> m (Decimal r s p)
fromIntegerDecimalBoundedIntegral
  {-# INLINABLE fromInteger #-}

instance (KnownNat s) => Fractional (Arith (Decimal r s Int)) where
  / :: Arith (Decimal r s Int)
-> Arith (Decimal r s Int) -> Arith (Decimal r s Int)
(/) = (Decimal r s Int -> Decimal r s Int -> Arith (Decimal r s Int))
-> Arith (Decimal r s Int)
-> Arith (Decimal r s Int)
-> Arith (Decimal r s Int)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int -> Decimal r s Int -> Arith (Decimal r s Int)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
divideDecimalBoundedWithoutLoss
  {-# INLINABLE (/) #-}
  fromRational :: Rational -> Arith (Decimal r s Int)
fromRational = Rational -> Arith (Decimal r s Int)
forall (m :: * -> *) (s :: Nat) p r.
(MonadThrow m, KnownNat s, Integral p, Bounded p) =>
Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithoutLoss
  {-# INLINABLE fromRational #-}

instance (KnownNat s) => Fractional (Arith (Decimal r s Int8)) where
  / :: Arith (Decimal r s Int8)
-> Arith (Decimal r s Int8) -> Arith (Decimal r s Int8)
(/) = (Decimal r s Int8 -> Decimal r s Int8 -> Arith (Decimal r s Int8))
-> Arith (Decimal r s Int8)
-> Arith (Decimal r s Int8)
-> Arith (Decimal r s Int8)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int8 -> Decimal r s Int8 -> Arith (Decimal r s Int8)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
divideDecimalBoundedWithoutLoss
  {-# INLINABLE (/) #-}
  fromRational :: Rational -> Arith (Decimal r s Int8)
fromRational = Rational -> Arith (Decimal r s Int8)
forall (m :: * -> *) (s :: Nat) p r.
(MonadThrow m, KnownNat s, Integral p, Bounded p) =>
Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithoutLoss
  {-# INLINABLE fromRational #-}

instance (KnownNat s) => Fractional (Arith (Decimal r s Int16)) where
  / :: Arith (Decimal r s Int16)
-> Arith (Decimal r s Int16) -> Arith (Decimal r s Int16)
(/) = (Decimal r s Int16
 -> Decimal r s Int16 -> Arith (Decimal r s Int16))
-> Arith (Decimal r s Int16)
-> Arith (Decimal r s Int16)
-> Arith (Decimal r s Int16)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int16 -> Decimal r s Int16 -> Arith (Decimal r s Int16)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
divideDecimalBoundedWithoutLoss
  {-# INLINABLE (/) #-}
  fromRational :: Rational -> Arith (Decimal r s Int16)
fromRational = Rational -> Arith (Decimal r s Int16)
forall (m :: * -> *) (s :: Nat) p r.
(MonadThrow m, KnownNat s, Integral p, Bounded p) =>
Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithoutLoss
  {-# INLINABLE fromRational #-}

instance (KnownNat s) => Fractional (Arith (Decimal r s Int32)) where
  / :: Arith (Decimal r s Int32)
-> Arith (Decimal r s Int32) -> Arith (Decimal r s Int32)
(/) = (Decimal r s Int32
 -> Decimal r s Int32 -> Arith (Decimal r s Int32))
-> Arith (Decimal r s Int32)
-> Arith (Decimal r s Int32)
-> Arith (Decimal r s Int32)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int32 -> Decimal r s Int32 -> Arith (Decimal r s Int32)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
divideDecimalBoundedWithoutLoss
  {-# INLINABLE (/) #-}
  fromRational :: Rational -> Arith (Decimal r s Int32)
fromRational = Rational -> Arith (Decimal r s Int32)
forall (m :: * -> *) (s :: Nat) p r.
(MonadThrow m, KnownNat s, Integral p, Bounded p) =>
Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithoutLoss
  {-# INLINABLE fromRational #-}


instance (KnownNat s) => Fractional (Arith (Decimal r s Int64)) where
  / :: Arith (Decimal r s Int64)
-> Arith (Decimal r s Int64) -> Arith (Decimal r s Int64)
(/) = (Decimal r s Int64
 -> Decimal r s Int64 -> Arith (Decimal r s Int64))
-> Arith (Decimal r s Int64)
-> Arith (Decimal r s Int64)
-> Arith (Decimal r s Int64)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Int64 -> Decimal r s Int64 -> Arith (Decimal r s Int64)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
divideDecimalBoundedWithoutLoss
  {-# INLINABLE (/) #-}
  fromRational :: Rational -> Arith (Decimal r s Int64)
fromRational = Rational -> Arith (Decimal r s Int64)
forall (m :: * -> *) (s :: Nat) p r.
(MonadThrow m, KnownNat s, Integral p, Bounded p) =>
Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithoutLoss
  {-# INLINABLE fromRational #-}

instance (KnownNat s) => Fractional (Arith (Decimal r s Word)) where
  / :: Arith (Decimal r s Word)
-> Arith (Decimal r s Word) -> Arith (Decimal r s Word)
(/) = (Decimal r s Word -> Decimal r s Word -> Arith (Decimal r s Word))
-> Arith (Decimal r s Word)
-> Arith (Decimal r s Word)
-> Arith (Decimal r s Word)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word -> Decimal r s Word -> Arith (Decimal r s Word)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
divideDecimalBoundedWithoutLoss
  {-# INLINABLE (/) #-}
  fromRational :: Rational -> Arith (Decimal r s Word)
fromRational = Rational -> Arith (Decimal r s Word)
forall (m :: * -> *) (s :: Nat) p r.
(MonadThrow m, KnownNat s, Integral p, Bounded p) =>
Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithoutLoss
  {-# INLINABLE fromRational #-}

instance (KnownNat s) => Fractional (Arith (Decimal r s Word8)) where
  / :: Arith (Decimal r s Word8)
-> Arith (Decimal r s Word8) -> Arith (Decimal r s Word8)
(/) = (Decimal r s Word8
 -> Decimal r s Word8 -> Arith (Decimal r s Word8))
-> Arith (Decimal r s Word8)
-> Arith (Decimal r s Word8)
-> Arith (Decimal r s Word8)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word8 -> Decimal r s Word8 -> Arith (Decimal r s Word8)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
divideDecimalBoundedWithoutLoss
  {-# INLINABLE (/) #-}
  fromRational :: Rational -> Arith (Decimal r s Word8)
fromRational = Rational -> Arith (Decimal r s Word8)
forall (m :: * -> *) (s :: Nat) p r.
(MonadThrow m, KnownNat s, Integral p, Bounded p) =>
Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithoutLoss
  {-# INLINABLE fromRational #-}

instance (KnownNat s) => Fractional (Arith (Decimal r s Word16)) where
  / :: Arith (Decimal r s Word16)
-> Arith (Decimal r s Word16) -> Arith (Decimal r s Word16)
(/) = (Decimal r s Word16
 -> Decimal r s Word16 -> Arith (Decimal r s Word16))
-> Arith (Decimal r s Word16)
-> Arith (Decimal r s Word16)
-> Arith (Decimal r s Word16)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word16
-> Decimal r s Word16 -> Arith (Decimal r s Word16)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
divideDecimalBoundedWithoutLoss
  {-# INLINABLE (/) #-}
  fromRational :: Rational -> Arith (Decimal r s Word16)
fromRational = Rational -> Arith (Decimal r s Word16)
forall (m :: * -> *) (s :: Nat) p r.
(MonadThrow m, KnownNat s, Integral p, Bounded p) =>
Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithoutLoss
  {-# INLINABLE fromRational #-}

instance (KnownNat s) => Fractional (Arith (Decimal r s Word32)) where
  / :: Arith (Decimal r s Word32)
-> Arith (Decimal r s Word32) -> Arith (Decimal r s Word32)
(/) = (Decimal r s Word32
 -> Decimal r s Word32 -> Arith (Decimal r s Word32))
-> Arith (Decimal r s Word32)
-> Arith (Decimal r s Word32)
-> Arith (Decimal r s Word32)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word32
-> Decimal r s Word32 -> Arith (Decimal r s Word32)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
divideDecimalBoundedWithoutLoss
  {-# INLINABLE (/) #-}
  fromRational :: Rational -> Arith (Decimal r s Word32)
fromRational = Rational -> Arith (Decimal r s Word32)
forall (m :: * -> *) (s :: Nat) p r.
(MonadThrow m, KnownNat s, Integral p, Bounded p) =>
Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithoutLoss
  {-# INLINABLE fromRational #-}

instance (KnownNat s) => Fractional (Arith (Decimal r s Word64)) where
  / :: Arith (Decimal r s Word64)
-> Arith (Decimal r s Word64) -> Arith (Decimal r s Word64)
(/) = (Decimal r s Word64
 -> Decimal r s Word64 -> Arith (Decimal r s Word64))
-> Arith (Decimal r s Word64)
-> Arith (Decimal r s Word64)
-> Arith (Decimal r s Word64)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
bindM2 Decimal r s Word64
-> Decimal r s Word64 -> Arith (Decimal r s Word64)
forall r (s :: Nat) p (m :: * -> *).
(Integral p, Bounded p, KnownNat s, MonadThrow m) =>
Decimal r s p -> Decimal r s p -> m (Decimal r s p)
divideDecimalBoundedWithoutLoss
  {-# INLINABLE (/) #-}
  fromRational :: Rational -> Arith (Decimal r s Word64)
fromRational = Rational -> Arith (Decimal r s Word64)
forall (m :: * -> *) (s :: Nat) p r.
(MonadThrow m, KnownNat s, Integral p, Bounded p) =>
Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithoutLoss
  {-# INLINABLE fromRational #-}


-- | Add two decimal numbers backed by `Integer`.
--
-- @since 0.1.0
plusDecimal :: Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
plusDecimal :: Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
plusDecimal = (Integer -> Integer -> Integer)
-> Decimal r s Integer
-> Decimal r s Integer
-> Decimal r s Integer
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(+)
{-# INLINABLE plusDecimal #-}

-- | Subtract two decimal numbers backed by `Integer`.
--
-- @since 0.1.0
minusDecimal ::
     Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
minusDecimal :: Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
minusDecimal = (Integer -> Integer -> Integer)
-> Decimal r s Integer
-> Decimal r s Integer
-> Decimal r s Integer
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (-)
{-# INLINABLE minusDecimal #-}


-- divideDecimalWithoutLoss ::
--      (MonadThrow m, KnownNat s)
--   => Decimal r s Integer
--   -> Decimal r s Integer
--   -> m (Decimal r s Integer)
-- divideDecimalWithoutLoss (Decimal x) (Decimal y)
--   | y == 0 = throwM DivideByZero
--   | otherwise = fromRationalDecimalWithoutLoss (toInteger x % toInteger y)
-- {-# INLINABLE divideDecimalWithoutLoss #-}

-- divideDecimalBoundedWithoutLoss ::
--      (MonadThrow m, KnownNat s, Bounded p, Integral p)
--   => Decimal r s p
--   -> Decimal r s p
--   -> m (Decimal r s p)
-- divideDecimalBoundedWithoutLoss (Decimal x) (Decimal y)
--   | y == 0 = throwM DivideByZero
--   | otherwise = fromRationalDecimalBoundedWithoutLoss (toInteger x % toInteger y)
-- {-# INLINABLE divideDecimalBoundedWithoutLoss #-}

divideDecimalWithRounding ::
     (MonadThrow m, KnownNat s, Round r Integer)
  => Decimal r s Integer
  -> Decimal r s Integer
  -> m (Decimal r s Integer)
divideDecimalWithRounding :: Decimal r s Integer
-> Decimal r s Integer -> m (Decimal r s Integer)
divideDecimalWithRounding (Decimal Integer
x) (Decimal Integer
y)
  | Integer
y Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = ArithException -> m (Decimal r s Integer)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM ArithException
DivideByZero
  | Bool
otherwise = Rational -> m (Decimal r s Integer)
forall (m :: * -> *) r (s :: Nat).
(MonadThrow m, KnownNat s, Round r Integer) =>
Rational -> m (Decimal r s Integer)
fromRationalDecimalWithRounding (Integer -> Integer
forall a. Integral a => a -> Integer
toInteger Integer
x Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer -> Integer
forall a. Integral a => a -> Integer
toInteger Integer
y)
{-# INLINABLE divideDecimalWithRounding #-}

divideDecimalBoundedWithRounding ::
     (MonadThrow m, KnownNat s, Round r Integer, Bounded p, Integral p)
  => Decimal r s p
  -> Decimal r s p
  -> m (Decimal r s p)
divideDecimalBoundedWithRounding :: Decimal r s p -> Decimal r s p -> m (Decimal r s p)
divideDecimalBoundedWithRounding (Decimal p
x) (Decimal p
y)
  | p
y p -> p -> Bool
forall a. Eq a => a -> a -> Bool
== p
0 = ArithException -> m (Decimal r s p)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM ArithException
DivideByZero
  | Bool
otherwise = Rational -> m (Decimal r s p)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, KnownNat s, Round r Integer, Bounded p,
 Integral p) =>
Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithRounding (p -> Integer
forall a. Integral a => a -> Integer
toInteger p
x Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% p -> Integer
forall a. Integral a => a -> Integer
toInteger p
y)
{-# INLINABLE divideDecimalBoundedWithRounding #-}


quotRemDecimalBounded ::
     forall m r s p. (MonadThrow m, Integral p, Bounded p)
  => Decimal r s p
  -> Integer
  -> m (Decimal r s p, Decimal r s p)
quotRemDecimalBounded :: Decimal r s p -> Integer -> m (Decimal r s p, Decimal r s p)
quotRemDecimalBounded (Decimal p
raw) Integer
i
  | Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< p -> Integer
forall a. Integral a => a -> Integer
toInteger (p
forall a. Bounded a => a
minBound :: p) = ArithException -> m (Decimal r s p, Decimal r s p)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM ArithException
Underflow
  | Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> p -> Integer
forall a. Integral a => a -> Integer
toInteger (p
forall a. Bounded a => a
maxBound :: p) = ArithException -> m (Decimal r s p, Decimal r s p)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM ArithException
Overflow
  | Bool
otherwise = do
      p
i' <- Integer -> m p
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Bounded a) =>
Integer -> m a
fromIntegerBounded Integer
i
      (p
q, p
r) <- p -> p -> m (p, p)
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Bounded a) =>
a -> a -> m (a, a)
quotRemBounded p
raw p
i'
      (Decimal r s p, Decimal r s p) -> m (Decimal r s p, Decimal r s p)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (p -> Decimal r s p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal p
q, p -> Decimal r s p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal p
r)
{-# INLINABLE quotRemDecimalBounded #-}


fromIntegerScaleBounded ::
     forall m a s. (MonadThrow m, Integral a, Bounded a, KnownNat s)
  => Proxy s
  -> Integer
  -> m a
fromIntegerScaleBounded :: Proxy s -> Integer -> m a
fromIntegerScaleBounded Proxy s
px Integer
x = Integer -> m a
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Bounded a) =>
Integer -> m a
fromIntegerBounded Integer
xs
  where
    xs :: Integer
xs = Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* (Integer
10 Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Proxy s -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal Proxy s
px)
{-# INLINABLE fromIntegerScaleBounded #-}


fromIntegersScaleBounded ::
     forall m a s. (MonadThrow m, Integral a, Bounded a, KnownNat s)
  => Proxy s
  -> Integer
  -> Integer
  -> m a
fromIntegersScaleBounded :: Proxy s -> Integer -> Integer -> m a
fromIntegersScaleBounded Proxy s
ps Integer
x Integer
y = Integer -> m a
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Bounded a) =>
Integer -> m a
fromIntegerBounded Integer
xs
  where
    xs :: Integer
xs = Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* (Integer
10 Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Proxy s -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal Proxy s
ps) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
y
{-# INLINABLE fromIntegersScaleBounded #-}


-- | Convert an Integer to a Decimal backed by a bounded integral while doing proper
-- scaling and checking the bounds.
--
-- @since 0.2.0
fromIntegerDecimalBoundedIntegral ::
     forall m r s p. (MonadThrow m, Integral p, Bounded p, KnownNat s)
  => Integer
  -> m (Decimal r s p)
fromIntegerDecimalBoundedIntegral :: Integer -> m (Decimal r s p)
fromIntegerDecimalBoundedIntegral Integer
x = p -> Decimal r s p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (p -> Decimal r s p) -> m p -> m (Decimal r s p)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Proxy s -> Integer -> m p
forall (m :: * -> *) a (s :: Nat).
(MonadThrow m, Integral a, Bounded a, KnownNat s) =>
Proxy s -> Integer -> m a
fromIntegerScaleBounded (Proxy s
forall k (t :: k). Proxy t
Proxy :: Proxy s) Integer
x
{-# INLINABLE fromIntegerDecimalBoundedIntegral #-}


fromIntegerDecimalBounded ::
     forall m r s p. (MonadThrow m, Integral p, Bounded p)
  => Decimal r s Integer
  -> m (Decimal r s p)
fromIntegerDecimalBounded :: Decimal r s Integer -> m (Decimal r s p)
fromIntegerDecimalBounded (Decimal Integer
x) = p -> Decimal r s p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (p -> Decimal r s p) -> m p -> m (Decimal r s p)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Integer -> m p
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Bounded a) =>
Integer -> m a
fromIntegerBounded Integer
x
{-# INLINABLE fromIntegerDecimalBounded #-}



-- | Add two decimal numbers.
--
-- @since 0.1.0
plusDecimalBounded ::
     (MonadThrow m, Eq p, Ord p, Num p, Bounded p)
  => Decimal r s p
  -> Decimal r s p
  -> m (Decimal r s p)
plusDecimalBounded :: Decimal r s p -> Decimal r s p -> m (Decimal r s p)
plusDecimalBounded (Decimal p
x) (Decimal p
y) = p -> Decimal r s p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (p -> Decimal r s p) -> m p -> m (Decimal r s p)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> p -> p -> m p
forall (m :: * -> *) a.
(MonadThrow m, Ord a, Num a, Bounded a) =>
a -> a -> m a
plusBounded p
x p
y
{-# INLINABLE plusDecimalBounded #-}

-- | Subtract two decimal numbers.
--
-- @since 0.1.0
minusDecimalBounded ::
     (MonadThrow m, Eq p, Ord p, Num p, Bounded p)
  => Decimal r s p
  -> Decimal r s p
  -> m (Decimal r s p)
minusDecimalBounded :: Decimal r s p -> Decimal r s p -> m (Decimal r s p)
minusDecimalBounded (Decimal p
x) (Decimal p
y) = p -> Decimal r s p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (p -> Decimal r s p) -> m p -> m (Decimal r s p)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> p -> p -> m p
forall (m :: * -> *) a.
(MonadThrow m, Ord a, Num a, Bounded a) =>
a -> a -> m a
minusBounded p
x p
y
{-# INLINABLE minusDecimalBounded #-}

-- | Multiply two bounded decimal numbers, adjusting their scale at the type level as well.
--
-- @since 0.1.0
timesDecimalBounded ::
     (MonadThrow m, Integral p, Bounded p)
  => Decimal r s1 p
  -> Decimal r s2 p
  -> m (Decimal r (s1 + s2) p)
timesDecimalBounded :: Decimal r s1 p -> Decimal r s2 p -> m (Decimal r (s1 + s2) p)
timesDecimalBounded (Decimal p
x) (Decimal p
y) = p -> Decimal r (s1 + s2) p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (p -> Decimal r (s1 + s2) p) -> m p -> m (Decimal r (s1 + s2) p)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> p -> p -> m p
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Bounded a) =>
a -> a -> m a
timesBounded p
x p
y
{-# INLINABLE timesDecimalBounded #-}

-- | Multiply two bounded decimal numbers, adjusting their scale at the type level as well.
--
-- @since 0.1.0
timesDecimal ::
     Decimal r s1 Integer
  -> Decimal r s2 Integer
  -> Decimal r (s1 + s2) Integer
timesDecimal :: Decimal r s1 Integer
-> Decimal r s2 Integer -> Decimal r (s1 + s2) Integer
timesDecimal (Decimal Integer
x) (Decimal Integer
y) = Integer -> Decimal r (s1 + s2) Integer
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
y)
{-# INLINABLE timesDecimal #-}


-- | Multiply two decimal numbers backed by `Integer`, while rounding the result according
-- to the rounding strategy.
--
-- @since 0.2.0
timesDecimalWithRounding ::
     (KnownNat s, Round r Integer)
  => Decimal r s Integer
  -> Decimal r s Integer
  -> Decimal r s Integer
timesDecimalWithRounding :: Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
timesDecimalWithRounding Decimal r s Integer
dx Decimal r s Integer
dy = Decimal r (s + s) Integer -> Decimal r s Integer
forall r p (k :: Nat) (n :: Nat).
(Round r p, KnownNat k) =>
Decimal r (n + k) p -> Decimal r n p
roundDecimal (Decimal r (s + s) Integer -> Decimal r s Integer)
-> Decimal r (s + s) Integer -> Decimal r s Integer
forall a b. (a -> b) -> a -> b
$ Decimal r s Integer
-> Decimal r s Integer -> Decimal r (s + s) Integer
forall r (s1 :: Nat) (s2 :: Nat).
Decimal r s1 Integer
-> Decimal r s2 Integer -> Decimal r (s1 + s2) Integer
timesDecimal Decimal r s Integer
dx Decimal r s Integer
dy
{-# INLINABLE timesDecimalWithRounding #-}


-- | Multiply two decimal numbers, while rounding the result according to the rounding strategy.
--
-- @since 0.2.0
timesDecimalBoundedWithRounding ::
     (MonadThrow m, KnownNat s, Round r Integer, Integral p, Bounded p)
  => Decimal r s p
  -> Decimal r s p
  -> m (Decimal r s p)
timesDecimalBoundedWithRounding :: Decimal r s p -> Decimal r s p -> m (Decimal r s p)
timesDecimalBoundedWithRounding Decimal r s p
dx Decimal r s p
dy =
  Decimal r s Integer -> m (Decimal r s p)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p) =>
Decimal r s Integer -> m (Decimal r s p)
fromIntegerDecimalBounded (Decimal r s Integer -> m (Decimal r s p))
-> Decimal r s Integer -> m (Decimal r s p)
forall a b. (a -> b) -> a -> b
$ Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
forall (s :: Nat) r.
(KnownNat s, Round r Integer) =>
Decimal r s Integer -> Decimal r s Integer -> Decimal r s Integer
timesDecimalWithRounding ((p -> Integer) -> Decimal r s p -> Decimal r s Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap p -> Integer
forall a. Integral a => a -> Integer
toInteger Decimal r s p
dx) ((p -> Integer) -> Decimal r s p -> Decimal r s Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap p -> Integer
forall a. Integral a => a -> Integer
toInteger Decimal r s p
dy)
{-# INLINABLE timesDecimalBoundedWithRounding #-}



-- | Multiply two decimal numbers that have the same scale, while throwing `PrecisionLoss`
-- whenever multiplication cannot be done without rounding. Also checks for bounds and can
-- throw `Overflow`/`Underflow`.
--
-- @since 0.2.0
timesDecimalBoundedWithoutLoss ::
     forall r s p m. (Integral p, Bounded p, KnownNat s, MonadThrow m)
  => Decimal r s p
  -> Decimal r s p
  -> m (Decimal r s p)
timesDecimalBoundedWithoutLoss :: Decimal r s p -> Decimal r s p -> m (Decimal r s p)
timesDecimalBoundedWithoutLoss Decimal r s p
d1 (Decimal p
i2)
  | Rational
q Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer -> Rational
forall a. Real a => a -> Rational
toRational Integer
i =
    PrecisionLoss -> m (Decimal r s p)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PrecisionLoss -> m (Decimal r s p))
-> PrecisionLoss -> m (Decimal r s p)
forall a b. (a -> b) -> a -> b
$ Rational -> Integer -> PrecisionLoss
PrecisionLoss (Rational
q Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* (Integer
1 Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Decimal r s p -> Integer
forall (s :: Nat) r p. KnownNat s => Decimal r s p -> Integer
decimalDenominator Decimal r s p
d1)) (Integer -> PrecisionLoss) -> Integer -> PrecisionLoss
forall a b. (a -> b) -> a -> b
$ Decimal r s p -> Integer
forall r (s :: Nat) p. KnownNat s => Decimal r s p -> Integer
getScale Decimal r s p
d1
  | Bool
otherwise = Decimal r s Integer -> m (Decimal r s p)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p) =>
Decimal r s Integer -> m (Decimal r s p)
fromIntegerDecimalBounded (Decimal r s Integer -> m (Decimal r s p))
-> Decimal r s Integer -> m (Decimal r s p)
forall a b. (a -> b) -> a -> b
$ Integer -> Decimal r s Integer
forall r (s :: Nat) a. a -> Decimal r s a
Decimal Integer
i
  where
    q :: Rational
q = Decimal r s p -> Rational
forall (s :: Nat) p r.
(KnownNat s, Integral p) =>
Decimal r s p -> Rational
toRationalDecimal Decimal r s p
d1 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* (p -> Integer
forall a. Integral a => a -> Integer
toInteger p
i2 Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer
1)
    i :: Integer
i = Rational -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
truncate Rational
q


-- | Multiply two decimal numbers that have the same scale, while throwing `PrecisionLoss`
-- whenever multiplication cannot be done without rounding.
--
-- @since 0.2.0
timesDecimalWithoutLoss ::
     forall r s m. (KnownNat s, MonadThrow m)
  => Decimal r s Integer
  -> Decimal r s Integer
  -> m (Decimal r s Integer)
timesDecimalWithoutLoss :: Decimal r s Integer
-> Decimal r s Integer -> m (Decimal r s Integer)
timesDecimalWithoutLoss Decimal r s Integer
d1 (Decimal Integer
i2)
  | Rational
q Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer -> Rational
forall a. Real a => a -> Rational
toRational Integer
i =
    PrecisionLoss -> m (Decimal r s Integer)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PrecisionLoss -> m (Decimal r s Integer))
-> PrecisionLoss -> m (Decimal r s Integer)
forall a b. (a -> b) -> a -> b
$ Rational -> Integer -> PrecisionLoss
PrecisionLoss (Rational
q Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* (Integer
1 Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Decimal r s Integer -> Integer
forall (s :: Nat) r p. KnownNat s => Decimal r s p -> Integer
decimalDenominator Decimal r s Integer
d1)) (Integer -> PrecisionLoss) -> Integer -> PrecisionLoss
forall a b. (a -> b) -> a -> b
$ Decimal r s Integer -> Integer
forall r (s :: Nat) p. KnownNat s => Decimal r s p -> Integer
getScale Decimal r s Integer
d1
  | Bool
otherwise = Decimal r s Integer -> m (Decimal r s Integer)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Decimal r s Integer -> m (Decimal r s Integer))
-> Decimal r s Integer -> m (Decimal r s Integer)
forall a b. (a -> b) -> a -> b
$ Integer -> Decimal r s Integer
forall r (s :: Nat) a. a -> Decimal r s a
Decimal Integer
i
  where
    q :: Rational
q = Decimal r s Integer -> Rational
forall (s :: Nat) p r.
(KnownNat s, Integral p) =>
Decimal r s p -> Rational
toRationalDecimal Decimal r s Integer
d1 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* (Integer -> Integer
forall a. Integral a => a -> Integer
toInteger Integer
i2 Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer
1)
    i :: Integer
i = Rational -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
truncate Rational
q



-- | Divide two decimal numbers that have the same scale, while throwing `PrecisionLoss`
-- whenever division cannot be done without rounding.
--
-- @since 0.2.0
divideDecimalWithoutLoss ::
     forall r s m. (KnownNat s, MonadThrow m)
  => Decimal r s Integer
  -> Decimal r s Integer
  -> m (Decimal r s Integer)
divideDecimalWithoutLoss :: Decimal r s Integer
-> Decimal r s Integer -> m (Decimal r s Integer)
divideDecimalWithoutLoss Decimal r s Integer
d1 (Decimal Integer
i2)
  | Integer
i2 Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = ArithException -> m (Decimal r s Integer)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM ArithException
DivideByZero
  | Rational
q Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer -> Rational
forall a. Real a => a -> Rational
toRational Integer
i = PrecisionLoss -> m (Decimal r s Integer)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PrecisionLoss -> m (Decimal r s Integer))
-> PrecisionLoss -> m (Decimal r s Integer)
forall a b. (a -> b) -> a -> b
$ Rational -> Integer -> PrecisionLoss
PrecisionLoss (Rational
q Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* (Integer
1 Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Decimal r s Integer -> Integer
forall (s :: Nat) r p. KnownNat s => Decimal r s p -> Integer
decimalDenominator Decimal r s Integer
d1)) (Integer -> PrecisionLoss) -> Integer -> PrecisionLoss
forall a b. (a -> b) -> a -> b
$ Decimal r s Integer -> Integer
forall r (s :: Nat) p. KnownNat s => Decimal r s p -> Integer
getScale Decimal r s Integer
d1
  | Bool
otherwise = Decimal r s Integer -> m (Decimal r s Integer)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Decimal r s Integer -> m (Decimal r s Integer))
-> Decimal r s Integer -> m (Decimal r s Integer)
forall a b. (a -> b) -> a -> b
$ Integer -> Decimal r s Integer
forall r (s :: Nat) a. a -> Decimal r s a
Decimal Integer
i
  where
    q :: Rational
q = (Decimal r s Integer -> Integer
forall p r (s :: Nat). Integral p => Decimal r s p -> Integer
decimalNumerator Decimal r s Integer
d1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Decimal r s Integer -> Integer
forall (s :: Nat) r p. KnownNat s => Decimal r s p -> Integer
decimalDenominator Decimal r s Integer
d1) Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer -> Integer
forall a. Integral a => a -> Integer
toInteger Integer
i2
    i :: Integer
i = Rational -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
truncate Rational
q


-- | Divide two decimal numbers that have the same scale, while throwing `PrecisionLoss`
-- whenever division cannot be done without rounding.
--
-- @since 0.2.0
divideDecimalBoundedWithoutLoss ::
     forall r s p m. (Integral p, Bounded p, KnownNat s, MonadThrow m)
  => Decimal r s p
  -> Decimal r s p
  -> m (Decimal r s p)
divideDecimalBoundedWithoutLoss :: Decimal r s p -> Decimal r s p -> m (Decimal r s p)
divideDecimalBoundedWithoutLoss Decimal r s p
d1 (Decimal p
i2)
  | p
i2 p -> p -> Bool
forall a. Eq a => a -> a -> Bool
== p
0 = ArithException -> m (Decimal r s p)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM ArithException
DivideByZero
  | Rational
q Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer -> Rational
forall a. Real a => a -> Rational
toRational Integer
i = PrecisionLoss -> m (Decimal r s p)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PrecisionLoss -> m (Decimal r s p))
-> PrecisionLoss -> m (Decimal r s p)
forall a b. (a -> b) -> a -> b
$ Rational -> Integer -> PrecisionLoss
PrecisionLoss (Rational
q Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* (Integer
1 Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Decimal r s p -> Integer
forall (s :: Nat) r p. KnownNat s => Decimal r s p -> Integer
decimalDenominator Decimal r s p
d1)) (Integer -> PrecisionLoss) -> Integer -> PrecisionLoss
forall a b. (a -> b) -> a -> b
$ Decimal r s p -> Integer
forall r (s :: Nat) p. KnownNat s => Decimal r s p -> Integer
getScale Decimal r s p
d1
  | Bool
otherwise = Decimal r s Integer -> m (Decimal r s p)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p) =>
Decimal r s Integer -> m (Decimal r s p)
fromIntegerDecimalBounded (Decimal r s Integer -> m (Decimal r s p))
-> Decimal r s Integer -> m (Decimal r s p)
forall a b. (a -> b) -> a -> b
$ Integer -> Decimal r s Integer
forall r (s :: Nat) a. a -> Decimal r s a
Decimal Integer
i
  where
    q :: Rational
q = (Decimal r s p -> Integer
forall p r (s :: Nat). Integral p => Decimal r s p -> Integer
decimalNumerator Decimal r s p
d1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Decimal r s p -> Integer
forall (s :: Nat) r p. KnownNat s => Decimal r s p -> Integer
decimalDenominator Decimal r s p
d1) Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% p -> Integer
forall a. Integral a => a -> Integer
toInteger p
i2
    i :: Integer
i = Rational -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
truncate Rational
q


toRationalDecimalInteger :: forall r s . KnownNat s => Decimal r s Integer -> Rational
toRationalDecimalInteger :: Decimal r s Integer -> Rational
toRationalDecimalInteger (Decimal Integer
p) = Integer
p Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% (Integer
10 Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Proxy s -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy s
forall k (t :: k). Proxy t
Proxy :: Proxy s))
{-# INLINABLE toRationalDecimalInteger #-}

-- | Convert a decimal to a Rational
--
-- @since 0.2.0
toRationalDecimal ::
     (KnownNat s, Integral p) => Decimal r s p -> Rational
toRationalDecimal :: Decimal r s p -> Rational
toRationalDecimal Decimal r s p
d = Decimal r s Integer -> Rational
forall r (s :: Nat). KnownNat s => Decimal r s Integer -> Rational
toRationalDecimalInteger (p -> Integer
forall a. Integral a => a -> Integer
toInteger (p -> Integer) -> Decimal r s p -> Decimal r s Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decimal r s p
d)
{-# INLINABLE toRationalDecimal #-}

-- | Convert from `Rational` to a `Decimal` backed by `Integer`. `PrecisionLoss` will be
-- thrown if conversion cannot be achieved without any loss of data. In case that rounding
-- is acceptable use `fromRationalDecimalBoundedWithRounding`
--
-- @since 0.2.0
fromRationalDecimalWithoutLoss ::
     forall m r s. (MonadThrow m, KnownNat s)
  => Rational
  -> m (Decimal r s Integer)
fromRationalDecimalWithoutLoss :: Rational -> m (Decimal r s Integer)
fromRationalDecimalWithoutLoss Rational
rational
  | Rational -> Integer
forall a. Ratio a -> a
denominator Rational
rational Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = ArithException -> m (Decimal r s Integer)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM ArithException
DivideByZero
  | Integer -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
t Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
/= Rational
scaledRat = PrecisionLoss -> m (Decimal r s Integer)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (Rational -> Integer -> PrecisionLoss
PrecisionLoss Rational
rational Integer
s)
  | Bool
otherwise = Decimal r s Integer -> m (Decimal r s Integer)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Decimal r s Integer
truncated
  where
    truncated :: Decimal r s Integer
truncated@(Decimal Integer
t) = Integer -> Decimal r s Integer
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (Rational -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
truncate Rational
scaledRat) :: Decimal r s Integer
    scaledRat :: Rational
scaledRat = Rational
rational Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* (Integer
d Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer
1)
    s :: Integer
s = Proxy s -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy s
forall k (t :: k). Proxy t
Proxy :: Proxy s)
    d :: Integer
d = Integer
10 Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
s
{-# INLINABLE fromRationalDecimalWithoutLoss #-}

-- | Convert a `Rational` to a bounded `Decimal`, but only if there is no precision loss
-- or `Overflow`/`Undeflow`.
--
-- @since 0.2.0
fromRationalDecimalBoundedWithoutLoss ::
     (MonadThrow m, KnownNat s, Integral p, Bounded p)
  => Rational
  -> m (Decimal r s p)
fromRationalDecimalBoundedWithoutLoss :: Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithoutLoss Rational
r =
  Rational -> m (Decimal r s Integer)
forall (m :: * -> *) r (s :: Nat).
(MonadThrow m, KnownNat s) =>
Rational -> m (Decimal r s Integer)
fromRationalDecimalWithoutLoss Rational
r m (Decimal r s Integer)
-> (Decimal r s Integer -> m (Decimal r s p)) -> m (Decimal r s p)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Decimal r s Integer -> m (Decimal r s p)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p) =>
Decimal r s Integer -> m (Decimal r s p)
fromIntegerDecimalBounded
{-# INLINABLE fromRationalDecimalBoundedWithoutLoss #-}

fromRationalDecimalWithRounding ::
     forall m r s . (MonadThrow m, KnownNat s, Round r Integer)
  => Rational
  -> m (Decimal r s Integer)
fromRationalDecimalWithRounding :: Rational -> m (Decimal r s Integer)
fromRationalDecimalWithRounding Rational
rational
  | Rational -> Integer
forall a. Ratio a -> a
denominator Rational
rational Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = ArithException -> m (Decimal r s Integer)
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM ArithException
DivideByZero
  | Bool
otherwise =
    Decimal r s Integer -> m (Decimal r s Integer)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Decimal r s Integer -> m (Decimal r s Integer))
-> Decimal r s Integer -> m (Decimal r s Integer)
forall a b. (a -> b) -> a -> b
$ Decimal r (s + 1) Integer -> Decimal r s Integer
forall r p (k :: Nat) (n :: Nat).
(Round r p, KnownNat k) =>
Decimal r (n + k) p -> Decimal r n p
roundDecimal (Integer -> Decimal r (s + 1) Integer
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (Rational -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
truncate Rational
scaledRat) :: Decimal r (s + 1) Integer)
  where
    scaledRat :: Rational
scaledRat = Rational
rational Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* (Integer
d Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer
1)
    d :: Integer
d = Integer
10 Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ (Proxy s -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy s
forall k (t :: k). Proxy t
Proxy :: Proxy s) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1)
{-# INLINABLE fromRationalDecimalWithRounding #-}


fromRationalDecimalBoundedWithRounding ::
     forall m r s p. (MonadThrow m, KnownNat s, Round r Integer, Bounded p, Integral p)
  => Rational
  -> m (Decimal r s p)
fromRationalDecimalBoundedWithRounding :: Rational -> m (Decimal r s p)
fromRationalDecimalBoundedWithRounding =
  Rational -> m (Decimal r s Integer)
forall (m :: * -> *) r (s :: Nat).
(MonadThrow m, KnownNat s, Round r Integer) =>
Rational -> m (Decimal r s Integer)
fromRationalDecimalWithRounding (Rational -> m (Decimal r s Integer))
-> (Decimal r s Integer -> m (Decimal r s p))
-> Rational
-> m (Decimal r s p)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Decimal r s Integer -> m (Decimal r s p)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p) =>
Decimal r s Integer -> m (Decimal r s p)
fromIntegerDecimalBounded
{-# INLINABLE fromRationalDecimalBoundedWithRounding #-}


-- | Compute absolute value of a decimal
--
-- @since 0.2.0
absDecimal :: KnownNat s => Decimal r s Integer -> Decimal r s Integer
absDecimal :: Decimal r s Integer -> Decimal r s Integer
absDecimal (Decimal Integer
d) = Integer -> Decimal r s Integer
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (Integer -> Integer
forall a. Num a => a -> a
abs Integer
d)
{-# INLINABLE absDecimal #-}

-- | Compute signum of a decimal, always one of 1, 0 or -1
--
-- @since 0.2.0
signumDecimal :: KnownNat s => Decimal r s Integer -> Decimal r s Integer
signumDecimal :: Decimal r s Integer -> Decimal r s Integer
signumDecimal (Decimal Integer
d) = Integer -> Decimal r s Integer
forall r (s :: Nat). KnownNat s => Integer -> Decimal r s Integer
fromIntegerDecimal (Integer -> Integer
forall a. Num a => a -> a
signum Integer
d)
{-# INLINABLE signumDecimal #-}

-- | Compute signum of a decimal, always one of 1, 0 or -1
signumDecimalBounded ::
     (KnownNat s, MonadThrow m, Integral p, Bounded p)
  => Decimal r s p
  -> m (Decimal r s p)
signumDecimalBounded :: Decimal r s p -> m (Decimal r s p)
signumDecimalBounded Decimal r s p
d = Decimal r s Integer -> m (Decimal r s p)
forall (m :: * -> *) r (s :: Nat) p.
(MonadThrow m, Integral p, Bounded p) =>
Decimal r s Integer -> m (Decimal r s p)
fromIntegerDecimalBounded (Decimal r s Integer -> m (Decimal r s p))
-> Decimal r s Integer -> m (Decimal r s p)
forall a b. (a -> b) -> a -> b
$ Decimal r s Integer -> Decimal r s Integer
forall (s :: Nat) r.
KnownNat s =>
Decimal r s Integer -> Decimal r s Integer
signumDecimal (p -> Integer
forall a. Integral a => a -> Integer
toInteger (p -> Integer) -> Decimal r s p -> Decimal r s Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decimal r s p
d)
{-# INLINABLE signumDecimalBounded #-}

-- | Compute absolute value of a bounded decimal. Protects against overflows for negative
-- `minBound`.
--
-- >>> abs (minBound :: Int8)
-- -128
-- >>> import Numeric.Decimal
-- >>> d <- arithM (fromRational (-1.28) :: Arith (Decimal RoundHalfUp 2 Int8))
-- >>> d
-- -1.28
-- >>> absDecimalBounded d :: Either SomeException (Decimal RoundHalfUp 2 Int8)
-- Left arithmetic overflow
--
-- /Note/ - Watch out for order of negation
--
-- >>> -1.28 :: Arith (Decimal RoundHalfUp 2 Int8)
-- ArithError arithmetic overflow
-- >>> negate (1.28 :: Arith (Decimal RoundHalfUp 2 Int8))
-- ArithError arithmetic overflow
-- >>> :set -XNegativeLiterals
-- >>> -1.28 :: Arith (Decimal RoundHalfUp 2 Int8)
-- Arith -1.28
--
-- @since 0.2.0
absDecimalBounded ::
     (KnownNat s, MonadThrow m, Integral p, Bounded p)
  => Decimal r s p
  -> m (Decimal r s p)
absDecimalBounded :: Decimal r s p -> m (Decimal r s p)
absDecimalBounded = (p -> Decimal r s p) -> m p -> m (Decimal r s p)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap p -> Decimal r s p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal (m p -> m (Decimal r s p))
-> (Decimal r s p -> m p) -> Decimal r s p -> m (Decimal r s p)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. p -> m p
forall (m :: * -> *) p. (MonadThrow m, Num p, Ord p) => p -> m p
absBounded (p -> m p) -> (Decimal r s p -> p) -> Decimal r s p -> m p
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Decimal r s p -> p
coerce
{-# INLINABLE absDecimalBounded #-}


-----------------------------------
-- Showing ------------------------
-----------------------------------

instance (Integral p, KnownNat s) => Show (Decimal r s p) where
  show :: Decimal r s p -> String
show d :: Decimal r s p
d@(Decimal p
a)
    | Int
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Integer -> String
forall a. Show a => a -> String
show (Integer -> String) -> Integer -> String
forall a b. (a -> b) -> a -> b
$ p -> Integer
forall a. Integral a => a -> Integer
toInteger p
a
    | Integer
r Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = String -> Integer -> String
forall r. PrintfType r => String -> r
printf (String
"%d." String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
s Char
'0') Integer
q
    | Integer -> Integer
forall a. Num a => a -> a
signum Integer
r Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 Bool -> Bool -> Bool
&& Integer
q Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = String
"-" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
formatted
    | Bool
otherwise = String
formatted
    where
      formatted :: String
formatted = String -> Integer -> Integer -> String
forall r. PrintfType r => String -> r
printf String
fmt Integer
q (Integer -> Integer
forall a. Num a => a -> a
abs Integer
r)
      s :: Int
s = Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Decimal r s p -> Integer
forall r (s :: Nat) p. KnownNat s => Decimal r s p -> Integer
getScale Decimal r s p
d
      fmt :: String
fmt = String
"%d.%0" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
s String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"u"
      (Integer
q, Integer
r) = Integer -> Integer -> (Integer, Integer)
forall a. Integral a => a -> a -> (a, a)
quotRem (p -> Integer
forall a. Integral a => a -> Integer
toInteger p
a) (Integer
10 Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
s)

-----------------------------------
-- Parsing ------------------------
-----------------------------------

maxBoundCharsCount :: forall a . (Integral a, Bounded a) => Proxy a -> Int
maxBoundCharsCount :: Proxy a -> Int
maxBoundCharsCount Proxy a
_ = String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Integer -> String
forall a. Show a => a -> String
show (a -> Integer
forall a. Integral a => a -> Integer
toInteger (a
forall a. Bounded a => a
maxBound :: a)))

minBoundCharsCount :: forall a . (Integral a, Bounded a) => Proxy a -> Int
minBoundCharsCount :: Proxy a -> Int
minBoundCharsCount Proxy a
_ = String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Integer -> String
forall a. Show a => a -> String
show (a -> Integer
forall a. Integral a => a -> Integer
toInteger (a
forall a. Bounded a => a
minBound :: a)))


parseDecimalBounded ::
     forall r s p. (KnownNat s, Bounded p, Integral p)
  => Bool
  -> String
  -> Either String (Decimal r s p)
parseDecimalBounded :: Bool -> String -> Either String (Decimal r s p)
parseDecimalBounded Bool
checkForPlusSign String
rawInput
  | Bool -> Bool
not (String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
tooMuch) = String -> Either String (Decimal r s p)
forall a b. a -> Either a b
Left String
"Input is too big for parsing as a bounded Decimal value"
  | Bool
otherwise = do
    (Integer
sign, String
signLeftOver) <- String -> Either String (Integer, String)
getSign String
input
    -- by now we conditionally extracted the sign (+/-)
    (Integer
num, String
leftOver) <- String -> Either String (Integer, String)
forall a. Num a => String -> Either String (a, String)
digits String
signLeftOver
    let s :: Int
s = Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Proxy s -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal Proxy s
spx) :: Int
    case String -> Maybe (Char, String)
forall a. [a] -> Maybe (a, [a])
uncons String
leftOver of
      Maybe (Char, String)
Nothing -> Either SomeException p -> Either String (Decimal r s p)
toStringError (Proxy s -> Integer -> Either SomeException p
forall (m :: * -> *) a (s :: Nat).
(MonadThrow m, Integral a, Bounded a, KnownNat s) =>
Proxy s -> Integer -> m a
fromIntegerScaleBounded Proxy s
spx (Integer
sign Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
num))
      Just (Char
'.', String
digitsTxt)
        | String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
digitsTxt Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
s -> String -> Either String (Decimal r s p)
forall a b. a -> Either a b
Left (String -> Either String (Decimal r s p))
-> String -> Either String (Decimal r s p)
forall a b. (a -> b) -> a -> b
$ String
"Too much text after the decimal: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
digitsTxt
      Just (Char
'.', String
digitsTxt)
        | Bool -> Bool
not (String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
digitsTxt) -> do
          (Integer
decimalDigits, String
extraTxt) <- String -> Either String (Integer, String)
forall a. Num a => String -> Either String (a, String)
digits (String
digitsTxt String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
digitsTxt) Char
'0')
          Bool -> Either String () -> Either String ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
extraTxt) (Either String () -> Either String ())
-> Either String () -> Either String ()
forall a b. (a -> b) -> a -> b
$ String -> Either String ()
forall a b. a -> Either a b
Left (String -> Either String ()) -> String -> Either String ()
forall a b. (a -> b) -> a -> b
$ String
"Unrecognized digits: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
digitsTxt
          Either SomeException p -> Either String (Decimal r s p)
toStringError (Proxy s -> Integer -> Integer -> Either SomeException p
forall (m :: * -> *) a (s :: Nat).
(MonadThrow m, Integral a, Bounded a, KnownNat s) =>
Proxy s -> Integer -> Integer -> m a
fromIntegersScaleBounded Proxy s
spx (Integer
sign Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
num) (Integer
sign Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
decimalDigits))
      Maybe (Char, String)
_ -> String -> Either String (Decimal r s p)
forall a b. a -> Either a b
Left (String -> Either String (Decimal r s p))
-> String -> Either String (Decimal r s p)
forall a b. (a -> b) -> a -> b
$ String
"Unrecognized left over text: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
leftOver
  where
    spx :: Proxy s
spx = Proxy s
forall k (t :: k). Proxy t
Proxy :: Proxy s
    toStringError :: Either SomeException p -> Either String (Decimal r s p)
toStringError =
      \case
        Left SomeException
exc
          | Just ArithException
Underflow <- SomeException -> Maybe ArithException
forall e. Exception e => SomeException -> Maybe e
fromException SomeException
exc ->
            String -> Either String (Decimal r s p)
forall a b. a -> Either a b
Left (String -> Either String (Decimal r s p))
-> String -> Either String (Decimal r s p)
forall a b. (a -> b) -> a -> b
$ String
"Number is too small to be represented as decimal: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
input
        Left SomeException
exc
          | Just ArithException
Overflow <- SomeException -> Maybe ArithException
forall e. Exception e => SomeException -> Maybe e
fromException SomeException
exc ->
            String -> Either String (Decimal r s p)
forall a b. a -> Either a b
Left (String -> Either String (Decimal r s p))
-> String -> Either String (Decimal r s p)
forall a b. (a -> b) -> a -> b
$ String
"Number is too big to be represented as decimal: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
input
        Left SomeException
err -> String -> Either String (Decimal r s p)
forall a b. a -> Either a b
Left (String -> Either String (Decimal r s p))
-> String -> Either String (Decimal r s p)
forall a b. (a -> b) -> a -> b
$ String
"Unexpected error: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ SomeException -> String
forall e. Exception e => e -> String
displayException SomeException
err
        Right p
val -> Decimal r s p -> Either String (Decimal r s p)
forall a b. b -> Either a b
Right (p -> Decimal r s p
forall r (s :: Nat) a. a -> Decimal r s a
Decimal p
val)
    maxChars :: Int
maxChars =
      Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Proxy p -> Int
forall a. (Integral a, Bounded a) => Proxy a -> Int
maxBoundCharsCount (Proxy p
forall k (t :: k). Proxy t
Proxy :: Proxy p)) (Proxy p -> Int
forall a. (Integral a, Bounded a) => Proxy a -> Int
minBoundCharsCount (Proxy p
forall k (t :: k). Proxy t
Proxy :: Proxy p))
    {-- ^ account for possible dot in the decimal and an extra preceding 0 -}
    (String
input, String
tooMuch) = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt Int
maxChars String
rawInput
    getSign :: String -> Either String (Integer, String)
getSign String
str =
      if (p
forall a. Bounded a => a
minBound :: p) p -> p -> Bool
forall a. Ord a => a -> a -> Bool
>= p
0
        then (Integer, String) -> Either String (Integer, String)
forall a b. b -> Either a b
Right (Integer
1, String
str)
        else case String -> Maybe (Char, String)
forall a. [a] -> Maybe (a, [a])
uncons String
str of
               Maybe (Char, String)
Nothing -> String -> Either String (Integer, String)
forall a b. a -> Either a b
Left String
"Input String is empty"
               Just (Char
'-', String
strLeftOver) -> (Integer, String) -> Either String (Integer, String)
forall a b. b -> Either a b
Right (-Integer
1, String
strLeftOver)
               Just (Char
'+', String
strLeftOver)
                 | Bool
checkForPlusSign -> (Integer, String) -> Either String (Integer, String)
forall a b. b -> Either a b
Right (Integer
1, String
strLeftOver)
               Maybe (Char, String)
_ -> (Integer, String) -> Either String (Integer, String)
forall a b. b -> Either a b
Right (Integer
1, String
str)

digits :: Num a => String -> Either String (a, String)
digits :: String -> Either String (a, String)
digits String
str
  | String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
h = String -> Either String (a, String)
forall a b. a -> Either a b
Left String
"Input does not start with a digit"
  | Bool
otherwise = (a, String) -> Either String (a, String)
forall a b. b -> Either a b
Right ((a -> Char -> a) -> a -> String -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
F.foldl' a -> Char -> a
forall a. Num a => a -> Char -> a
go a
0 String
h, String
t)
  where
    (String
h, String
t) = (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
span Char -> Bool
isDigit String
str
    go :: a -> Char -> a
go a
n Char
d = a
n a -> a -> a
forall a. Num a => a -> a -> a
* a
10 a -> a -> a
forall a. Num a => a -> a -> a
+ Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
digitToInt Char
d)