2 | import Derive.Prelude
8 | %language ElabReflection
13 | solveQuadratic : (a,b,c : Double) -> Maybe (Double,Double)
14 | solveQuadratic a b c =
15 | let disc := b * b - 4 * a * c
16 | True := disc >= 0 && a > 0 | False => Nothing
18 | in Just (((-b) - root) / (2 * a), ((-b) + root) / (2 * a))
36 | record LinearTransformation where
43 | Id : LinearTransformation
48 | rotation : Angle -> LinearTransformation
53 | scaling : Scale -> LinearTransformation
54 | scaling = (`LT` zero)
57 | Semigroup LinearTransformation where
58 | LT s1 r1 <+> LT s2 r2 = LT (s1 * s2) (r1 + r2)
61 | Monoid LinearTransformation where neutral = Id
67 | inverse : LinearTransformation -> LinearTransformation
68 | inverse (LT s r) = LT (inverse s) (negate r)
76 | record Vector (t : LinearTransformation) where
81 | %runElab deriveIndexed "Vector" [Show,Eq,Ord]
95 | vid : (x,y : Double) -> Vector Id
100 | length : Vector t -> Double
101 | length (V x y) = sqrt (x * x + y * y)
105 | (+) : Vector t -> Vector t -> Vector t
106 | V x1 y1 + V x2 y2 = V (x1+x2) (y1+y2)
110 | (-) : Vector t -> Vector t -> Vector t
111 | V x1 y1 - V x2 y2 = V (x1-x2) (y1-y2)
115 | negate : Vector t -> Vector t
116 | negate (V x y) = V (-x) (-y)
120 | scale : Double -> Vector t -> Vector t
121 | scale v (V x y) = V (v*x) (v*y)
125 | scaleTo : Double -> Vector t -> Vector t
127 | let lv := length v in if lv == 0.0 then v else scale (l/lv) v
131 | normalize : Vector t -> Vector t
132 | normalize = scaleTo 1.0
136 | transform : LinearTransformation -> Vector t -> Vector t
137 | transform (LT s r) (V x y) =
138 | let co := s.value * cos r.value
139 | si := s.value * sin r.value
140 | in V (co * x - si * y) (si * x + co * y)
144 | polar : Scale -> Angle -> Vector t
145 | polar s a = transform (LT s a) vone
149 | rotate : Angle -> Vector t -> Vector t
150 | rotate = transform . rotation
155 | angle : Vector t -> Maybe Angle
157 | if x == 0 && y == 0 then Nothing
158 | else if x == 0 then Just $
if y > 0 then halfPi else negate halfPi
160 | let phi := atan (y / x)
161 | in Just $
if x > 0 then angle phi else angle (phi + pi)
165 | angleOrZero : Vector t -> Angle
166 | angleOrZero = fromMaybe zero . angle
172 | perpendicular : Vector t -> Vector t
173 | perpendicular (V x y) = V (-y) x
177 | dot : Vector t -> Vector t -> Double
178 | dot (V x1 y1) (V x2 y2) = x1*x2 + y1*y2