mirror of
https://github.com/carp-lang/Carp.git
synced 2024-11-04 19:26:10 +03:00
285 lines
7.2 KiB
Plaintext
285 lines
7.2 KiB
Plaintext
(deftype (Vector2 f) [x f, y f])
|
|
(derive Vector2 zero)
|
|
(derive Vector2 =)
|
|
|
|
(defmodule Vector2
|
|
(defn map [f v]
|
|
(init (f @(x v))
|
|
(f @(y v))))
|
|
|
|
(defn zip [f a b]
|
|
(init (f @(x a) @(x b))
|
|
(f @(y a) @(y b))))
|
|
|
|
(defn vreduce [f i v]
|
|
(f (f i @(x v)) @(y v)))
|
|
|
|
(defn random []
|
|
(init (random-0-1) (random-0-1)))
|
|
(implements random Vector2.random)
|
|
|
|
(defn add [a b]
|
|
(zip + a b))
|
|
|
|
(defn sub [a b]
|
|
(zip - a b))
|
|
|
|
(defn mul [a n]
|
|
(init (* @(x a) n)
|
|
(* @(y a) n)))
|
|
|
|
(defn div [a n]
|
|
(init (/ @(x a) n)
|
|
(/ @(y a) n)))
|
|
|
|
(doc vapprox "Check whether the vectors a and b are approximately equal.")
|
|
(defn vapprox [a b]
|
|
(vreduce (fn [i v] (and i v)) true &(zip Generics.approx a b)))
|
|
|
|
(defn sum [o]
|
|
(vreduce + (zero) o))
|
|
|
|
(doc dot "Get the dot product of the two vectors x and y.")
|
|
(defn dot [a b]
|
|
(sum &(zip * a b)))
|
|
|
|
(doc mag-sq "Get the squared magnitude of a vector.")
|
|
(defn mag-sq [o]
|
|
(dot o o))
|
|
|
|
(doc mag "Get the magnitude of a vector.")
|
|
(defn mag [o]
|
|
(sqrt (mag-sq o)))
|
|
|
|
(doc normalize "Normalize a vector.")
|
|
(defn normalize [o]
|
|
(let [m (mag o)]
|
|
(if (zero? m)
|
|
@o
|
|
(div o m))))
|
|
|
|
(doc dist "Get the distance between the vectors a and b.")
|
|
(defn dist [a b]
|
|
(let [s (sub b a)]
|
|
(mag &s)))
|
|
|
|
(doc heading "Get the heading of the vector a.")
|
|
(defn heading [a]
|
|
(atan2 @(y a) @(x a)))
|
|
|
|
(doc rotate "Rotate the vector a by the radians n.")
|
|
(defn rotate [a n]
|
|
(let [h (+ (heading a) n)
|
|
m (mag a)]
|
|
(init (* (cos h) m) (* (sin h) m))))
|
|
|
|
(doc angle-between "Get the angle between two vectors a and b.")
|
|
(defn angle-between [a b]
|
|
(let [dmm (/ (dot a b) (* (mag a) (mag b)))]
|
|
(acos (clamp--1-1 dmm))))
|
|
|
|
(doc anti-parallel? "Check whether the two vectors a and b are anti-parallel.")
|
|
(defn anti-parallel? [a b]
|
|
(= (angle-between a b) pi))
|
|
|
|
(doc parallel? "Check whether the two vectors a and b are parallel.")
|
|
(defn parallel? [a b]
|
|
(zero? (angle-between a b)))
|
|
|
|
(doc perpendicular? "Check whether the two vectors a and b are perpendicular.")
|
|
(defn perpendicular? [a b]
|
|
(= (angle-between a b) (Generics.half-pi)))
|
|
|
|
(doc vlerp "Linearly interpolate between the two vectors a and b by amnt (between 0 and 1).")
|
|
(defn vlerp [a b amnt]
|
|
(zip (fn [a b] (lerp a b amnt)) a b))
|
|
)
|
|
|
|
(deftype (Vector3 f) [x f, y f, z f])
|
|
(derive Vector3 zero)
|
|
(derive Vector3 =)
|
|
|
|
(defmodule Vector3
|
|
(defn map [f v]
|
|
(init (f @(x v))
|
|
(f @(y v))
|
|
(f @(z v))))
|
|
|
|
(defn zip [f a b]
|
|
(init (f @(x a) @(x b))
|
|
(f @(y a) @(y b))
|
|
(f @(z a) @(z b))))
|
|
|
|
(defn vreduce [f i v]
|
|
(f (f (f i @(x v)) @(y v)) @(z v)))
|
|
|
|
(defn random []
|
|
(init (random-0-1) (random-0-1) (random-0-1)))
|
|
(implements random Vector3.random)
|
|
|
|
(doc vapprox "Check whether the vectors a and b are approximately equal.")
|
|
(defn vapprox [a b]
|
|
(vreduce (fn [i v] (and i v)) true &(zip Generics.approx a b)))
|
|
|
|
(defn add [a b]
|
|
(zip + a b))
|
|
|
|
(defn sub [a b]
|
|
(zip - a b))
|
|
|
|
(defn cmul [a b]
|
|
(zip * a b))
|
|
|
|
(defn neg [a]
|
|
(map neg a))
|
|
|
|
(defn mul [v n]
|
|
(map (fn [c] (* n c)) v))
|
|
|
|
(defn div [v n]
|
|
(map (fn [c] (/ c n)) v))
|
|
|
|
(defn sum [o]
|
|
(vreduce + (zero) o))
|
|
|
|
(doc dot "Get the dot product of the two vectors x and y.")
|
|
(defn dot [a b]
|
|
(sum &(zip * a b)))
|
|
|
|
(doc mag-sq "Get the squared magnitude of a vector.")
|
|
(defn mag-sq [o]
|
|
(dot o o))
|
|
|
|
(doc mag "Get the magnitude of a vector.")
|
|
(defn mag [o]
|
|
(sqrt (mag-sq o)))
|
|
|
|
(doc normalize "Normalize a vector.")
|
|
(defn normalize [o]
|
|
(let [m (mag o)]
|
|
(if (= m (zero))
|
|
@o
|
|
(div o m))))
|
|
|
|
(doc dist "Get the distance between the vectors a and b.")
|
|
(defn dist [a b]
|
|
(let [s (sub b a)]
|
|
(mag &s)))
|
|
|
|
(doc cross "Compute the cross product of the two vectors x and y.")
|
|
(defn cross [a b]
|
|
(init
|
|
(- (* @(y a) @(z b))
|
|
(* @(z a) @(y b)))
|
|
(- (* @(z a) @(x b))
|
|
(* @(x a) @(z b)))
|
|
(- (* @(x a) @(y b))
|
|
(* @(y a) @(x b)))))
|
|
|
|
(doc angle-between "Get the angle between two vectors a and b.")
|
|
(defn angle-between [a b]
|
|
(let [dmm (/ (dot a b) (* (mag a) (mag b)))]
|
|
(acos (clamp--1-1 dmm))))
|
|
|
|
(doc anti-parallel? "Check whether the two vectors a and b are anti-parallel.")
|
|
(defn anti-parallel? [a b]
|
|
(= (angle-between a b) pi))
|
|
|
|
(doc parallel? "Check whether the two vectors a and b are parallel.")
|
|
(defn parallel? [a b]
|
|
(zero? (angle-between a b)))
|
|
|
|
(doc perpendicular? "Check whether the two vectors a and b are perpendicular.")
|
|
(defn perpendicular? [a b]
|
|
(= (angle-between a b) (Generics.half-pi)))
|
|
|
|
(doc vlerp "Linearly interpolate between the two vectors a and b by amnt (between 0 and 1).")
|
|
(defn vlerp [a b amnt]
|
|
(zip (fn [a b] (lerp a b amnt)) a b))
|
|
)
|
|
|
|
|
|
(deftype (VectorN f) [n Int, v (Array f)])
|
|
(derive VectorN =)
|
|
|
|
(defmodule VectorN
|
|
(defn zero-sized [n]
|
|
(let [z (zero)]
|
|
(init n (Array.replicate n &z))))
|
|
|
|
(defn random-sized [n]
|
|
(init n (Array.repeat n &random-0-1)))
|
|
|
|
(defn zip- [f a b]
|
|
(let [total (Array.allocate (Array.length a))]
|
|
(do
|
|
(for [i 0 (Array.length a)]
|
|
(Array.aset-uninitialized! &total i (f @(Array.unsafe-nth a i)
|
|
@(Array.unsafe-nth b i))))
|
|
(init (Array.length a) total))))
|
|
|
|
(defn zip [f a b]
|
|
(if (= @(n a) @(n b))
|
|
(Maybe.Just (zip- f (v a) (v b)))
|
|
(Maybe.Nothing)))
|
|
|
|
(defn add [a b]
|
|
(zip + a b))
|
|
|
|
(defn sub [a b]
|
|
(zip - a b))
|
|
|
|
(defn mul [a n]
|
|
(zip- * (v a) &(Array.replicate @(VectorN.n a) &n)))
|
|
|
|
(defn div [a n]
|
|
(zip- / (v a) &(Array.replicate @(VectorN.n a) &n)))
|
|
|
|
(doc dot "Get the dot product of the two vectors x and y.")
|
|
(defn dot [x y]
|
|
(Maybe.apply (zip * x y)
|
|
&(fn [x] (Array.reduce &(fn [x y] (+ x @y)) (zero) (v &x)))))
|
|
|
|
(doc mag-sq "Get the squared magnitude of a vector.")
|
|
(defn mag-sq [o]
|
|
(Maybe.unsafe-from (dot o o)))
|
|
|
|
(doc mag "Get the magnitude of a vector.")
|
|
(defn mag [o]
|
|
(sqrt (mag-sq o)))
|
|
|
|
(doc dist "Get the distance between the vectors a and b.")
|
|
(defn dist [a b]
|
|
(Maybe.apply (sub b a) &(fn [s] (mag &s))))
|
|
|
|
(doc normalize "Normalize a vector.")
|
|
(defn normalize [o]
|
|
(let [m (mag o)]
|
|
(if (zero? m)
|
|
@o
|
|
(div o m))))
|
|
|
|
(doc angle-between "Get the angle between two vectors a and b.")
|
|
(defn angle-between [a b]
|
|
(Maybe.apply (VectorN.dot a b)
|
|
&(fn [x]
|
|
(let [dmm (/ x (* (VectorN.mag a) (VectorN.mag b)))]
|
|
(acos (clamp--1-1 dmm))))))
|
|
|
|
(doc anti-parallel? "Check whether the two vectors a and b are anti-parallel.")
|
|
(defn anti-parallel? [a b]
|
|
(Maybe.apply (angle-between a b) &(fn [x] (= x pi))))
|
|
|
|
(doc parallel? "Check whether the two vectors a and b are parallel.")
|
|
(defn parallel? [a b]
|
|
(Maybe.apply (angle-between a b) &(fn [x] (zero? x))))
|
|
|
|
(doc perpendicular? "Check whether the two vectors a and b are perpendicular.")
|
|
(defn perpendicular? [a b]
|
|
(Maybe.apply (angle-between a b) &(fn [x] (= x (Generics.half-pi)))))
|
|
|
|
(doc vlerp "Linearly interpolate between the two vectors a and b by amnt (between 0 and 1).")
|
|
(defn vlerp [a b amnt]
|
|
(zip (fn [a b] (lerp a b amnt)) a b))
|
|
)
|