{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module Number.Physical where
import qualified Number.Physical.Unit as Unit
import Algebra.OccasionallyScalar as OccScalar
import qualified Algebra.VectorSpace as VectorSpace
import qualified Algebra.Module as Module
import qualified Algebra.Vector as Vector
import qualified Algebra.Transcendental as Trans
import qualified Algebra.Algebraic as Algebraic
import qualified Algebra.Field as Field
import qualified Algebra.Absolute as Absolute
import qualified Algebra.Ring as Ring
import qualified Algebra.Additive as Additive
import qualified Algebra.ZeroTestable as ZeroTestable
import qualified Algebra.ToInteger as ToInteger
import qualified Number.Ratio as Ratio
import Control.Monad (guard, liftM, liftM2, ap)
import Control.Applicative (Applicative(pure, (<*>)))
import Data.Maybe.HT(toMaybe)
import Data.Maybe(fromMaybe)
import NumericPrelude.Numeric
import NumericPrelude.Base
data T i a = Cons (Unit.T i) a
quantity :: (Ord i, Enum i, Ring.C a) => [Int] -> a -> T i a
quantity :: [Int] -> a -> T i a
quantity [Int]
v = T i -> a -> T i a
forall i a. T i -> a -> T i a
Cons ([Int] -> T i
forall i. (Enum i, Ord i) => [Int] -> T i
Unit.fromVector [Int]
v)
fromScalarSingle :: a -> T i a
fromScalarSingle :: a -> T i a
fromScalarSingle = T i -> a -> T i a
forall i a. T i -> a -> T i a
Cons T i
forall i. T i
Unit.scalar
isScalar :: T i a -> Bool
isScalar :: T i a -> Bool
isScalar (Cons T i
u a
_) = T i -> Bool
forall i. T i -> Bool
Unit.isScalar T i
u
lift :: (a -> b) -> T i a -> T i b
lift :: (a -> b) -> T i a -> T i b
lift a -> b
f (Cons T i
xu a
x) = T i -> b -> T i b
forall i a. T i -> a -> T i a
Cons T i
xu (a -> b
f a
x)
lift2 :: (Eq i) => String -> (a -> b -> c) -> T i a -> T i b -> T i c
lift2 :: String -> (a -> b -> c) -> T i a -> T i b -> T i c
lift2 String
opName a -> b -> c
op T i a
x T i b
y =
T i c -> Maybe (T i c) -> T i c
forall a. a -> Maybe a -> a
fromMaybe (String -> T i c
forall a. String -> a
errorUnitMismatch String
opName) ((a -> b -> c) -> T i a -> T i b -> Maybe (T i c)
forall i a b c.
Eq i =>
(a -> b -> c) -> T i a -> T i b -> Maybe (T i c)
lift2Maybe a -> b -> c
op T i a
x T i b
y)
lift2Maybe :: (Eq i) => (a -> b -> c) -> T i a -> T i b -> Maybe (T i c)
lift2Maybe :: (a -> b -> c) -> T i a -> T i b -> Maybe (T i c)
lift2Maybe a -> b -> c
op (Cons T i
xu a
x) (Cons T i
yu b
y) =
Bool -> T i c -> Maybe (T i c)
forall a. Bool -> a -> Maybe a
toMaybe (T i
xuT i -> T i -> Bool
forall a. Eq a => a -> a -> Bool
==T i
yu) (T i -> c -> T i c
forall i a. T i -> a -> T i a
Cons T i
xu (a -> b -> c
op a
x b
y))
lift2Gen :: (Eq i) => String -> (a -> b -> c) -> T i a -> T i b -> c
lift2Gen :: String -> (a -> b -> c) -> T i a -> T i b -> c
lift2Gen String
opName a -> b -> c
op (Cons T i
xu a
x) (Cons T i
yu b
y) =
if (T i
xuT i -> T i -> Bool
forall a. Eq a => a -> a -> Bool
==T i
yu)
then a -> b -> c
op a
x b
y
else String -> c
forall a. String -> a
errorUnitMismatch String
opName
errorUnitMismatch :: String -> a
errorUnitMismatch :: String -> a
errorUnitMismatch String
opName =
String -> a
forall a. HasCallStack => String -> a
error (String
"Physics.Quantity.Value."String -> String -> String
forall a. [a] -> [a] -> [a]
++String
opNameString -> String -> String
forall a. [a] -> [a] -> [a]
++String
": units mismatch")
addMaybe :: (Eq i, Additive.C a) =>
T i a -> T i a -> Maybe (T i a)
addMaybe :: T i a -> T i a -> Maybe (T i a)
addMaybe = (a -> a -> a) -> T i a -> T i a -> Maybe (T i a)
forall i a b c.
Eq i =>
(a -> b -> c) -> T i a -> T i b -> Maybe (T i c)
lift2Maybe a -> a -> a
forall a. C a => a -> a -> a
(+)
subMaybe :: (Eq i, Additive.C a) =>
T i a -> T i a -> Maybe (T i a)
subMaybe :: T i a -> T i a -> Maybe (T i a)
subMaybe = (a -> a -> a) -> T i a -> T i a -> Maybe (T i a)
forall i a b c.
Eq i =>
(a -> b -> c) -> T i a -> T i b -> Maybe (T i c)
lift2Maybe (-)
scale :: (Ord i, Ring.C a) => a -> T i a -> T i a
scale :: a -> T i a -> T i a
scale a
x = (a -> a) -> T i a -> T i a
forall a b i. (a -> b) -> T i a -> T i b
lift (a
xa -> a -> a
forall a. C a => a -> a -> a
*)
ratPow :: Trans.C a => Ratio.T Int -> T i a -> T i a
ratPow :: T Int -> T i a -> T i a
ratPow T Int
expo (Cons T i
xu a
x) =
T i -> a -> T i a
forall i a. T i -> a -> T i a
Cons (T Int -> T i -> T i
forall i. T Int -> T i -> T i
Unit.ratScale T Int
expo T i
xu) (a
x a -> a -> a
forall a. C a => a -> a -> a
** T Int -> a
forall b a. (C b, C a) => T a -> b
fromRatio T Int
expo)
ratPowMaybe :: (Trans.C a) =>
Ratio.T Int -> T i a -> Maybe (T i a)
ratPowMaybe :: T Int -> T i a -> Maybe (T i a)
ratPowMaybe T Int
expo (Cons T i
xu a
x) =
(T i -> T i a) -> Maybe (T i) -> Maybe (T i a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((T i -> a -> T i a) -> a -> T i -> T i a
forall a b c. (a -> b -> c) -> b -> a -> c
flip T i -> a -> T i a
forall i a. T i -> a -> T i a
Cons (a
x a -> a -> a
forall a. C a => a -> a -> a
** T Int -> a
forall b a. (C b, C a) => T a -> b
fromRatio T Int
expo)) (T Int -> T i -> Maybe (T i)
forall i. T Int -> T i -> Maybe (T i)
Unit.ratScaleMaybe T Int
expo T i
xu)
fromRatio :: (Field.C b, ToInteger.C a) => Ratio.T a -> b
fromRatio :: T a -> b
fromRatio T a
expo = a -> b
forall a b. (C a, C b) => a -> b
fromIntegral (T a -> a
forall a. T a -> a
numerator T a
expo) b -> b -> b
forall a. C a => a -> a -> a
/
a -> b
forall a b. (C a, C b) => a -> b
fromIntegral (T a -> a
forall a. T a -> a
denominator T a
expo)
instance (ZeroTestable.C v) => ZeroTestable.C (T a v) where
isZero :: T a v -> Bool
isZero (Cons T a
_ v
x) = v -> Bool
forall a. C a => a -> Bool
isZero v
x
instance (Eq i, Eq a) => Eq (T i a) where
== :: T i a -> T i a -> Bool
(==) = String -> (a -> a -> Bool) -> T i a -> T i a -> Bool
forall i a b c.
Eq i =>
String -> (a -> b -> c) -> T i a -> T i b -> c
lift2Gen String
"(==)" a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==)
instance (Ord i, Enum i, Show a) => Show (T i a) where
show :: T i a -> String
show (Cons T i
xu a
x) = String
"quantity " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [Int] -> String
forall a. Show a => a -> String
show (T i -> [Int]
forall i. (Enum i, Ord i) => T i -> [Int]
Unit.toVector T i
xu) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
x
instance (Ord i, Additive.C a) => Additive.C (T i a) where
zero :: T i a
zero = a -> T i a
forall a i. a -> T i a
fromScalarSingle a
forall a. C a => a
zero
+ :: T i a -> T i a -> T i a
(+) = String -> (a -> a -> a) -> T i a -> T i a -> T i a
forall i a b c.
Eq i =>
String -> (a -> b -> c) -> T i a -> T i b -> T i c
lift2 String
"(+)" a -> a -> a
forall a. C a => a -> a -> a
(+)
(-) = String -> (a -> a -> a) -> T i a -> T i a -> T i a
forall i a b c.
Eq i =>
String -> (a -> b -> c) -> T i a -> T i b -> T i c
lift2 String
"(-)" (-)
negate :: T i a -> T i a
negate = (a -> a) -> T i a -> T i a
forall a b i. (a -> b) -> T i a -> T i b
lift a -> a
forall a. C a => a -> a
negate
instance (Ord i, Ring.C a) => Ring.C (T i a) where
(Cons T i
xu a
x) * :: T i a -> T i a -> T i a
* (Cons T i
yu a
y) = T i -> a -> T i a
forall i a. T i -> a -> T i a
Cons (T i
xuT i -> T i -> T i
forall a. C a => a -> a -> a
+T i
yu) (a
xa -> a -> a
forall a. C a => a -> a -> a
*a
y)
fromInteger :: Integer -> T i a
fromInteger = a -> T i a
forall a i. a -> T i a
fromScalarSingle (a -> T i a) -> (Integer -> a) -> Integer -> T i a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> a
forall a. C a => Integer -> a
fromInteger
instance (Ord i, Ord a) => Ord (T i a) where
max :: T i a -> T i a -> T i a
max = String -> (a -> a -> a) -> T i a -> T i a -> T i a
forall i a b c.
Eq i =>
String -> (a -> b -> c) -> T i a -> T i b -> T i c
lift2 String
"max" a -> a -> a
forall a. Ord a => a -> a -> a
max
min :: T i a -> T i a -> T i a
min = String -> (a -> a -> a) -> T i a -> T i a -> T i a
forall i a b c.
Eq i =>
String -> (a -> b -> c) -> T i a -> T i b -> T i c
lift2 String
"min" a -> a -> a
forall a. Ord a => a -> a -> a
min
compare :: T i a -> T i a -> Ordering
compare = String -> (a -> a -> Ordering) -> T i a -> T i a -> Ordering
forall i a b c.
Eq i =>
String -> (a -> b -> c) -> T i a -> T i b -> c
lift2Gen String
"compare" a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare
< :: T i a -> T i a -> Bool
(<) = String -> (a -> a -> Bool) -> T i a -> T i a -> Bool
forall i a b c.
Eq i =>
String -> (a -> b -> c) -> T i a -> T i b -> c
lift2Gen String
"(<)" a -> a -> Bool
forall a. Ord a => a -> a -> Bool
(<)
> :: T i a -> T i a -> Bool
(>) = String -> (a -> a -> Bool) -> T i a -> T i a -> Bool
forall i a b c.
Eq i =>
String -> (a -> b -> c) -> T i a -> T i b -> c
lift2Gen String
"(>)" a -> a -> Bool
forall a. Ord a => a -> a -> Bool
(>)
<= :: T i a -> T i a -> Bool
(<=) = String -> (a -> a -> Bool) -> T i a -> T i a -> Bool
forall i a b c.
Eq i =>
String -> (a -> b -> c) -> T i a -> T i b -> c
lift2Gen String
"(<=)" a -> a -> Bool
forall a. Ord a => a -> a -> Bool
(<=)
>= :: T i a -> T i a -> Bool
(>=) = String -> (a -> a -> Bool) -> T i a -> T i a -> Bool
forall i a b c.
Eq i =>
String -> (a -> b -> c) -> T i a -> T i b -> c
lift2Gen String
"(>=)" a -> a -> Bool
forall a. Ord a => a -> a -> Bool
(>=)
instance (Ord i, Absolute.C a) => Absolute.C (T i a) where
abs :: T i a -> T i a
abs = (a -> a) -> T i a -> T i a
forall a b i. (a -> b) -> T i a -> T i b
lift a -> a
forall a. C a => a -> a
abs
signum :: T i a -> T i a
signum (Cons T i
_ a
x) = a -> T i a
forall a i. a -> T i a
fromScalarSingle (a -> a
forall a. C a => a -> a
signum a
x)
instance (Ord i, Field.C a) => Field.C (T i a) where
(Cons T i
xu a
x) / :: T i a -> T i a -> T i a
/ (Cons T i
yu a
y) = T i -> a -> T i a
forall i a. T i -> a -> T i a
Cons (T i
xuT i -> T i -> T i
forall a. C a => a -> a -> a
-T i
yu) (a
xa -> a -> a
forall a. C a => a -> a -> a
/a
y)
fromRational' :: Rational -> T i a
fromRational' = a -> T i a
forall a i. a -> T i a
fromScalarSingle (a -> T i a) -> (Rational -> a) -> Rational -> T i a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> a
forall a. C a => Rational -> a
fromRational'
instance (Ord i, Algebraic.C a) => Algebraic.C (T i a) where
sqrt :: T i a -> T i a
sqrt (Cons T i
xu a
x) = T i -> a -> T i a
forall i a. T i -> a -> T i a
Cons (T Int -> T i -> T i
forall i. T Int -> T i -> T i
Unit.ratScale T Int
0.5 T i
xu) (a -> a
forall a. C a => a -> a
sqrt a
x)
Cons T i
xu a
x ^/ :: T i a -> Rational -> T i a
^/ Rational
y =
T i -> a -> T i a
forall i a. T i -> a -> T i a
Cons (T Int -> T i -> T i
forall i. T Int -> T i -> T i
Unit.ratScale (Rational -> T Int
forall a. C a => Rational -> a
fromRational' Rational
y) T i
xu) (a
x a -> Rational -> a
forall a. C a => a -> Rational -> a
^/ Rational
y)
instance (Ord i, Trans.C a) => Trans.C (T i a) where
pi :: T i a
pi = a -> T i a
forall a i. a -> T i a
fromScalarSingle a
forall a. C a => a
pi
log :: T i a -> T i a
log = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
log
exp :: T i a -> T i a
exp = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
exp
logBase :: T i a -> T i a -> T i a
logBase = (a -> a -> a) -> T i a -> T i a -> T i a
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 a -> a -> a
forall a. C a => a -> a -> a
logBase
** :: T i a -> T i a -> T i a
(**) = (a -> a -> a) -> T i a -> T i a -> T i a
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 a -> a -> a
forall a. C a => a -> a -> a
(**)
cos :: T i a -> T i a
cos = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
cos
tan :: T i a -> T i a
tan = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
tan
sin :: T i a -> T i a
sin = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
sin
acos :: T i a -> T i a
acos = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
acos
atan :: T i a -> T i a
atan = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
atan
asin :: T i a -> T i a
asin = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
asin
cosh :: T i a -> T i a
cosh = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
cosh
tanh :: T i a -> T i a
tanh = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
tanh
sinh :: T i a -> T i a
sinh = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
sinh
acosh :: T i a -> T i a
acosh = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
acosh
atanh :: T i a -> T i a
atanh = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
atanh
asinh :: T i a -> T i a
asinh = (a -> a) -> T i a -> T i a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> a
forall a. C a => a -> a
asinh
instance Ord i => Vector.C (T i) where
zero :: T i a
zero = T i a
forall a. C a => a
zero
<+> :: T i a -> T i a -> T i a
(<+>) = T i a -> T i a -> T i a
forall a. C a => a -> a -> a
(+)
*> :: a -> T i a -> T i a
(*>) = a -> T i a -> T i a
forall i a. (Ord i, C a) => a -> T i a -> T i a
scale
instance (Ord i, Module.C a v) => Module.C a (T i v) where
a
x *> :: a -> T i v -> T i v
*> (Cons T i
yu v
y) = T i -> v -> T i v
forall i a. T i -> a -> T i a
Cons T i
yu (a
x a -> v -> v
forall a v. C a v => a -> v -> v
Module.*> v
y)
instance (Ord i, VectorSpace.C a v) => VectorSpace.C a (T i v)
instance (OccScalar.C a v)
=> OccScalar.C a (T i v) where
toScalar :: T i v -> a
toScalar = T i v -> a
forall a v. C a v => v -> a
toScalarDefault
toMaybeScalar :: T i v -> Maybe a
toMaybeScalar (Cons T i
xu v
x)
= Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (T i -> Bool
forall i. T i -> Bool
Unit.isScalar T i
xu) Maybe () -> Maybe a -> Maybe a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> v -> Maybe a
forall a v. C a v => v -> Maybe a
toMaybeScalar v
x
fromScalar :: a -> T i v
fromScalar = v -> T i v
forall a i. a -> T i a
fromScalarSingle (v -> T i v) -> (a -> v) -> a -> T i v
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> v
forall a v. C a v => a -> v
fromScalar
instance Functor (T i) where
fmap :: (a -> b) -> T i a -> T i b
fmap a -> b
f (Cons T i
xu a
x) =
if T i -> Bool
forall i. T i -> Bool
Unit.isScalar T i
xu
then b -> T i b
forall a i. a -> T i a
fromScalarSingle (a -> b
f a
x)
else String -> T i b
forall a. HasCallStack => String -> a
error String
"Physics.Quantity.Value.fmap: function for scalars, only"
instance Applicative (T a) where
<*> :: T a (a -> b) -> T a a -> T a b
(<*>) = T a (a -> b) -> T a a -> T a b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
pure :: a -> T a a
pure = a -> T a a
forall (m :: * -> *) a. Monad m => a -> m a
return
instance Monad (T i) where
>>= :: T i a -> (a -> T i b) -> T i b
(>>=) (Cons T i
xu a
x) a -> T i b
f =
if T i -> Bool
forall i. T i -> Bool
Unit.isScalar T i
xu
then a -> T i b
f a
x
else String -> T i b
forall a. HasCallStack => String -> a
error String
"Physics.Quantity.Value.(>>=): function for scalars, only"
return :: a -> T i a
return = a -> T i a
forall a i. a -> T i a
fromScalarSingle