{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeSynonymInstances #-}
module HMath.API.Algebra (
Ring (..),
Field (..),
Scalar (..),
FloatingPoint (..),
Numeric (..),
MatrixLike (..),
TensorLike (..),
VectorSpace (..),
Differentiable (..),
horner,
innerProduct,
Exact (..),
) where
import Data.Complex (Complex ((:+)), conjugate, imagPart, realPart)
import qualified Data.Ratio as R
import qualified HMath.Autodiff as AD
import HMath.Error
import qualified HMath.Matrix as M
import qualified HMath.Tensor as T
import qualified HMath.Vector as V
class (Eq a) => Ring a where
zero :: a
one :: a
plus :: a -> a -> a
times :: a -> a -> a
negative :: a -> a
integer :: Integer -> a
class (Ring a) => Field a where
invert :: a -> Either MathError a
class (Ring a) => Scalar a where
conjugateScalar :: a -> a
class (Scalar a) => FloatingPoint a where
machineEpsilon :: proxy a -> Double
finiteScalar :: a -> Bool
class (Ring a) => Numeric a where
rational :: Rational -> Either MathError a
instance Ring Integer where
zero :: Integer
zero = Integer
0
one :: Integer
one = Integer
1
plus :: Integer -> Integer -> Integer
plus = Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(+)
times :: Integer -> Integer -> Integer
times = Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(*)
negative :: Integer -> Integer
negative = Integer -> Integer
forall a. Num a => a -> a
negate
integer :: Integer -> Integer
integer = Integer -> Integer
forall a. a -> a
id
instance Scalar Integer where conjugateScalar :: Integer -> Integer
conjugateScalar = Integer -> Integer
forall a. a -> a
id
instance Numeric Integer where
rational :: Rational -> Either MathError Integer
rational Rational
q
| Rational -> Integer
forall a. Ratio a -> a
R.denominator Rational
q Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
1 = Integer -> Either MathError Integer
forall a b. b -> Either a b
Right (Rational -> Integer
forall a. Ratio a -> a
R.numerator Rational
q)
| Bool
otherwise = MathError -> Either MathError Integer
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"Integer cannot represent a non-integral rational")
instance Ring Rational where
zero :: Rational
zero = Rational
0
one :: Rational
one = Rational
1
plus :: Rational -> Rational -> Rational
plus = Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
(+)
times :: Rational -> Rational -> Rational
times = Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
(*)
negative :: Rational -> Rational
negative = Rational -> Rational
forall a. Num a => a -> a
negate
integer :: Integer -> Rational
integer = Integer -> Rational
forall a. Num a => Integer -> a
fromInteger
instance Field Rational where
invert :: Rational -> Either MathError Rational
invert Rational
x
| Rational
x Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
== Rational
0 = MathError -> Either MathError Rational
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"field inverse of zero")
| Bool
otherwise = Rational -> Either MathError Rational
forall a b. b -> Either a b
Right (Rational -> Rational
forall a. Fractional a => a -> a
recip Rational
x)
instance Scalar Rational where conjugateScalar :: Rational -> Rational
conjugateScalar = Rational -> Rational
forall a. a -> a
id
instance Numeric Rational where rational :: Rational -> Either MathError Rational
rational = Rational -> Either MathError Rational
forall a b. b -> Either a b
Right
instance Ring Double where
zero :: Double
zero = Double
0
one :: Double
one = Double
1
plus :: Double -> Double -> Double
plus = Double -> Double -> Double
forall a. Num a => a -> a -> a
(+)
times :: Double -> Double -> Double
times = Double -> Double -> Double
forall a. Num a => a -> a -> a
(*)
negative :: Double -> Double
negative = Double -> Double
forall a. Num a => a -> a
negate
integer :: Integer -> Double
integer = Integer -> Double
forall a. Num a => Integer -> a
fromInteger
instance Field Double where
invert :: Double -> Either MathError Double
invert Double
x
| Double
x Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 Bool -> Bool -> Bool
|| Bool -> Bool
not (Double -> Bool
forall a. FloatingPoint a => a -> Bool
finiteScalar Double
x) = MathError -> Either MathError Double
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"finite nonzero field inverse required")
| Bool
otherwise = let y :: Double
y = Double -> Double
forall a. Fractional a => a -> a
recip Double
x in if Double -> Bool
forall a. FloatingPoint a => a -> Bool
finiteScalar Double
y then Double -> Either MathError Double
forall a b. b -> Either a b
Right Double
y else MathError -> Either MathError Double
forall a b. a -> Either a b
Left MathError
NonFiniteResult
instance Scalar Double where conjugateScalar :: Double -> Double
conjugateScalar = Double -> Double
forall a. a -> a
id
instance FloatingPoint Double where
machineEpsilon :: forall (proxy :: * -> *). proxy Double -> Double
machineEpsilon proxy Double
_ = Double
2 Double -> Double -> Double
forall a. Floating a => a -> a -> a
** (-Double
52)
finiteScalar :: Double -> Bool
finiteScalar Double
x = Bool -> Bool
not (Double -> Bool
forall a. RealFloat a => a -> Bool
isNaN Double
x Bool -> Bool -> Bool
|| Double -> Bool
forall a. RealFloat a => a -> Bool
isInfinite Double
x)
instance Numeric Double where
rational :: Rational -> Either MathError Double
rational Rational
q = let x :: Double
x = Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
q in if Double -> Bool
forall a. FloatingPoint a => a -> Bool
finiteScalar Double
x then Double -> Either MathError Double
forall a b. b -> Either a b
Right Double
x else MathError -> Either MathError Double
forall a b. a -> Either a b
Left MathError
NonFiniteResult
instance Ring Float where
zero :: Float
zero = Float
0
one :: Float
one = Float
1
plus :: Float -> Float -> Float
plus = Float -> Float -> Float
forall a. Num a => a -> a -> a
(+)
times :: Float -> Float -> Float
times = Float -> Float -> Float
forall a. Num a => a -> a -> a
(*)
negative :: Float -> Float
negative = Float -> Float
forall a. Num a => a -> a
negate
integer :: Integer -> Float
integer = Integer -> Float
forall a. Num a => Integer -> a
fromInteger
instance Field Float where
invert :: Float -> Either MathError Float
invert Float
x
| Float
x Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
== Float
0 Bool -> Bool -> Bool
|| Bool -> Bool
not (Float -> Bool
forall a. FloatingPoint a => a -> Bool
finiteScalar Float
x) = MathError -> Either MathError Float
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"finite nonzero field inverse required")
| Bool
otherwise = let y :: Float
y = Float -> Float
forall a. Fractional a => a -> a
recip Float
x in if Float -> Bool
forall a. FloatingPoint a => a -> Bool
finiteScalar Float
y then Float -> Either MathError Float
forall a b. b -> Either a b
Right Float
y else MathError -> Either MathError Float
forall a b. a -> Either a b
Left MathError
NonFiniteResult
instance Scalar Float where conjugateScalar :: Float -> Float
conjugateScalar = Float -> Float
forall a. a -> a
id
instance FloatingPoint Float where
machineEpsilon :: forall (proxy :: * -> *). proxy Float -> Double
machineEpsilon proxy Float
_ = Double
2 Double -> Double -> Double
forall a. Floating a => a -> a -> a
** (-Double
23)
finiteScalar :: Float -> Bool
finiteScalar Float
x = Bool -> Bool
not (Float -> Bool
forall a. RealFloat a => a -> Bool
isNaN Float
x Bool -> Bool -> Bool
|| Float -> Bool
forall a. RealFloat a => a -> Bool
isInfinite Float
x)
instance Numeric Float where
rational :: Rational -> Either MathError Float
rational Rational
q = let x :: Float
x = Rational -> Float
forall a. Fractional a => Rational -> a
fromRational Rational
q in if Float -> Bool
forall a. FloatingPoint a => a -> Bool
finiteScalar Float
x then Float -> Either MathError Float
forall a b. b -> Either a b
Right Float
x else MathError -> Either MathError Float
forall a b. a -> Either a b
Left MathError
NonFiniteResult
instance Ring (Complex Double) where
zero :: Complex Double
zero = Complex Double
0
one :: Complex Double
one = Complex Double
1
plus :: Complex Double -> Complex Double -> Complex Double
plus = Complex Double -> Complex Double -> Complex Double
forall a. Num a => a -> a -> a
(+)
times :: Complex Double -> Complex Double -> Complex Double
times = Complex Double -> Complex Double -> Complex Double
forall a. Num a => a -> a -> a
(*)
negative :: Complex Double -> Complex Double
negative = Complex Double -> Complex Double
forall a. Num a => a -> a
negate
integer :: Integer -> Complex Double
integer = Integer -> Complex Double
forall a. Num a => Integer -> a
fromInteger
instance Scalar (Complex Double) where conjugateScalar :: Complex Double -> Complex Double
conjugateScalar = Complex Double -> Complex Double
forall a. Num a => Complex a -> Complex a
conjugate
instance FloatingPoint (Complex Double) where
machineEpsilon :: forall (proxy :: * -> *). proxy (Complex Double) -> Double
machineEpsilon proxy (Complex Double)
_ = Double
2 Double -> Double -> Double
forall a. Floating a => a -> a -> a
** (-Double
52)
finiteScalar :: Complex Double -> Bool
finiteScalar Complex Double
z = Double -> Bool
forall a. FloatingPoint a => a -> Bool
finiteScalar (Complex Double -> Double
forall a. Complex a -> a
realPart Complex Double
z) Bool -> Bool -> Bool
&& Double -> Bool
forall a. FloatingPoint a => a -> Bool
finiteScalar (Complex Double -> Double
forall a. Complex a -> a
imagPart Complex Double
z)
instance Field (Complex Double) where
invert :: Complex Double -> Either MathError (Complex Double)
invert Complex Double
z
| Complex Double
z Complex Double -> Complex Double -> Bool
forall a. Eq a => a -> a -> Bool
== Complex Double
0 Bool -> Bool -> Bool
|| Bool -> Bool
not (Complex Double -> Bool
forall a. FloatingPoint a => a -> Bool
finiteScalar Complex Double
z) = MathError -> Either MathError (Complex Double)
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"finite nonzero complex inverse required")
| Bool
otherwise =
let a :: Double
a = Complex Double -> Double
forall a. Complex a -> a
realPart Complex Double
z
b :: Double
b = Complex Double -> Double
forall a. Complex a -> a
imagPart Complex Double
z
s :: Double
s = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max (Double -> Double
forall a. Num a => a -> a
abs Double
a) (Double -> Double
forall a. Num a => a -> a
abs Double
b)
x :: Double
x = Double
a Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
s
y :: Double
y = Double
b Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
s
d :: Double
d = Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y
w :: Complex Double
w = ((Double
x Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
d) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
s) Double -> Double -> Complex Double
forall a. a -> a -> Complex a
:+ ((-Double
y Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
d) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
s)
in if Complex Double -> Bool
forall a. FloatingPoint a => a -> Bool
finiteScalar Complex Double
w then Complex Double -> Either MathError (Complex Double)
forall a b. b -> Either a b
Right Complex Double
w else MathError -> Either MathError (Complex Double)
forall a b. a -> Either a b
Left MathError
NonFiniteResult
instance Numeric (Complex Double) where
rational :: Rational -> Either MathError (Complex Double)
rational Rational
q = (Double -> Double -> Complex Double
forall a. a -> a -> Complex a
:+ Double
0) (Double -> Complex Double)
-> Either MathError Double -> Either MathError (Complex Double)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Rational -> Either MathError Double
forall a. Numeric a => Rational -> Either MathError a
rational Rational
q :: Either MathError Double)
newtype Exact = Exact
{ Exact -> Rational
getExact :: Rational
}
deriving (Exact -> Exact -> Bool
(Exact -> Exact -> Bool) -> (Exact -> Exact -> Bool) -> Eq Exact
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Exact -> Exact -> Bool
== :: Exact -> Exact -> Bool
$c/= :: Exact -> Exact -> Bool
/= :: Exact -> Exact -> Bool
Eq, Eq Exact
Eq Exact =>
(Exact -> Exact -> Ordering)
-> (Exact -> Exact -> Bool)
-> (Exact -> Exact -> Bool)
-> (Exact -> Exact -> Bool)
-> (Exact -> Exact -> Bool)
-> (Exact -> Exact -> Exact)
-> (Exact -> Exact -> Exact)
-> Ord Exact
Exact -> Exact -> Bool
Exact -> Exact -> Ordering
Exact -> Exact -> Exact
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
$ccompare :: Exact -> Exact -> Ordering
compare :: Exact -> Exact -> Ordering
$c< :: Exact -> Exact -> Bool
< :: Exact -> Exact -> Bool
$c<= :: Exact -> Exact -> Bool
<= :: Exact -> Exact -> Bool
$c> :: Exact -> Exact -> Bool
> :: Exact -> Exact -> Bool
$c>= :: Exact -> Exact -> Bool
>= :: Exact -> Exact -> Bool
$cmax :: Exact -> Exact -> Exact
max :: Exact -> Exact -> Exact
$cmin :: Exact -> Exact -> Exact
min :: Exact -> Exact -> Exact
Ord, Int -> Exact -> ShowS
[Exact] -> ShowS
Exact -> String
(Int -> Exact -> ShowS)
-> (Exact -> String) -> ([Exact] -> ShowS) -> Show Exact
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Exact -> ShowS
showsPrec :: Int -> Exact -> ShowS
$cshow :: Exact -> String
show :: Exact -> String
$cshowList :: [Exact] -> ShowS
showList :: [Exact] -> ShowS
Show)
instance Ring Exact where
zero :: Exact
zero = Rational -> Exact
Exact Rational
0
one :: Exact
one = Rational -> Exact
Exact Rational
1
plus :: Exact -> Exact -> Exact
plus (Exact Rational
a) (Exact Rational
b) = Rational -> Exact
Exact (Rational
a Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
b)
times :: Exact -> Exact -> Exact
times (Exact Rational
a) (Exact Rational
b) = Rational -> Exact
Exact (Rational
a Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
b)
negative :: Exact -> Exact
negative (Exact Rational
a) = Rational -> Exact
Exact (-Rational
a)
integer :: Integer -> Exact
integer = Rational -> Exact
Exact (Rational -> Exact) -> (Integer -> Rational) -> Integer -> Exact
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Rational
forall a. Num a => Integer -> a
fromInteger
instance Field Exact where invert :: Exact -> Either MathError Exact
invert (Exact Rational
a) = Rational -> Exact
Exact (Rational -> Exact)
-> Either MathError Rational -> Either MathError Exact
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Rational -> Either MathError Rational
forall a. Field a => a -> Either MathError a
invert Rational
a
instance Scalar Exact where conjugateScalar :: Exact -> Exact
conjugateScalar = Exact -> Exact
forall a. a -> a
id
instance Numeric Exact where rational :: Rational -> Either MathError Exact
rational = Exact -> Either MathError Exact
forall a b. b -> Either a b
Right (Exact -> Either MathError Exact)
-> (Rational -> Exact) -> Rational -> Either MathError Exact
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Exact
Exact
horner :: (Ring a) => [a] -> a -> a
horner :: forall a. Ring a => [a] -> a -> a
horner [a]
coefficients a
x = (a -> a -> a) -> a -> [a] -> a
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\a
value a
coefficient -> a -> a -> a
forall a. Ring a => a -> a -> a
plus (a -> a -> a
forall a. Ring a => a -> a -> a
times a
value a
x) a
coefficient) a
forall a. Ring a => a
zero [a]
coefficients
innerProduct :: (Scalar a) => [a] -> [a] -> Either MathError a
innerProduct :: forall a. Scalar a => [a] -> [a] -> Either MathError a
innerProduct [a]
a [a]
b
| [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
a Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
b = MathError -> Either MathError a
forall a b. a -> Either a b
Left (Int -> Int -> MathError
VectorLengthMismatch ([a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
a) ([a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
b))
| Bool
otherwise = a -> Either MathError a
forall a b. b -> Either a b
Right ((a -> a -> a) -> a -> [a] -> a
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl a -> a -> a
forall a. Ring a => a -> a -> a
plus a
forall a. Ring a => a
zero ((a -> a -> a) -> [a] -> [a] -> [a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\a
x a
y -> a -> a -> a
forall a. Ring a => a -> a -> a
times (a -> a
forall a. Scalar a => a -> a
conjugateScalar a
x) a
y) [a]
a [a]
b))
class MatrixLike m where
matrixDimensions :: m a -> (Int, Int)
matrixElements :: m a -> [a]
matrixConstruct :: Int -> Int -> [a] -> Either MathError (m a)
instance MatrixLike M.Matrix where
matrixDimensions :: forall a. Matrix a -> (Int, Int)
matrixDimensions = Matrix a -> (Int, Int)
forall a. Matrix a -> (Int, Int)
M.shape
matrixElements :: forall a. Matrix a -> [a]
matrixElements = Matrix a -> [a]
forall a. Matrix a -> [a]
M.toList
matrixConstruct :: forall a. Int -> Int -> [a] -> Either MathError (Matrix a)
matrixConstruct = Int -> Int -> [a] -> Either MathError (Matrix a)
forall a. Int -> Int -> [a] -> Either MathError (Matrix a)
M.fromListChecked
class TensorLike t where
tensorDimensions :: t a -> [Int]
tensorElements :: t a -> [a]
tensorConstruct :: [Int] -> [a] -> Either MathError (t a)
instance TensorLike T.Tensor where
tensorDimensions :: forall a. Tensor a -> [Int]
tensorDimensions = Tensor a -> [Int]
forall a. Tensor a -> [Int]
T.tensorShape
tensorElements :: forall a. Tensor a -> [a]
tensorElements = Tensor a -> [a]
forall a. Tensor a -> [a]
T.tensorValues
tensorConstruct :: forall a. [Int] -> [a] -> Either MathError (Tensor a)
tensorConstruct = [Int] -> [a] -> Either MathError (Tensor a)
forall a. [Int] -> [a] -> Either MathError (Tensor a)
T.tensor
class VectorSpace v where
vectorPlus :: (Num a) => v a -> v a -> Either MathError (v a)
vectorScale :: (Num a) => a -> v a -> v a
instance VectorSpace V.Vector where vectorPlus :: forall a.
Num a =>
Vector a -> Vector a -> Either MathError (Vector a)
vectorPlus = Vector a -> Vector a -> Either MathError (Vector a)
forall a.
Num a =>
Vector a -> Vector a -> Either MathError (Vector a)
V.vectorAdd; vectorScale :: forall a. Num a => a -> Vector a -> Vector a
vectorScale = a -> Vector a -> Vector a
forall a. Num a => a -> Vector a -> Vector a
V.vectorScale
instance VectorSpace M.Matrix where vectorPlus :: forall a.
Num a =>
Matrix a -> Matrix a -> Either MathError (Matrix a)
vectorPlus = Matrix a -> Matrix a -> Either MathError (Matrix a)
forall a.
Num a =>
Matrix a -> Matrix a -> Either MathError (Matrix a)
M.addMatrixChecked; vectorScale :: forall a. Num a => a -> Matrix a -> Matrix a
vectorScale = a -> Matrix a -> Matrix a
forall a. Num a => a -> Matrix a -> Matrix a
M.scaleMatrix
class Differentiable a where
type Differential a
differential :: a -> Differential a
instance Differentiable (AD.Dual a) where
type Differential (AD.Dual a) = a
differential :: Dual a -> Differential (Dual a)
differential = Dual a -> a
Dual a -> Differential (Dual a)
forall a. Dual a -> a
AD.tangent