module Foundation.Number
( Number(..)
, fromInteger
, Signed(..)
, Additive(..)
, Multiplicative(..)
, Subtractive(..)
, Divisible(..)
, Sign(..)
) where
import Foundation.Internal.Base
import qualified Prelude
infixl 7 *
infixl 6 +,
infixr 8 ^
data Sign = Negative | Zero | Positive
deriving (Eq)
orderingToSign :: Ordering -> Sign
orderingToSign EQ = Zero
orderingToSign GT = Negative
orderingToSign LT = Positive
class (Eq a, Ord a, Prelude.Num a, Enum a, Additive a, Subtractive a, Difference a ~ a, Multiplicative a, Divisible a) => Number a where
toInteger :: a -> Integer
fromInteger :: Number a => Integer -> a
fromInteger = Prelude.fromInteger
class Number a => Signed a where
abs :: a -> a
signum :: a -> Sign
class Additive a where
azero :: a
(+) :: a -> a -> a
scale :: Number n => n -> a -> a
default scale :: Number n => n -> a -> a
scale 0 _ = azero
scale 1 a = a
scale 2 a = a + a
scale n a
| n < 0 = error "cannot scale by negative number"
| otherwise = a + scale (pred n) a
class Multiplicative a where
midentity :: a
(*) :: a -> a -> a
(^) :: Number n => a -> n -> a
(^) = power
class Subtractive a where
type Difference a
() :: a -> a -> Difference a
class Multiplicative a => Divisible a where
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)
instance Number Integer where
toInteger i = i
instance Number Int where
toInteger i = Prelude.fromIntegral i
instance Number Int8 where
toInteger i = Prelude.fromIntegral i
instance Number Int16 where
toInteger i = Prelude.fromIntegral i
instance Number Int32 where
toInteger i = Prelude.fromIntegral i
instance Number Int64 where
toInteger i = Prelude.fromIntegral i
instance Signed Integer where
abs = Prelude.abs
signum = orderingToSign . compare 0
instance Signed Int where
abs = Prelude.abs
signum = orderingToSign . compare 0
instance Signed Int8 where
abs = Prelude.abs
signum = orderingToSign . compare 0
instance Signed Int16 where
abs = Prelude.abs
signum = orderingToSign . compare 0
instance Signed Int32 where
abs = Prelude.abs
signum = orderingToSign . compare 0
instance Signed Int64 where
abs = Prelude.abs
signum = orderingToSign . compare 0
instance Number Word where
toInteger i = Prelude.fromIntegral i
instance Number Word8 where
toInteger i = Prelude.fromIntegral i
instance Number Word16 where
toInteger i = Prelude.fromIntegral i
instance Number Word32 where
toInteger i = Prelude.fromIntegral i
instance Number Word64 where
toInteger i = Prelude.fromIntegral i
instance Additive Integer where
azero = 0
(+) = (Prelude.+)
scale = scaleNum
instance Additive Int where
azero = 0
(+) = (Prelude.+)
scale = scaleNum
instance Additive Int8 where
azero = 0
(+) = (Prelude.+)
scale = scaleNum
instance Additive Int16 where
azero = 0
(+) = (Prelude.+)
scale = scaleNum
instance Additive Int32 where
azero = 0
(+) = (Prelude.+)
scale = scaleNum
instance Additive Int64 where
azero = 0
(+) = (Prelude.+)
scale = scaleNum
instance Additive Word where
azero = 0
(+) = (Prelude.+)
scale = scaleNum
instance Additive Word8 where
azero = 0
(+) = (Prelude.+)
scale = scaleNum
instance Additive Word16 where
azero = 0
(+) = (Prelude.+)
scale = scaleNum
instance Additive Word32 where
azero = 0
(+) = (Prelude.+)
scale = scaleNum
instance Additive Word64 where
azero = 0
(+) = (Prelude.+)
scale = scaleNum
scaleNum :: (Prelude.Num a, Number n) => n -> a -> a
scaleNum n a = (Prelude.fromIntegral $ toInteger n) Prelude.* a
instance Subtractive Integer where
type Difference Integer = Integer
() = (Prelude.-)
instance Subtractive Int where
type Difference Int = Int
() = (Prelude.-)
instance Subtractive Int8 where
type Difference Int8 = Int8
() = (Prelude.-)
instance Subtractive Int16 where
type Difference Int16 = Int16
() = (Prelude.-)
instance Subtractive Int32 where
type Difference Int32 = Int32
() = (Prelude.-)
instance Subtractive Int64 where
type Difference Int64 = Int64
() = (Prelude.-)
instance Subtractive Word where
type Difference Word = Word
() = (Prelude.-)
instance Subtractive Word8 where
type Difference Word8 = Word8
() = (Prelude.-)
instance Subtractive Word16 where
type Difference Word16 = Word16
() = (Prelude.-)
instance Subtractive Word32 where
type Difference Word32 = Word32
() = (Prelude.-)
instance Subtractive Word64 where
type Difference Word64 = Word64
() = (Prelude.-)
instance Multiplicative Integer where
midentity = 1
(*) = (Prelude.*)
(^) = power
instance Multiplicative Int where
midentity = 1
(*) = (Prelude.*)
(^) = power
instance Multiplicative Int8 where
midentity = 1
(*) = (Prelude.*)
(^) = power
instance Multiplicative Int16 where
midentity = 1
(*) = (Prelude.*)
(^) = power
instance Multiplicative Int32 where
midentity = 1
(*) = (Prelude.*)
(^) = power
instance Multiplicative Int64 where
midentity = 1
(*) = (Prelude.*)
(^) = power
instance Multiplicative Word where
midentity = 1
(*) = (Prelude.*)
(^) = power
instance Multiplicative Word8 where
midentity = 1
(*) = (Prelude.*)
(^) = power
instance Multiplicative Word16 where
midentity = 1
(*) = (Prelude.*)
(^) = power
instance Multiplicative Word32 where
midentity = 1
(*) = (Prelude.*)
(^) = power
instance Multiplicative Word64 where
midentity = 1
(*) = (Prelude.*)
(^) = power
power :: (Number n, Multiplicative a) => a -> n -> a
power a n
| n < 0 = error "(^): cannot use negative exponent"
| 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 :: Number n => n -> Bool
even n = (n `mod` 2) == 0
instance Divisible Integer where
div = Prelude.div
mod = Prelude.mod
instance Divisible Int where
div = Prelude.div
mod = Prelude.mod
instance Divisible Int8 where
div = Prelude.div
mod = Prelude.mod
instance Divisible Int16 where
div = Prelude.div
mod = Prelude.mod
instance Divisible Int32 where
div = Prelude.div
mod = Prelude.mod
instance Divisible Int64 where
div = Prelude.div
mod = Prelude.mod
instance Divisible Word where
div = Prelude.quot
mod = Prelude.rem
instance Divisible Word8 where
div = Prelude.quot
mod = Prelude.rem
instance Divisible Word16 where
div = Prelude.quot
mod = Prelude.rem
instance Divisible Word32 where
div = Prelude.quot
mod = Prelude.rem
instance Divisible Word64 where
div = Prelude.quot
mod = Prelude.rem
--numUpSize