diff --git a/core/Array.carp b/core/Array.carp index 10903767..d4901f0d 100644 --- a/core/Array.carp +++ b/core/Array.carp @@ -1,5 +1,6 @@ (defmodule Array + (doc reduce "Reduce an array, using the function f.") (defn reduce [f x xs] (let [total x] (do @@ -7,12 +8,15 @@ (set! total (f &total (nth xs i)))) total))) + (doc first "Take the first element of an array.") (defn first [a] @(Array.nth a 0)) + (doc last "Take the last element of an array.") (defn last [a] @(Array.nth a (Int.dec (Array.count a)))) + (defn = "Compare two arrays.") (defn = [a b] (if (/= (count a) (count b)) false @@ -24,6 +28,7 @@ (break)))) eq))) + (doc maximum "Get the maximum in an array (elements must support <).") (defn maximum [xs] (let [result (first xs) n (count xs)] @@ -35,6 +40,7 @@ ()))) result))) + (doc minimum "Get the maximum in an array (elements must support >).") (defn minimum [xs] (let [result (first xs) n (count xs)] @@ -46,9 +52,11 @@ ()))) result))) + (doc minimum "Sum an array (elements must support + and zero).") (defn sum [xs] (Array.reduce add-ref (zero) xs)) + (doc subarray "Get subarray from start-index to end-index.") (defn subarray [xs start-index end-index] (let [result []] (do @@ -56,12 +64,15 @@ (set! result (push-back result @(nth xs i)))) result))) + (doc prefix-array "Get prefix-array to end-index.") (defn prefix-array [xs end-index] (subarray xs 0 end-index)) + (doc suffix-array "Get subarray from start-index.") (defn suffix-array [xs start-index] (subarray xs start-index (count xs))) + (doc reverse "Reverse an array.") (defn reverse [a] (let-do [i 0 j (Int.dec (count &a))] @@ -73,6 +84,7 @@ (set! j (Int.dec j)))) a)) + (doc index-of "Get the index of element e in an array.") (defn index-of [a e] (let-do [idx -1] (for [i 0 (count a)] @@ -82,24 +94,29 @@ (break)))) idx)) + (doc element-count "Count occurrences of element e in an array.") (defn element-count [a e] (let-do [c 0] (for [i 0 (count a)] (when (= e (nth a i)) (set! c (Int.inc c)))) c)) + (doc aupdate "Transmute the element at index i of array a using function f.") (defn aupdate [a i f] (let [new-value (f (nth &a i))] (aset a i new-value))) + (doc aupdate "Transmute the element at index i of array a using function f in place.") (defn aupdate! [a i f] (aset! a i (f (nth a i)))) + (doc aupdate "Swap indices i and j of array a.") (defn swap [a i j] (let [x @(nth &a i) y @(nth &a j)] (aset (aset a i y) j x))) + (doc aupdate "Swap indices i and j of array a in place.") (defn swap! [a i j] (let-do [x @(nth a i) y @(nth a j)] @@ -107,6 +124,7 @@ (aset! a j x))) ; cannot use for, because we want also be able to go downwards + (doc range "Create an array from start to end with step between them (the elements must support <, <=, and >=).") (defn range [start end step] (let-do [x (allocate (Int.inc (Int.abs (/ (- end start) step)))) e start @@ -119,24 +137,29 @@ (set! e (+ e step)))) x)) + (doc sort "Sort an array (the elements must support cmp).") (defn sort [a] (sort-with a cmp)) + (doc repeat "Repeat function f n times and store the results in an array.") (defn repeat [n f] (let-do [a (allocate n)] (for [i 0 n] (aset-uninitialized! &a i (f))) a)) + (doc repeat-indexed "Repeat function f n times and store the results in an array (will be supplied with the index).") (defn repeat-indexed [n f] (let-do [a (allocate n)] (for [i 0 n] (aset-uninitialized! &a i (f i))) a)) + (doc replicate "Repeat element e n times and store the results in an array.") (defn replicate [n e] (let-do [a (allocate n)] (for [i 0 n] (aset-uninitialized! &a i @e)) a)) + (doc copy-map "Map over array a using function f (copies the array).") (defn copy-map [f a] (let-do [na (allocate (count a))] (for [i 0 (count a)] diff --git a/core/Bench.carp b/core/Bench.carp index f88fab01..0b695c05 100644 --- a/core/Bench.carp +++ b/core/Bench.carp @@ -5,12 +5,17 @@ (defmodule Bench (def min-runs 50) + (private min-runs) + (hidden min-runs) + (doc set-min-runs! "Set the minimum number of runs. If your functions takes a large amount of time, experimenting with this might make sense.") (defn set-min-runs! [n] ; / 2 because we run it twice per benchmarking run, ; but this is an implementation detail (set! min-runs (/ n 2))) + (private get-unit) + (hidden get-unit) (defn get-unit [n] (cond (< n 1000.0) (String.append (Double.str n) @"ns") @@ -18,18 +23,24 @@ (< n 1000000000.0) (String.append (Double.str (/ n 1000000.0)) @"ms") (String.append (Double.str (/ n 1000000000.0)) @"s"))) + (private print) + (hidden print) (defn print [title n] (let [unit (get-unit n)] (do (IO.print title) (IO.println &unit)))) + (private ns-iter-inner) + (hidden ns-iter-inner) (defn ns-iter-inner [f n] (let [start (get-time-elapsed)] (do (for [i 0 n] (ignore (f))) (Double.- (get-time-elapsed) start)))) + (private print-bench-results) + (hidden print-bench-results) (defn print-bench-results [res total] (do (print "Total time elapsed: " total) @@ -37,6 +48,8 @@ (print "Worst case: " @(Statistics.Summary.max res)) (print "Standard deviation: " @(Statistics.Summary.stdev res)))) + (private get-samples) + (hidden get-samples) (defn get-samples [f n] (let [zero 0.0 samples (Array.replicate min-runs &zero)] @@ -45,11 +58,14 @@ (Array.aset! &samples i (Double./ (ns-iter-inner f (Double.to-int n)) n))) (Statistics.summary &(Statistics.winsorize &samples 5.0))))) + (private min-one) + (hidden min-one) (defn min-one [n] (if (> 1.0 n) n 1.0)) ; it is actually possible to make this run forever by supplying a _really_ ; long-running function, where long-running is everything over 30ms. + (doc bench "Benchmark function f and print the results.") (defn bench [f] (let [ns (ns-iter-inner f 1) ns-target-total 1000000.0 diff --git a/core/Char.carp b/core/Char.carp index 4955d195..cb97e075 100644 --- a/core/Char.carp +++ b/core/Char.carp @@ -6,6 +6,7 @@ (register from-int (Fn [Int] Char)) (register copy (Fn [&Char] Char)) + (doc meaning "Convert a numerical char into the appropriate number.") (defn meaning [char-ref] (cond (= @char-ref \0) 0 diff --git a/core/Debug.carp b/core/Debug.carp index cef4f931..264b0b36 100644 --- a/core/Debug.carp +++ b/core/Debug.carp @@ -2,6 +2,7 @@ (defmodule Debug + (doc sanitize-addresses "Instruct the compiler to sanitize addresses.") (defdynamic sanitize-addresses [] (add-cflag "-fsanitize=address")) @@ -9,14 +10,14 @@ (register reset-memory-balance! (Fn [] ())) (register log-memory-balance! (Fn [Bool] ())) - ;; The calls inside the form will be logged to stdout. Requires compiling with --log-memory. + (doc memory-logged "Log all calls to memory allocation within te form. Requires compiling with --log-memory.") (defmacro memory-logged [form] (list 'do '(Debug.log-memory-balance! true) form '(Debug.log-memory-balance! false))) - ;; Raises an error if the memory balance (nr of alloc:s minus nr of free:s) isn't 0. Requires compiling with --log-memory. + (doc assert-balanced "Raises an error if the memory balance (numberr of alloc:s - number of free:s) isn't 0. Requires compiling with --log-memory.") (defmacro assert-balanced [form] (list 'let '[balance (Debug.memory-balance)] (list 'do @@ -28,16 +29,17 @@ (System.exit 1))) ()))) - ;; Print the value of an expression to stdout, then return its value. + (doc trace "Print the value of an expression to stdout, then return its value.") (defn trace [x] (do (IO.println &(str &x)) x)) - ;; Leak some memory. Useful for testing tools that detect leaks. + (doc leak-array "Leak some memory. Useful for testing tools that detect leaks.") (register leak-array (Fn [a] ()) "Debug_leak_MINUS_array") ) +) ;; HACK! This silences compiler errors about 'source-location' and 'source-path' being undefined. ;; Actual calls to these special forms will be handled directly in the dynamic evaluator, see 'Eval.hs'.