diff --git a/core/Statistics.carp b/core/Statistics.carp index fe3b226a..8d344142 100644 --- a/core/Statistics.carp +++ b/core/Statistics.carp @@ -17,9 +17,11 @@ iqr Double ]) + (doc mean "Compute the mean of the samples data.") (defn mean [data] (/ (Array.sum data) (from-int (Array.length data)))) + (hidden _pp) (defn _pp [a mean] (let [sum 0.0] (do @@ -28,6 +30,7 @@ (set! sum (Double.* tmp tmp)))) sum))) + (hidden _xx) (defn _xx [a mean] (let [sum 0.0] (do @@ -35,6 +38,7 @@ (set! sum (Double.- (Double.copy (Array.nth a i)) mean))) sum))) + (hidden _ss) (defn _ss [data] (let [m (mean data) tmp (_xx data m)] @@ -42,6 +46,7 @@ (Double./ (Double.* tmp tmp) (Double.from-int (Array.length data)))))) + (doc median "Compute the median of the samples data.") (defn median [data] (let [n (Array.length data) sorted (Array.sort @data)] @@ -52,6 +57,7 @@ @(Array.nth data mid)) 2.0))))) + (doc low-median "Compute the low median of the samples data.") (defn low-median [data] (let [n (Array.length data) sorted (Array.sort @data)] @@ -59,6 +65,7 @@ (= (mod n 2) 1) @(Array.nth data (/ n 2)) @(Array.nth data (dec (/ n 2)))))) ; else + (doc high-median "Compute the high median of the samples data.") (defn high-median [data] (let [n (Array.length data) sorted (Array.sort @data)] @@ -66,6 +73,7 @@ 0.0 @(Array.nth data (/ n 2))))) + (doc grouped-median "Compute the grouped median of the samples data.") (defn grouped-median [data interval] (let [n (Array.length data) sorted (Array.sort @data)] @@ -78,25 +86,31 @@ (+ l (/ (* (from-int interval) (- (/ (from-int n) 2.0) (from-int cf))) (from-int f))))))) + (doc variance "Compute the variance of the samples data.") (defn variance [data] (let [n (Array.length data) ss (_ss data)] (/ ss (from-int (dec n))))) + (doc pvariance "Compute the population variance of the samples data.") (defn pvariance [data] (let [n (Array.length data) ss (_ss data)] (/ ss (from-int n)))) + (doc stdev "Compute the standard deviation of the samples data.") (defn stdev [data] (Double.sqrt (variance data))) + (doc pstdev "Compute the population standard deviation of the samples data.") (defn pstdev [data] (Double.sqrt (pvariance data))) + (doc pstdev-pct "Compute the standard deviation of the samples data as a percentile.") (defn stdev-pct [data] (* (/ (stdev data) (mean data)) 100.0)) + (hidden median-abs-dev) (defn median-abs-dev [data] (let [med (median data) zero 0.0 @@ -107,9 +121,11 @@ (Array.aset! &abs-devs i (abs (- med @(Array.nth data i))))) (* (median &abs-devs) n)))) + (hidden median-abs-dev-pct) (defn median-abs-dev-pct [data] (* (/ (median-abs-dev data) (median data)) 100.0)) + (hidden percentile-of-sorted) (defn percentile-of-sorted [sorted pct] (cond (Int.= 0 (Array.length sorted)) -1.0 ; should abort here @@ -126,6 +142,7 @@ hi @(Array.nth sorted (Int.inc n))] (Double.+ lo (Double.* d (Double.- hi lo)))))) + (doc quartiles "Compute the quartiles of the samples data.") (defn quartiles [data] (let [tmp (Array.sort @data) first 25.0 @@ -136,10 +153,12 @@ c (percentile-of-sorted &tmp third)] [a b c])) + (doc iqr "Compute the interquartile range.") (defn iqr [data] (let [s &(quartiles data)] (the Double (- @(Array.nth s 2) @(Array.nth s 0))))) + (hidden winsorize) (defn winsorize [samples pct] (let [tmp &(Array.sort @samples) lo (Statistics.percentile-of-sorted tmp pct) @@ -153,6 +172,7 @@ ()))) (Array.copy tmp)))) + (doc summary "Compute a variety of statistical values from a list of samples.") (defn summary [samples] (Summary.init (Array.sum samples) @@ -167,5 +187,4 @@ (median-abs-dev-pct samples) (quartiles samples) (iqr samples))) - ) diff --git a/core/Test.carp b/core/Test.carp index 5c0b8537..7692f24f 100644 --- a/core/Test.carp +++ b/core/Test.carp @@ -1,4 +1,5 @@ (defmodule IO + (hidden color-table) (def color-table [[@"black" @"30"] [@"red" @"31"] @@ -24,8 +25,10 @@ [@"bg-cyan" @"46"] [@"bg-white" @"47"]]) + (hidden len-color-table) (def len-color-table (Array.length &color-table)) + (hidden color-name-to-ansi) (defn color-name-to-ansi [cname] (let [res @""] (do @@ -35,7 +38,7 @@ ())) (StringCopy.append @"\x1b[" (StringCopy.append res @"m"))))) - + (hidden color) (defn color [cname] (print &(color-name-to-ansi cname))) ) @@ -43,6 +46,7 @@ (defmodule Test (deftype State [passed Int, failed Int]) + (hidden handler) (defn handler [state expected actual descr what op] (if (op expected actual) (do @@ -59,24 +63,31 @@ (IO.color "reset") (State.update-failed (State.copy state) Int.inc)))) + (doc assert-op "Assert that op returns true when given x and y.") (defn assert-op [state x y descr op] (handler state x y descr "value" op)) + (doc assert-equal "Assert that x and y are equal. Equality needs to be implemented for their type.") (defn assert-equal [state x y descr] (handler state x y descr "value" =)) + (doc assert-not-equal "Assert that x and y are not equal. Equality needs to be implemented for their type.") (defn assert-not-equal [state x y descr] (handler state x y descr "not value" /=)) + (doc assert-true "Assert that x is true.") (defn assert-true [state x descr] (assert-equal state true x descr)) + (doc assert-false "Assert that x is false.") (defn assert-false [state x descr] (assert-equal state false x descr)) + (doc reset "Reset test state.") (defn reset [state] (State.set-failed (State.set-passed state 0) 0)) + (hidden run-child) (defn run-child [x] (let [pid (System.fork) status 0] @@ -88,8 +99,10 @@ (ignore (System.wait (address status))) (System.get-exit-status status))))) + (hidden handle-signal) (defn handle-signal [x] (System.exit x)) + (hidden run-child-signals) (defn run-child-signals [x] (let [pid (System.fork) status 0] @@ -106,12 +119,15 @@ (ignore (System.wait (address status))) (System.get-exit-status status))))) - (defn assert-exit [state exit-code x descr] - (assert-equal state exit-code (run-child x) descr)) + (doc assert-exit "Assert that function f exits with exit code exit-code.") + (defn assert-exit [state exit-code f descr] + (assert-equal state exit-code (run-child f) descr)) + (doc assert-exit "Assert that function f aborts with OS signal signal.") (defn assert-signal [state signal x descr] (assert-equal state signal (run-child-signals x) descr)) + (doc print-test-results "Print test results.") (defn print-test-results [state] (let [passed @(State.passed state) failed @(State.failed state)] diff --git a/core/Vector.carp b/core/Vector.carp index ccbf4aaa..9f8f182d 100644 --- a/core/Vector.carp +++ b/core/Vector.carp @@ -48,53 +48,66 @@ (defn /= [a b] (not (= a b))) + (doc approx "Check whether the vectors a and b are approximately equal.") (defn approx [a b] (and (Double.approx @(V2.x a) @(V2.x b)) (Double.approx @(V2.y a) @(V2.y b)))) + (doc mag-sq "Get the squared magnitude of a vector.") (defn mag-sq [o] (let [x @(V2.x o) y @(V2.y o)] (+ (* x x) (* y y)))) + (doc mag "Get the magnitude of a vector.") (defn mag [o] (Double.sqrt (mag-sq o))) + (doc normalize "Normalize a vector.") (defn normalize [o] (let [m (mag o)] (if (= m 0.0) (V2.copy 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] (Double.atan2 @(V2.y a) @(V2.x a))) + (doc rotate "Rotate the vector a by the radians n.") (defn rotate [a n] (let [h (+ (heading a) n) m (mag a)] (V2.init (* (Double.cos h) m) (* (Double.sin h) m)))) + (doc dot "Get the dot product of the two vectors x and y.") (defn dot [x y] (+ (* @(V2.x x) @(V2.x y)) (* @(V2.y x) @(V2.y y)))) + (doc angle-between "Get the angle between to vectors a and b.") (defn angle-between [a b] (let [dmm (/ (dot a b) (* (mag a) (mag b)))] (Double.acos (Double.clamp -1.0 1.0 dmm)))) + (doc anti-parallel? "Check whether the two vectors a and b are anti-parallel.") (defn anti-parallel? [a b] (= (angle-between a b) Double.pi)) + (doc parallel? "Check whether the two vectors a and b are parallel.") (defn parallel? [a b] (= (angle-between a b) 0.0)) + (doc perpendicular? "Check whether the two vectors a and b are perpendicular.") (defn perpendicular? [a b] (= (angle-between a b) (/ Double.pi 2.0))) + (doc lerp "Linearly interpolate between the two vectors a and b by amnt (between 0 and 1).") (defn lerp [a b amnt] (init (* (- @(V2.x b) @(V2.x a)) amnt) (* (- @(V2.y b) @(V2.y a)) amnt))) @@ -144,21 +157,25 @@ (/ @(V3.y a) n) (/ @(V3.z a) n))) + (doc mag-sq "Get the squared magnitude of a vector.") (defn mag-sq [o] (let [x @(V3.x o) y @(V3.y o) z @(V3.z o)] (+ (* x x) (+ (* y y) (* z z))))) + (doc mag "Get the magnitude of a vector.") (defn mag [o] (Double.sqrt (mag-sq o))) + (doc normalize "Normalize a vector.") (defn normalize [o] (let [m (mag o)] (if (= m 0.0) (V3.copy o) (div o m)))) + (doc cross "Compute the cross product of the two vectors x and y.") (defn cross [x y] (V3.init (- (* @(V3.y x) @(V3.z y)) @@ -168,24 +185,30 @@ (- (* @(V3.x x) @(V3.y y)) (* @(V3.y x) @(V3.x y))))) + (doc dot "Get the dot product of the two vectors x and y.") (defn dot [x y] (+ (* @(V3.x x) @(V3.x y)) (+ (* @(V3.y x) @(V3.y y)) (* @(V3.z x) @(V3.z y))))) + (doc angle-between "Get the angle between to vectors a and b.") (defn angle-between [a b] (let [dmm (/ (dot a b) (* (mag a) (mag b)))] (Double.acos (Double.clamp -1.0 1.0 dmm)))) + (doc anti-parallel? "Check whether the two vectors a and b are anti-parallel.") (defn anti-parallel? [a b] (= (angle-between a b) Double.pi)) + (doc parallel? "Check whether the two vectors a and b are parallel.") (defn parallel? [a b] (= (angle-between a b) 0.0)) + (doc perpendicular? "Check whether the two vectors a and b are perpendicular.") (defn perpendicular? [a b] (= (angle-between a b) (/ Double.pi 2.0))) + (doc lerp "Linearly interpolate between the two vectors a and b by amnt (between 0 and 1).") (defn lerp [a b amnt] (init (* (- @(V3.x b) @(V3.x a)) amnt) (* (- @(V3.y b) @(V3.y a)) amnt) @@ -252,38 +275,48 @@ (defn add- [x y] (+ @x @y)) + (doc mag-sq "Get the squared magnitude of a vector.") (defn mag-sq [o] (Array.reduce add- 0.0 &(Array.copy-map square- (VN.v o)))) + (doc mag "Get the magnitude of a vector.") (defn mag [o] (Double.sqrt (mag-sq o))) + (doc dist "Get the distance between the vectors a and b.") (defn dist [a b] (let [s (sub b a)] (mag &s))) + (doc normalize "Normalize a vector.") (defn normalize [o] (let [m (mag o)] (if (= m 0.0) (VN.copy o) (div o m)))) + (doc dot "Get the dot product of the two vectors x and y.") (defn dot [x y] (Array.reduce add- 0.0 (VN.v &(zip * x y)))) + (doc angle-between "Get the angle between to vectors a and b.") (defn angle-between [a b] (let [dmm (/ (dot a b) (* (mag a) (mag b)))] (Double.acos (Double.clamp -1.0 1.0 dmm)))) + (doc anti-parallel? "Check whether the two vectors a and b are anti-parallel.") (defn anti-parallel? [a b] (= (angle-between a b) Double.pi)) + (doc parallel? "Check whether the two vectors a and b are parallel.") (defn parallel? [a b] (= (angle-between a b) 0.0)) + (doc perpendicular? "Check whether the two vectors a and b are perpendicular.") (defn perpendicular? [a b] (= (angle-between a b) (/ Double.pi 2.0))) + (doc lerp "Linearly interpolate between the two vectors a and b by amnt (between 0 and 1).") (defn lerp [a b amnt] (init @(VN.n a) @(VN.v &(zip- * &(Array.replicate @(VN.n a) &amnt) (VN.v &(zip - b a))))))