{-# LANGUAGE CPP #-} {-# LANGUAGE MagicHash #-} module Basement.Numerical.Additive ( Additive(..) ) where #include "MachDeps.h" import Basement.Compat.Base import Basement.Compat.Natural import Basement.Numerical.Number import qualified Prelude import GHC.Types import GHC.Prim import GHC.Int import GHC.Word import Foreign.C.Types #if WORD_SIZE_IN_BITS < 64 import GHC.IntWord64 #endif -- | Represent class of things that can be added together, -- contains a neutral element and is commutative. -- -- > x + azero = x -- > azero + x = x -- > x + y = y + x -- class Additive a where {-# MINIMAL azero, (+) #-} azero :: a -- the identity element over addition (+) :: a -> a -> a -- the addition scale :: IsNatural n => n -> a -> a -- scale: repeated addition scale 0 _ = azero scale 1 a = a scale 2 a = a + a scale n a = a + scale (pred n) a -- TODO optimise. define by group of 2. infixl 6 + instance Additive Integer where azero = 0 (+) = (Prelude.+) scale = scaleNum instance Additive Int where azero = 0 (I# a) + (I# b) = I# (a +# b) scale = scaleNum instance Additive Int8 where azero = 0 (I8# a) + (I8# b) = I8# (narrow8Int# (a +# b)) scale = scaleNum instance Additive Int16 where azero = 0 (I16# a) + (I16# b) = I16# (narrow16Int# (a +# b)) scale = scaleNum instance Additive Int32 where azero = 0 (I32# a) + (I32# b) = I32# (narrow32Int# (a +# b)) scale = scaleNum instance Additive Int64 where azero = 0 #if WORD_SIZE_IN_BITS == 64 (I64# a) + (I64# b) = I64# (a +# b) #else (I64# a) + (I64# b) = I64# (a `plusInt64#` b) #endif scale = scaleNum instance Additive Word where azero = 0 (W# a) + (W# b) = W# (a `plusWord#` b) scale = scaleNum instance Additive Natural where azero = 0 (+) = (Prelude.+) scale = scaleNum instance Additive Word8 where azero = 0 (W8# a) + (W8# b) = W8# (narrow8Word# (a `plusWord#` b)) scale = scaleNum instance Additive Word16 where azero = 0 (W16# a) + (W16# b) = W16# (narrow16Word# (a `plusWord#` b)) scale = scaleNum instance Additive Word32 where azero = 0 (W32# a) + (W32# b) = W32# (narrow32Word# (a `plusWord#` b)) scale = scaleNum instance Additive Word64 where azero = 0 #if WORD_SIZE_IN_BITS == 64 (W64# a) + (W64# b) = W64# (a `plusWord#` b) #else (W64# a) + (W64# b) = W64# (int64ToWord64# (word64ToInt64# a `plusInt64#` word64ToInt64# b)) #endif scale = scaleNum instance Additive Prelude.Float where azero = 0.0 (F# a) + (F# b) = F# (a `plusFloat#` b) scale = scaleNum instance Additive Prelude.Double where azero = 0.0 (D# a) + (D# b) = D# (a +## b) scale = scaleNum instance Additive CSize where azero = 0 (+) = (Prelude.+) scale = scaleNum scaleNum :: (Prelude.Num a, IsNatural n) => n -> a -> a scaleNum n a = (Prelude.fromIntegral $ toNatural n) Prelude.* a