/
Math.purs
151 lines (117 loc) · 3.17 KB
/
Math.purs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
-- | This module defines mathematical operations on physical quantities. Most
-- | of these functions return `Either ConversionError Quantity` since they
-- | can only be applied to scalar (dimensionless) values. If the conversion
-- | to a scalar fails, they will return a `ConversionError`.
module Data.Quantity.Math
( acos
, asin
, atan
, atan2
, cos
, exp
, ln
, sin
, tan
, sinh
, cosh
, tanh
, asinh
, acosh
, atanh
, ceil
, floor
, log10
, max2
, max
, min2
, min
, mean
, modulo
, round
, gamma
, factorial
, pi
, e
, tau
) where
import Prelude
import Data.Decimal as Decimal
import Data.List.NonEmpty (NonEmptyList, head, tail, length)
import Data.Foldable (foldM)
import Data.Decimal (Decimal)
import Data.Either (Either)
import Data.Quantity (Quantity, ConversionError, derivedUnit, asValueIn',
scalar', quantity', toScalar', (⊘), (⊕), (.*))
type Result = Either ConversionError Quantity
lift ∷ (Decimal → Decimal) → Quantity → Result
lift fn q = (scalar' <<< fn) <$> toScalar' q
lift2 ∷ (Decimal → Decimal → Decimal) → Quantity → Quantity → Result
lift2 f q1 q2 = do
let u = derivedUnit q1
v1 ← q1 `asValueIn'` u
v2 ← q2 `asValueIn'` u
pure $ quantity' (f v1 v2) u
acos ∷ Quantity → Result
acos = lift Decimal.acos
asin ∷ Quantity → Result
asin = lift Decimal.asin
atan ∷ Quantity → Result
atan = lift Decimal.atan
atan2 ∷ Quantity → Quantity → Result
atan2 x y = removeDims <$> lift2 Decimal.atan2 x y
where
removeDims q = q ⊘ 1.0 .* derivedUnit q
cos ∷ Quantity → Result
cos = lift Decimal.cos
exp ∷ Quantity → Result
exp = lift Decimal.exp
ln ∷ Quantity → Result
ln = lift Decimal.ln
sin ∷ Quantity → Result
sin = lift Decimal.sin
tan ∷ Quantity → Result
tan = lift Decimal.tan
sinh ∷ Quantity → Result
sinh = lift Decimal.sinh
cosh ∷ Quantity → Result
cosh = lift Decimal.cosh
tanh ∷ Quantity → Result
tanh = lift Decimal.tanh
asinh ∷ Quantity → Result
asinh = lift Decimal.asinh
acosh ∷ Quantity → Result
acosh = lift Decimal.acosh
atanh ∷ Quantity → Result
atanh = lift Decimal.atanh
ceil ∷ Quantity → Result
ceil = lift Decimal.ceil
floor ∷ Quantity → Result
floor = lift Decimal.floor
log10 ∷ Quantity → Result
log10 = lift Decimal.log10
max2 ∷ Quantity → Quantity → Result
max2 = lift2 Decimal.max
max ∷ NonEmptyList Quantity → Result
max xs = foldM max2 (head xs) (tail xs)
min2 ∷ Quantity → Quantity → Result
min2 = lift2 Decimal.min
min ∷ NonEmptyList Quantity → Result
min xs = foldM min2 (head xs) (tail xs)
mean ∷ NonEmptyList Quantity → Result
mean xs = (_ ⊘ n) <$> foldM (⊕) (head xs) (tail xs)
where
n = scalar' (Decimal.fromInt (length xs))
modulo ∷ Quantity → Quantity → Result
modulo = lift2 Decimal.modulo
round ∷ Quantity → Result
round = lift Decimal.round
gamma ∷ Quantity → Result
gamma = lift Decimal.gamma
factorial ∷ Quantity → Result
factorial = lift Decimal.factorial
pi ∷ Quantity
pi = scalar' Decimal.pi
e ∷ Quantity
e = scalar' Decimal.e
tau ∷ Quantity
tau = scalar' $ Decimal.fromNumber 2.0 * Decimal.pi