{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE DefaultSignatures #-} module Basement.Numerical.Multiplicative ( Multiplicative(..) , IDivisible(..) , Divisible(..) , recip ) where import Basement.Compat.Base import Basement.Compat.C.Types import Basement.Compat.Natural import Basement.Compat.NumLiteral import Basement.Numerical.Number import Basement.Numerical.Additive import Basement.Types.Word128 (Word128) import Basement.Types.Word256 (Word256) import qualified Basement.Types.Word128 as Word128 import qualified Basement.Types.Word256 as Word256 import qualified Prelude -- | Represent class of things that can be multiplied together -- -- > x * midentity = x -- > midentity * x = x class Multiplicative a where {-# MINIMAL midentity, (*) #-} -- | Identity element over multiplication midentity :: a -- | Multiplication of 2 elements that result in another element (*) :: a -> a -> a -- | Raise to power, repeated multiplication -- e.g. -- > a ^ 2 = a * a -- > a ^ 10 = (a ^ 5) * (a ^ 5) .. --(^) :: (IsNatural n) => a -> n -> a (^) :: (IsNatural n, Enum n, IDivisible n) => a -> n -> a (^) = power -- | Represent types that supports an euclidian division -- -- > (x ‘div‘ y) * y + (x ‘mod‘ y) == x class (Additive a, Multiplicative a) => IDivisible a where {-# MINIMAL (div, mod) | divMod #-} div :: a -> a -> a div a b = fst $ divMod a b mod :: a -> a -> a mod a b = snd $ divMod a b divMod :: a -> a -> (a, a) divMod a b = (div a b, mod a b) -- | Support for division between same types -- -- This is likely to change to represent specific mathematic divisions class Multiplicative a => Divisible a where {-# MINIMAL (/) #-} (/) :: a -> a -> a infixl 7 *, / infixr 8 ^ instance Multiplicative Integer where midentity = 1 (*) = (Prelude.*) instance Multiplicative Int where midentity = 1 (*) = (Prelude.*) instance Multiplicative Int8 where midentity = 1 (*) = (Prelude.*) instance Multiplicative Int16 where midentity = 1 (*) = (Prelude.*) instance Multiplicative Int32 where midentity = 1 (*) = (Prelude.*) instance Multiplicative Int64 where midentity = 1 (*) = (Prelude.*) instance Multiplicative Natural where midentity = 1 (*) = (Prelude.*) instance Multiplicative Word where midentity = 1 (*) = (Prelude.*) instance Multiplicative Word8 where midentity = 1 (*) = (Prelude.*) instance Multiplicative Word16 where midentity = 1 (*) = (Prelude.*) instance Multiplicative Word32 where midentity = 1 (*) = (Prelude.*) instance Multiplicative Word64 where midentity = 1 (*) = (Prelude.*) instance Multiplicative Word128 where midentity = 1 (*) = (Word128.*) instance Multiplicative Word256 where midentity = 1 (*) = (Word256.*) instance Multiplicative Prelude.Float where midentity = 1.0 (*) = (Prelude.*) instance Multiplicative Prelude.Double where midentity = 1.0 (*) = (Prelude.*) instance Multiplicative Prelude.Rational where midentity = 1.0 (*) = (Prelude.*) instance Multiplicative CChar where midentity = 1 (*) = (Prelude.*) instance Multiplicative CSChar where midentity = 1 (*) = (Prelude.*) instance Multiplicative CUChar where midentity = 1 (*) = (Prelude.*) instance Multiplicative CShort where midentity = 1 (*) = (Prelude.*) instance Multiplicative CUShort where midentity = 1 (*) = (Prelude.*) instance Multiplicative CInt where midentity = 1 (*) = (Prelude.*) instance Multiplicative CUInt where midentity = 1 (*) = (Prelude.*) instance Multiplicative CLong where midentity = 1 (*) = (Prelude.*) instance Multiplicative CULong where midentity = 1 (*) = (Prelude.*) instance Multiplicative CPtrdiff where midentity = 1 (*) = (Prelude.*) instance Multiplicative CSize where midentity = 1 (*) = (Prelude.*) instance Multiplicative CWchar where midentity = 1 (*) = (Prelude.*) instance Multiplicative CSigAtomic where midentity = 1 (*) = (Prelude.*) instance Multiplicative CLLong where midentity = 1 (*) = (Prelude.*) instance Multiplicative CULLong where midentity = 1 (*) = (Prelude.*) instance Multiplicative CIntPtr where midentity = 1 (*) = (Prelude.*) instance Multiplicative CUIntPtr where midentity = 1 (*) = (Prelude.*) instance Multiplicative CIntMax where midentity = 1 (*) = (Prelude.*) instance Multiplicative CUIntMax where midentity = 1 (*) = (Prelude.*) instance Multiplicative CClock where midentity = 1 (*) = (Prelude.*) instance Multiplicative CTime where midentity = 1 (*) = (Prelude.*) instance Multiplicative CUSeconds where midentity = 1 (*) = (Prelude.*) instance Multiplicative CSUSeconds where midentity = 1 (*) = (Prelude.*) instance Multiplicative COff where midentity = 1 (*) = (Prelude.*) instance Multiplicative CFloat where midentity = 1.0 (*) = (Prelude.*) instance Multiplicative CDouble where midentity = 1.0 (*) = (Prelude.*) instance IDivisible Integer where div = Prelude.div mod = Prelude.mod instance IDivisible Int where div = Prelude.div mod = Prelude.mod instance IDivisible Int8 where div = Prelude.div mod = Prelude.mod instance IDivisible Int16 where div = Prelude.div mod = Prelude.mod instance IDivisible Int32 where div = Prelude.div mod = Prelude.mod instance IDivisible Int64 where div = Prelude.div mod = Prelude.mod instance IDivisible Natural where div = Prelude.quot mod = Prelude.rem instance IDivisible Word where div = Prelude.quot mod = Prelude.rem instance IDivisible Word8 where div = Prelude.quot mod = Prelude.rem instance IDivisible Word16 where div = Prelude.quot mod = Prelude.rem instance IDivisible Word32 where div = Prelude.quot mod = Prelude.rem instance IDivisible Word64 where div = Prelude.quot mod = Prelude.rem instance IDivisible Word128 where div = Word128.quot mod = Word128.rem instance IDivisible Word256 where div = Word256.quot mod = Word256.rem instance IDivisible CChar where div = Prelude.quot mod = Prelude.rem instance IDivisible CSChar where div = Prelude.quot mod = Prelude.rem instance IDivisible CUChar where div = Prelude.quot mod = Prelude.rem instance IDivisible CShort where div = Prelude.quot mod = Prelude.rem instance IDivisible CUShort where div = Prelude.quot mod = Prelude.rem instance IDivisible CInt where div = Prelude.quot mod = Prelude.rem instance IDivisible CUInt where div = Prelude.quot mod = Prelude.rem instance IDivisible CLong where div = Prelude.quot mod = Prelude.rem instance IDivisible CULong where div = Prelude.quot mod = Prelude.rem instance IDivisible CPtrdiff where div = Prelude.quot mod = Prelude.rem instance IDivisible CSize where div = Prelude.quot mod = Prelude.rem instance IDivisible CWchar where div = Prelude.quot mod = Prelude.rem instance IDivisible CSigAtomic where div = Prelude.quot mod = Prelude.rem instance IDivisible CLLong where div = Prelude.quot mod = Prelude.rem instance IDivisible CULLong where div = Prelude.quot mod = Prelude.rem instance IDivisible CIntPtr where div = Prelude.quot mod = Prelude.rem instance IDivisible CUIntPtr where div = Prelude.quot mod = Prelude.rem instance IDivisible CIntMax where div = Prelude.quot mod = Prelude.rem instance IDivisible CUIntMax where div = Prelude.quot mod = Prelude.rem instance Divisible Prelude.Rational where (/) = (Prelude./) instance Divisible Float where (/) = (Prelude./) instance Divisible Double where (/) = (Prelude./) instance Divisible CFloat where (/) = (Prelude./) instance Divisible CDouble where (/) = (Prelude./) recip :: Divisible a => a -> a recip x = midentity / x power :: (Enum n, IsNatural n, IDivisible n, Multiplicative a) => a -> n -> a power a n | n == 0 = midentity | otherwise = squaring midentity a n where squaring y x i | i == 0 = y | i == 1 = x * y | even i = squaring y (x*x) (i`div`2) | otherwise = squaring (x*y) (x*x) (pred i`div` 2) even :: (IDivisible n, IsIntegral n) => n -> Bool even n = (n `mod` 2) == 0