332 lines
8.6 KiB
Haskell
332 lines
8.6 KiB
Haskell
|
|
{-# LANGUAGE BangPatterns #-}
|
|||
|
|
{-# LANGUAGE DeriveDataTypeable #-}
|
|||
|
|
{-# LANGUAGE TypeFamilies #-}
|
|||
|
|
{-# LANGUAGE RebindableSyntax #-}
|
|||
|
|
{-# LANGUAGE NoImplicitPrelude #-}
|
|||
|
|
{-# 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
|