core: initial documentation work

This commit is contained in:
hellerve 2018-03-29 11:36:42 +02:00
parent 7755cd8e1f
commit b2c57e16d3
4 changed files with 46 additions and 4 deletions

View File

@ -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)]

View File

@ -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

View File

@ -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

View File

@ -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'.