module HMath.Trigonometry (
sinChecked,
cosChecked,
tanChecked,
asinChecked,
acosChecked,
atanChecked,
atan2Checked,
sec,
csc,
cot,
asec,
acsc,
acot,
sinhChecked,
coshChecked,
tanhChecked,
asinhChecked,
acoshChecked,
atanhChecked,
sech,
csch,
coth,
asech,
acsch,
acoth,
sincos,
wrap,
normalizeAngle,
normalizeSignedAngle,
angleDifference,
versine,
haversine,
sinc,
cosc,
greatCircleAngle,
greatCircleDistance,
sphericalSide,
sphericalAngles,
sphericalExcess,
ComplexFunction (..),
complexFunction,
complexSin,
complexCos,
complexTan,
complexAsin,
complexAcos,
complexAtan,
complexSinh,
complexCosh,
complexTanh,
complexAsinh,
complexAcosh,
complexAtanh,
periodicSawtooth,
periodicTriangle,
periodicSquare,
) where
import Data.Complex (Complex (..), imagPart, realPart)
import HMath.Error (MathError (..))
finite :: (RealFloat a) => a -> Bool
finite :: forall a. RealFloat a => a -> Bool
finite a
x = Bool -> Bool
not (a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
x Bool -> Bool -> Bool
|| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
x)
checked :: (RealFloat a) => (a -> a) -> a -> Either MathError a
checked :: forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked a -> a
f a
x
| Bool -> Bool
not (a -> Bool
forall a. RealFloat a => a -> Bool
finite a
x) = MathError -> Either MathError a
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"non-finite angular input")
| Bool -> Bool
not (a -> Bool
forall a. RealFloat a => a -> Bool
finite a
y) = MathError -> Either MathError a
forall a b. a -> Either a b
Left MathError
NonFiniteResult
| Bool
otherwise = a -> Either MathError a
forall a b. b -> Either a b
Right a
y
where
y :: a
y = a -> a
f a
x
restricted :: (RealFloat a) => (a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted :: forall a.
RealFloat a =>
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted a -> Bool
domain String
message a -> a
f a
x
| Bool -> Bool
not (a -> Bool
forall a. RealFloat a => a -> Bool
finite a
x) Bool -> Bool -> Bool
|| Bool -> Bool
not (a -> Bool
domain a
x) = MathError -> Either MathError a
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
message)
| Bool
otherwise = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked a -> a
f a
x
sinChecked
, cosChecked
, tanChecked
, asinChecked
, acosChecked
, atanChecked ::
(RealFloat a) => a -> Either MathError a
sinChecked :: forall a. RealFloat a => a -> Either MathError a
sinChecked = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked a -> a
forall a. Floating a => a -> a
sin
cosChecked :: forall a. RealFloat a => a -> Either MathError a
cosChecked = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked a -> a
forall a. Floating a => a -> a
cos
tanChecked :: forall a. RealFloat a => a -> Either MathError a
tanChecked a
x = do
a <- a -> Either MathError a
forall a. RealFloat a => a -> Either MathError a
normalizeSignedAngle a
x
if abs a == pi / 2 then Left (DomainError "tangent pole") else checked tan x
asinChecked :: forall a. RealFloat a => a -> Either MathError a
asinChecked = (a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
forall a.
RealFloat a =>
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted (\a
x -> a -> a
forall a. Num a => a -> a
abs a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
1) String
"asin needs abs x <= 1" a -> a
forall a. Floating a => a -> a
asin
acosChecked :: forall a. RealFloat a => a -> Either MathError a
acosChecked = (a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
forall a.
RealFloat a =>
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted (\a
x -> a -> a
forall a. Num a => a -> a
abs a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
1) String
"acos needs abs x <= 1" a -> a
forall a. Floating a => a -> a
acos
atanChecked :: forall a. RealFloat a => a -> Either MathError a
atanChecked = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked a -> a
forall a. Floating a => a -> a
atan
atan2Checked :: (RealFloat a) => a -> a -> Either MathError a
atan2Checked :: forall a. RealFloat a => a -> a -> Either MathError a
atan2Checked a
y a
x
| Bool -> Bool
not ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all a -> Bool
forall a. RealFloat a => a -> Bool
finite [a
x, a
y]) Bool -> Bool -> Bool
|| (a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 Bool -> Bool -> Bool
&& a
y a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0) = MathError -> Either MathError a
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"invalid atan2 point")
| Bool
otherwise = a -> Either MathError a
forall a b. b -> Either a b
Right (a -> a -> a
forall a. RealFloat a => a -> a -> a
atan2 a
y a
x)
sec, csc, cot, asec, acsc, acot :: (RealFloat a) => a -> Either MathError a
sec :: forall a. RealFloat a => a -> Either MathError a
sec a
x = do
a <- a -> Either MathError a
forall a. RealFloat a => a -> Either MathError a
normalizeSignedAngle a
x
if abs a == pi / 2 then Left (DomainError "secant pole") else checked (\a
v -> a
1 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a -> a
forall a. Floating a => a -> a
cos a
v) x
csc :: forall a. RealFloat a => a -> Either MathError a
csc a
x = do
a <- a -> a -> a -> Either MathError a
forall a. RealFloat a => a -> a -> a -> Either MathError a
wrap a
0 a
forall a. Floating a => a
pi a
x
if a == 0 then Left (DomainError "cosecant pole") else checked (\a
v -> a
1 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a -> a
forall a. Floating a => a -> a
sin a
v) x
cot :: forall a. RealFloat a => a -> Either MathError a
cot a
x = do
a <- a -> a -> a -> Either MathError a
forall a. RealFloat a => a -> a -> a -> Either MathError a
wrap a
0 a
forall a. Floating a => a
pi a
x
if a == 0 then Left (DomainError "cotangent pole") else checked (\a
v -> a -> a
forall a. Floating a => a -> a
cos a
v a -> a -> a
forall a. Fractional a => a -> a -> a
/ a -> a
forall a. Floating a => a -> a
sin a
v) x
asec :: forall a. RealFloat a => a -> Either MathError a
asec = (a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
forall a.
RealFloat a =>
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted (\a
x -> a -> a
forall a. Num a => a -> a
abs a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
1) String
"asec needs abs x >= 1" (a -> a
forall a. Floating a => a -> a
acos (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. Fractional a => a -> a
recip)
acsc :: forall a. RealFloat a => a -> Either MathError a
acsc = (a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
forall a.
RealFloat a =>
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted (\a
x -> a -> a
forall a. Num a => a -> a
abs a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
1) String
"acsc needs abs x >= 1" (a -> a
forall a. Floating a => a -> a
asin (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. Fractional a => a -> a
recip)
acot :: forall a. RealFloat a => a -> Either MathError a
acot = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked (a -> a -> a
forall a. RealFloat a => a -> a -> a
atan2 a
1)
sinhChecked
, coshChecked
, tanhChecked
, asinhChecked
, acoshChecked
, atanhChecked ::
(RealFloat a) => a -> Either MathError a
sinhChecked :: forall a. RealFloat a => a -> Either MathError a
sinhChecked = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked a -> a
forall a. Floating a => a -> a
sinh
coshChecked :: forall a. RealFloat a => a -> Either MathError a
coshChecked = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked a -> a
forall a. Floating a => a -> a
cosh
tanhChecked :: forall a. RealFloat a => a -> Either MathError a
tanhChecked = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked a -> a
forall a. Floating a => a -> a
tanh
asinhChecked :: forall a. RealFloat a => a -> Either MathError a
asinhChecked = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked a -> a
forall a. Floating a => a -> a
asinh
acoshChecked :: forall a. RealFloat a => a -> Either MathError a
acoshChecked = (a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
forall a.
RealFloat a =>
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted (a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
1) String
"acosh needs x >= 1" a -> a
forall a. Floating a => a -> a
acosh
atanhChecked :: forall a. RealFloat a => a -> Either MathError a
atanhChecked = (a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
forall a.
RealFloat a =>
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted (\a
x -> a -> a
forall a. Num a => a -> a
abs a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
1) String
"atanh needs abs x < 1" a -> a
forall a. Floating a => a -> a
atanh
sech, csch, coth, asech, acsch, acoth :: (RealFloat a) => a -> Either MathError a
sech :: forall a. RealFloat a => a -> Either MathError a
sech = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked (\a
x -> let e :: a
e = a -> a
forall a. Floating a => a -> a
exp (-a -> a
forall a. Num a => a -> a
abs a
x) in a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a
e a -> a -> a
forall a. Fractional a => a -> a -> a
/ (a
1 a -> a -> a
forall a. Num a => a -> a -> a
+ a
e a -> a -> a
forall a. Num a => a -> a -> a
* a
e))
csch :: forall a. RealFloat a => a -> Either MathError a
csch =
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
forall a.
RealFloat a =>
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted
(a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
0)
String
"csch pole"
(\a
x -> if a -> a
forall a. Num a => a -> a
abs a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
1 then a
1 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a -> a
forall a. Floating a => a -> a
sinh a
x else let e :: a
e = a -> a
forall a. Floating a => a -> a
exp (-a -> a
forall a. Num a => a -> a
abs a
x) in a -> a
forall a. Num a => a -> a
signum a
x a -> a -> a
forall a. Num a => a -> a -> a
* a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a
e a -> a -> a
forall a. Fractional a => a -> a -> a
/ (a
1 a -> a -> a
forall a. Num a => a -> a -> a
- a
e a -> a -> a
forall a. Num a => a -> a -> a
* a
e))
coth :: forall a. RealFloat a => a -> Either MathError a
coth = (a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
forall a.
RealFloat a =>
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
0) String
"coth pole" (a -> a
forall a. Fractional a => a -> a
recip (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. Floating a => a -> a
tanh)
asech :: forall a. RealFloat a => a -> Either MathError a
asech =
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
forall a.
RealFloat a =>
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted
(\a
x -> a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
0 Bool -> Bool -> Bool
&& a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
1)
String
"asech needs 0 < x <= 1"
(\a
x -> a -> a
forall a. Floating a => a -> a
log (a
1 a -> a -> a
forall a. Num a => a -> a -> a
+ a -> a
forall a. Floating a => a -> a
sqrt (a
1 a -> a -> a
forall a. Num a => a -> a -> a
- a
x a -> a -> a
forall a. Num a => a -> a -> a
* a
x)) a -> a -> a
forall a. Num a => a -> a -> a
- a -> a
forall a. Floating a => a -> a
log a
x)
acsch :: forall a. RealFloat a => a -> Either MathError a
acsch =
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
forall a.
RealFloat a =>
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted
(a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
0)
String
"acsch needs x /= 0"
(\a
x -> if a -> a
forall a. Num a => a -> a
abs a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
1e-15 then a -> a
forall a. Num a => a -> a
signum a
x a -> a -> a
forall a. Num a => a -> a -> a
* (a -> a
forall a. Floating a => a -> a
log a
2 a -> a -> a
forall a. Num a => a -> a -> a
- a -> a
forall a. Floating a => a -> a
log (a -> a
forall a. Num a => a -> a
abs a
x)) else a -> a
forall a. Floating a => a -> a
asinh (a
1 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
x))
acoth :: forall a. RealFloat a => a -> Either MathError a
acoth = (a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
forall a.
RealFloat a =>
(a -> Bool) -> String -> (a -> a) -> a -> Either MathError a
restricted (\a
x -> a -> a
forall a. Num a => a -> a
abs a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
1) String
"acoth needs abs x > 1" (a -> a
forall a. Floating a => a -> a
atanh (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. Fractional a => a -> a
recip)
sincos :: (RealFloat a) => a -> Either MathError (a, a)
sincos :: forall a. RealFloat a => a -> Either MathError (a, a)
sincos a
x = do s <- a -> Either MathError a
forall a. RealFloat a => a -> Either MathError a
sinChecked a
x; c <- cosChecked x; Right (s, c)
wrap :: (RealFloat a) => a -> a -> a -> Either MathError a
wrap :: forall a. RealFloat a => a -> a -> a -> Either MathError a
wrap a
lo a
hi a
x
| Bool -> Bool
not ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all a -> Bool
forall a. RealFloat a => a -> Bool
finite [a
lo, a
hi, a
x]) Bool -> Bool -> Bool
|| a
lo a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
hi = MathError -> Either MathError a
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"invalid wrapping interval")
| Bool
otherwise =
let a :: Rational
a = a -> Rational
forall a. Real a => a -> Rational
toRational a
lo
b :: Rational
b = a -> Rational
forall a. Real a => a -> Rational
toRational a
hi
period :: Rational
period = Rational
b Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Rational
a
v :: Rational
v = a -> Rational
forall a. Real a => a -> Rational
toRational a
x Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Rational
a
r :: a
r = Rational -> a
forall a. Fractional a => Rational -> a
fromRational (Rational
a Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
v Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Integer -> Rational
forall a. Num a => Integer -> a
fromInteger (Rational -> Integer
forall b. Integral b => Rational -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor (Rational
v Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational
period)) Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
period)
in a -> Either MathError a
forall a b. b -> Either a b
Right (if a
r a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
hi then a
lo else a -> a -> a
forall a. Ord a => a -> a -> a
max a
lo a
r)
normalizeAngle, normalizeSignedAngle :: (RealFloat a) => a -> Either MathError a
normalizeAngle :: forall a. RealFloat a => a -> Either MathError a
normalizeAngle = a -> a -> a -> Either MathError a
forall a. RealFloat a => a -> a -> a -> Either MathError a
wrap a
0 (a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a
forall a. Floating a => a
pi)
normalizeSignedAngle :: forall a. RealFloat a => a -> Either MathError a
normalizeSignedAngle = a -> a -> a -> Either MathError a
forall a. RealFloat a => a -> a -> a -> Either MathError a
wrap (-a
forall a. Floating a => a
pi) a
forall a. Floating a => a
pi
angleDifference :: (RealFloat a) => a -> a -> Either MathError a
angleDifference :: forall a. RealFloat a => a -> a -> Either MathError a
angleDifference a
a a
b
| Bool -> Bool
not ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all a -> Bool
forall a. RealFloat a => a -> Bool
finite [a
a, a
b]) = MathError -> Either MathError a
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"non-finite angle")
| Bool
otherwise = do x <- a -> Either MathError a
forall a. RealFloat a => a -> Either MathError a
normalizeSignedAngle a
a; y <- normalizeSignedAngle b; normalizeSignedAngle (x - y)
versine, haversine, sinc, cosc :: (RealFloat a) => a -> Either MathError a
versine :: forall a. RealFloat a => a -> Either MathError a
versine = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked (\a
x -> a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
sin (a
x a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2) a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2 :: Int))
haversine :: forall a. RealFloat a => a -> Either MathError a
haversine = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked (\a
x -> a -> a
forall a. Floating a => a -> a
sin (a
x a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2) a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2 :: Int))
sinc :: forall a. RealFloat a => a -> Either MathError a
sinc a
x
| a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = a -> Either MathError a
forall a b. b -> Either a b
Right a
1
| Bool
otherwise = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked (\a
v -> a -> a
forall a. Floating a => a -> a
sin a
v a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
v) a
x
cosc :: forall a. RealFloat a => a -> Either MathError a
cosc a
x
| a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = a -> Either MathError a
forall a b. b -> Either a b
Right a
x
| Bool
otherwise = (a -> a) -> a -> Either MathError a
forall a. RealFloat a => (a -> a) -> a -> Either MathError a
checked (\a
v -> (a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
sin (a
v a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2) a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
v) a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
sin (a
v a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2)) a
x
greatCircleAngle :: (RealFloat a) => (a, a) -> (a, a) -> Either MathError a
greatCircleAngle :: forall a. RealFloat a => (a, a) -> (a, a) -> Either MathError a
greatCircleAngle (a
lat1, a
lon1) (a
lat2, a
lon2)
| Bool -> Bool
not ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all a -> Bool
forall a. RealFloat a => a -> Bool
finite [a
lat1, a
lon1, a
lat2, a
lon2]) Bool -> Bool -> Bool
|| a -> a
forall a. Num a => a -> a
abs a
lat1 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
forall a. Floating a => a
pi a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2 Bool -> Bool -> Bool
|| a -> a
forall a. Num a => a -> a
abs a
lat2 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
forall a. Floating a => a
pi a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2 =
MathError -> Either MathError a
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"invalid spherical coordinates")
| Bool
otherwise = do
dl <- a -> a -> Either MathError a
forall a. RealFloat a => a -> a -> Either MathError a
angleDifference a
lon2 a
lon1
let a = a -> a
forall a. Floating a => a -> a
sin ((a
lat2 a -> a -> a
forall a. Num a => a -> a -> a
- a
lat1) a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2) a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2 :: Int) a -> a -> a
forall a. Num a => a -> a -> a
+ a -> a
forall a. Floating a => a -> a
cos a
lat1 a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
cos a
lat2 a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
sin (a
dl a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2) a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2 :: Int)
h = a -> a -> a
forall a. Ord a => a -> a -> a
max a
0 (a -> a -> a
forall a. Ord a => a -> a -> a
min a
1 a
a)
Right (2 * atan2 (sqrt h) (sqrt (1 - h)))
greatCircleDistance :: (RealFloat a) => a -> (a, a) -> (a, a) -> Either MathError a
greatCircleDistance :: forall a.
RealFloat a =>
a -> (a, a) -> (a, a) -> Either MathError a
greatCircleDistance a
radius (a, a)
a (a, a)
b
| Bool -> Bool
not (a -> Bool
forall a. RealFloat a => a -> Bool
finite a
radius) Bool -> Bool -> Bool
|| a
radius a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = MathError -> Either MathError a
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"invalid sphere radius")
| Bool
otherwise =
(a, a) -> (a, a) -> Either MathError a
forall a. RealFloat a => (a, a) -> (a, a) -> Either MathError a
greatCircleAngle (a, a)
a (a, a)
b Either MathError a
-> (a -> Either MathError a) -> Either MathError a
forall a b.
Either MathError a
-> (a -> Either MathError b) -> Either MathError b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a
v -> if a -> Bool
forall a. RealFloat a => a -> Bool
finite (a
radius a -> a -> a
forall a. Num a => a -> a -> a
* a
v) then a -> Either MathError a
forall a b. b -> Either a b
Right (a
radius a -> a -> a
forall a. Num a => a -> a -> a
* a
v) else MathError -> Either MathError a
forall a b. a -> Either a b
Left MathError
NonFiniteResult
sphericalSide :: (RealFloat a) => a -> a -> a -> Either MathError a
sphericalSide :: forall a. RealFloat a => a -> a -> a -> Either MathError a
sphericalSide a
a a
b a
included
| Bool -> Bool
not ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all a -> Bool
forall a. RealFloat a => a -> Bool
finite [a
a, a
b, a
included]) Bool -> Bool -> Bool
|| (a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (\a
x -> a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 Bool -> Bool -> Bool
|| a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
forall a. Floating a => a
pi) [a
a, a
b, a
included] =
MathError -> Either MathError a
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"invalid spherical sides/angle")
| Bool
otherwise = a -> Either MathError a
forall a b. b -> Either a b
Right (a -> a
forall a. Floating a => a -> a
acos (a -> a -> a
forall a. Ord a => a -> a -> a
max (-a
1) (a -> a -> a
forall a. Ord a => a -> a -> a
min a
1 (a -> a
forall a. Floating a => a -> a
cos a
a a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
cos a
b a -> a -> a
forall a. Num a => a -> a -> a
+ a -> a
forall a. Floating a => a -> a
sin a
a a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
sin a
b a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
cos a
included))))
sphericalAngles :: (RealFloat a) => a -> a -> a -> Either MathError (a, a, a)
sphericalAngles :: forall a. RealFloat a => a -> a -> a -> Either MathError (a, a, a)
sphericalAngles a
a a
b a
c
| Bool -> Bool
not ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all a -> Bool
forall a. RealFloat a => a -> Bool
finite [a
a, a
b, a
c])
Bool -> Bool -> Bool
|| (a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (\a
x -> a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0 Bool -> Bool -> Bool
|| a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
forall a. Floating a => a
pi) [a
a, a
b, a
c]
Bool -> Bool -> Bool
|| a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a
b a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
c
Bool -> Bool -> Bool
|| a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a
c a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
b
Bool -> Bool -> Bool
|| a
b a -> a -> a
forall a. Num a => a -> a -> a
+ a
c a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
a
Bool -> Bool -> Bool
|| a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a
b a -> a -> a
forall a. Num a => a -> a -> a
+ a
c a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a
forall a. Floating a => a
pi =
MathError -> Either MathError (a, a, a)
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"degenerate spherical triangle")
| Bool
otherwise = (a, a, a) -> Either MathError (a, a, a)
forall a b. b -> Either a b
Right (a -> a -> a -> a
forall {a}. (Floating a, Ord a) => a -> a -> a -> a
angle a
a a
b a
c, a -> a -> a -> a
forall {a}. (Floating a, Ord a) => a -> a -> a -> a
angle a
b a
a a
c, a -> a -> a -> a
forall {a}. (Floating a, Ord a) => a -> a -> a -> a
angle a
c a
a a
b)
where
angle :: a -> a -> a -> a
angle a
x a
y a
z = a -> a
forall a. Floating a => a -> a
acos (a -> a -> a
forall a. Ord a => a -> a -> a
max (-a
1) (a -> a -> a
forall a. Ord a => a -> a -> a
min a
1 ((a -> a
forall a. Floating a => a -> a
cos a
x a -> a -> a
forall a. Num a => a -> a -> a
- a -> a
forall a. Floating a => a -> a
cos a
y a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
cos a
z) a -> a -> a
forall a. Fractional a => a -> a -> a
/ (a -> a
forall a. Floating a => a -> a
sin a
y a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Floating a => a -> a
sin a
z))))
sphericalExcess :: (RealFloat a) => a -> a -> a -> Either MathError a
sphericalExcess :: forall a. RealFloat a => a -> a -> a -> Either MathError a
sphericalExcess a
a a
b a
c = do (x, y, z) <- a -> a -> a -> Either MathError (a, a, a)
forall a. RealFloat a => a -> a -> a -> Either MathError (a, a, a)
sphericalAngles a
a a
b a
c; Right (x + y + z - pi)
data ComplexFunction
= CSin
| CCos
| CTan
| CAsin
| CAcos
| CAtan
| CSinh
| CCosh
| CTanh
| CAsinh
| CAcosh
| CAtanh
| CSec
| CCsc
| CCot
| CSech
| CCsch
| CCoth
deriving (ComplexFunction -> ComplexFunction -> Bool
(ComplexFunction -> ComplexFunction -> Bool)
-> (ComplexFunction -> ComplexFunction -> Bool)
-> Eq ComplexFunction
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ComplexFunction -> ComplexFunction -> Bool
== :: ComplexFunction -> ComplexFunction -> Bool
$c/= :: ComplexFunction -> ComplexFunction -> Bool
/= :: ComplexFunction -> ComplexFunction -> Bool
Eq, Int -> ComplexFunction -> ShowS
[ComplexFunction] -> ShowS
ComplexFunction -> String
(Int -> ComplexFunction -> ShowS)
-> (ComplexFunction -> String)
-> ([ComplexFunction] -> ShowS)
-> Show ComplexFunction
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ComplexFunction -> ShowS
showsPrec :: Int -> ComplexFunction -> ShowS
$cshow :: ComplexFunction -> String
show :: ComplexFunction -> String
$cshowList :: [ComplexFunction] -> ShowS
showList :: [ComplexFunction] -> ShowS
Show)
complexFunction :: (RealFloat a) => ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction :: forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
name Complex a
z
| Bool -> Bool
not (a -> Bool
forall a. RealFloat a => a -> Bool
finite (Complex a -> a
forall a. Complex a -> a
realPart Complex a
z) Bool -> Bool -> Bool
&& a -> Bool
forall a. RealFloat a => a -> Bool
finite (Complex a -> a
forall a. Complex a -> a
imagPart Complex a
z)) =
MathError -> Either MathError (Complex a)
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"non-finite complex argument")
| Bool -> Bool
not (a -> Bool
forall a. RealFloat a => a -> Bool
finite (Complex a -> a
forall a. Complex a -> a
realPart Complex a
value) Bool -> Bool -> Bool
&& a -> Bool
forall a. RealFloat a => a -> Bool
finite (Complex a -> a
forall a. Complex a -> a
imagPart Complex a
value)) =
MathError -> Either MathError (Complex a)
forall a b. a -> Either a b
Left (String -> MathError
DomainError String
"complex pole or overflow")
| Bool
otherwise = Complex a -> Either MathError (Complex a)
forall a b. b -> Either a b
Right Complex a
value
where
value :: Complex a
value = case ComplexFunction
name of
ComplexFunction
CSin -> Complex a -> Complex a
forall a. Floating a => a -> a
sin Complex a
z
ComplexFunction
CCos -> Complex a -> Complex a
forall a. Floating a => a -> a
cos Complex a
z
ComplexFunction
CTan -> Complex a -> Complex a
forall a. Floating a => a -> a
tan Complex a
z
ComplexFunction
CAsin -> Complex a -> Complex a
forall a. Floating a => a -> a
asin Complex a
z
ComplexFunction
CAcos -> Complex a -> Complex a
forall a. Floating a => a -> a
acos Complex a
z
ComplexFunction
CAtan -> Complex a -> Complex a
forall a. Floating a => a -> a
atan Complex a
z
ComplexFunction
CSinh -> Complex a -> Complex a
forall a. Floating a => a -> a
sinh Complex a
z
ComplexFunction
CCosh -> Complex a -> Complex a
forall a. Floating a => a -> a
cosh Complex a
z
ComplexFunction
CTanh -> Complex a -> Complex a
forall a. Floating a => a -> a
tanh Complex a
z
ComplexFunction
CAsinh -> Complex a -> Complex a
forall a. Floating a => a -> a
asinh Complex a
z
ComplexFunction
CAcosh -> Complex a -> Complex a
forall a. Floating a => a -> a
acosh Complex a
z
ComplexFunction
CAtanh -> Complex a -> Complex a
forall a. Floating a => a -> a
atanh Complex a
z
ComplexFunction
CSec -> Complex a
1 Complex a -> Complex a -> Complex a
forall a. Fractional a => a -> a -> a
/ Complex a -> Complex a
forall a. Floating a => a -> a
cos Complex a
z
ComplexFunction
CCsc -> Complex a
1 Complex a -> Complex a -> Complex a
forall a. Fractional a => a -> a -> a
/ Complex a -> Complex a
forall a. Floating a => a -> a
sin Complex a
z
ComplexFunction
CCot -> Complex a -> Complex a
forall a. Floating a => a -> a
cos Complex a
z Complex a -> Complex a -> Complex a
forall a. Fractional a => a -> a -> a
/ Complex a -> Complex a
forall a. Floating a => a -> a
sin Complex a
z
ComplexFunction
CSech -> Complex a
1 Complex a -> Complex a -> Complex a
forall a. Fractional a => a -> a -> a
/ Complex a -> Complex a
forall a. Floating a => a -> a
cosh Complex a
z
ComplexFunction
CCsch -> Complex a
1 Complex a -> Complex a -> Complex a
forall a. Fractional a => a -> a -> a
/ Complex a -> Complex a
forall a. Floating a => a -> a
sinh Complex a
z
ComplexFunction
CCoth -> Complex a -> Complex a
forall a. Floating a => a -> a
cosh Complex a
z Complex a -> Complex a -> Complex a
forall a. Fractional a => a -> a -> a
/ Complex a -> Complex a
forall a. Floating a => a -> a
sinh Complex a
z
complexSin
, complexCos
, complexTan
, complexAsin
, complexAcos
, complexAtan
, complexSinh
, complexCosh
, complexTanh
, complexAsinh
, complexAcosh
, complexAtanh ::
(RealFloat a) => Complex a -> Either MathError (Complex a)
complexSin :: forall a. RealFloat a => Complex a -> Either MathError (Complex a)
complexSin = ComplexFunction -> Complex a -> Either MathError (Complex a)
forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
CSin
complexCos :: forall a. RealFloat a => Complex a -> Either MathError (Complex a)
complexCos = ComplexFunction -> Complex a -> Either MathError (Complex a)
forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
CCos
complexTan :: forall a. RealFloat a => Complex a -> Either MathError (Complex a)
complexTan = ComplexFunction -> Complex a -> Either MathError (Complex a)
forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
CTan
complexAsin :: forall a. RealFloat a => Complex a -> Either MathError (Complex a)
complexAsin = ComplexFunction -> Complex a -> Either MathError (Complex a)
forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
CAsin
complexAcos :: forall a. RealFloat a => Complex a -> Either MathError (Complex a)
complexAcos = ComplexFunction -> Complex a -> Either MathError (Complex a)
forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
CAcos
complexAtan :: forall a. RealFloat a => Complex a -> Either MathError (Complex a)
complexAtan = ComplexFunction -> Complex a -> Either MathError (Complex a)
forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
CAtan
complexSinh :: forall a. RealFloat a => Complex a -> Either MathError (Complex a)
complexSinh = ComplexFunction -> Complex a -> Either MathError (Complex a)
forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
CSinh
complexCosh :: forall a. RealFloat a => Complex a -> Either MathError (Complex a)
complexCosh = ComplexFunction -> Complex a -> Either MathError (Complex a)
forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
CCosh
complexTanh :: forall a. RealFloat a => Complex a -> Either MathError (Complex a)
complexTanh = ComplexFunction -> Complex a -> Either MathError (Complex a)
forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
CTanh
complexAsinh :: forall a. RealFloat a => Complex a -> Either MathError (Complex a)
complexAsinh = ComplexFunction -> Complex a -> Either MathError (Complex a)
forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
CAsinh
complexAcosh :: forall a. RealFloat a => Complex a -> Either MathError (Complex a)
complexAcosh = ComplexFunction -> Complex a -> Either MathError (Complex a)
forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
CAcosh
complexAtanh :: forall a. RealFloat a => Complex a -> Either MathError (Complex a)
complexAtanh = ComplexFunction -> Complex a -> Either MathError (Complex a)
forall a.
RealFloat a =>
ComplexFunction -> Complex a -> Either MathError (Complex a)
complexFunction ComplexFunction
CAtanh
periodicSawtooth, periodicTriangle, periodicSquare :: (RealFloat a) => a -> a -> Either MathError a
periodicSawtooth :: forall a. RealFloat a => a -> a -> Either MathError a
periodicSawtooth a
period a
x = do t <- a -> a -> a -> Either MathError a
forall a. RealFloat a => a -> a -> a -> Either MathError a
wrap a
0 a
period a
x; Right (2 * (t / period) - 1)
periodicTriangle :: forall a. RealFloat a => a -> a -> Either MathError a
periodicTriangle a
period a
x = do t <- a -> a -> a -> Either MathError a
forall a. RealFloat a => a -> a -> a -> Either MathError a
wrap a
0 a
period a
x; Right (1 - 4 * abs (t / period - 0.5))
periodicSquare :: forall a. RealFloat a => a -> a -> Either MathError a
periodicSquare a
period a
x = do t <- a -> a -> a -> Either MathError a
forall a. RealFloat a => a -> a -> a -> Either MathError a
wrap a
0 a
period a
x; Right (if t / period < 0.5 then 1 else -1)