The trio the author decided on 2026-09-20 is now all built: def is CL's defparameter — its initialiser runs on every daemon re-run, unguarded, so an edited initialiser repaints the same storage on C-c C-c plus re-run — defonce (Clojure's name for CL's defvar, per the author) initialises once behind the .init~once. flag, and defconst stays the image. One parse arm reads both forms; the difference is Ast.reinit, carried to Tast.global's grerun. Emit.startup_plan gives a def no guard flag, and Check.check_global lifts every def initialiser — zero and literal included — into global/<n>, so the host's startup reaches it through the function cell and a re-evaluated def swaps it (Session's def_inits; Emit.redefinition declares the cell for a non-sibling target). The old defvar spelling is refused with the rename and both compiling spellings, and every program, test, doc and editor list is swept — except sand.flan, the author's live WIP, whose seven defvar lines are flagged in FIX.org and keep its three dependent tests red on this branch.
79 lines
3.2 KiB
Plaintext
79 lines
3.2 KiB
Plaintext
;;;; atan2, pow, and clamp — the three gaps NEXT.md's second-tier list names
|
|
;;;; under "maths gaps".
|
|
;;;;
|
|
;;;; Two of them are declares over libm and the third is a macro, and that
|
|
;;;; split is the whole content of this file. atan2f and powf are not correctly
|
|
;;;; rounded under IEEE-754, exactly as sinf and cosf are not, so every case
|
|
;;;; below is a value whose answer is exact in binary — a quadrant boundary, a
|
|
;;;; power of two, a perfect square — rather than one that would pin a
|
|
;;;; particular libm's last bit and then fail on wasi-libc.
|
|
;;;;
|
|
;;;; clamp is a macro because a function could not be: min and max are builtins
|
|
;;;; at every numeric type and there are no generics, so a clamp function is
|
|
;;;; one copy per type. The proof that the macro is not one copy per type is
|
|
;;;; that the same three-word call below is made at i32, i64, u8 and f32.
|
|
|
|
(defn show [x f32] ()
|
|
(print x)
|
|
(print " "))
|
|
|
|
;;; clamp must evaluate each of its three arguments exactly once. A macro that
|
|
;;; repeated one — say (if (< x lo) lo (if (> x hi) hi x)), which names x twice
|
|
;;; — would read identically and call this twice.
|
|
(defonce calls i32 0)
|
|
|
|
(defn tick [x i32] i32
|
|
(set calls (+ calls 1))
|
|
x)
|
|
|
|
(defn main [] i32
|
|
;; atan2 across all four quadrants and on both axes, which is the whole
|
|
;; reason for it over a division: the quadrant is recovered from two signs,
|
|
;; and (/ y x) has thrown it away before atan sees it. The two on the x = 0
|
|
;; axis are where the division does not exist at all.
|
|
(show (atan2-f32 1.0 1.0)) ; pi/4
|
|
(show (atan2-f32 1.0 -1.0)) ; 3pi/4
|
|
(show (atan2-f32 -1.0 -1.0)) ; -3pi/4
|
|
(show (atan2-f32 -1.0 1.0)) ; -pi/4
|
|
(show (atan2-f32 0.0 1.0)) ; 0
|
|
(show (atan2-f32 1.0 0.0)) ; pi/2
|
|
(show (atan2-f32 -1.0 0.0)) ; -pi/2
|
|
(println "")
|
|
|
|
;; pow. A power of two, a half-power that is a perfect square, a negative
|
|
;; exponent, and the two edge exponents every implementation special-cases.
|
|
(show (pow-f32 2.0 10.0)) ; 1024
|
|
(show (pow-f32 9.0 0.5)) ; 3
|
|
(show (pow-f32 2.0 -2.0)) ; 0.25
|
|
(show (pow-f32 5.0 0.0)) ; 1
|
|
(show (pow-f32 5.0 1.0)) ; 5
|
|
(println "")
|
|
|
|
;; clamp: below the range, above it, and inside it untouched.
|
|
(print (clamp 0 1 3)) (print " ") ; 1
|
|
(print (clamp 5 1 3)) (print " ") ; 3
|
|
(print (clamp 2 1 3)) (print " ") ; 2
|
|
;; Both ends are inclusive, which is the off-by-one a hand-written clamp
|
|
;; gets wrong with a < where it wanted <=.
|
|
(print (clamp 1 1 3)) (print " ") ; 1
|
|
(print (clamp 3 1 3)) ; 3
|
|
(println "")
|
|
|
|
;; The same three words at three more types, none of which a function could
|
|
;; have served without a copy of its own.
|
|
(print (clamp (i64 900) (i64 0) (i64 255))) (print " ") ; 255
|
|
(print (clamp (u8 200) (u8 0) (u8 255))) (print " ") ; 200
|
|
(show (clamp 2.5 0.0 1.0)) ; 1
|
|
(println "")
|
|
|
|
;; lo above hi is not an error and answers hi: the outer min wins. Written
|
|
;; down here rather than left for someone to discover.
|
|
(print (clamp 7 5 1))
|
|
(println "")
|
|
|
|
;; Three arguments, three evaluations.
|
|
(print (clamp (tick 5) (tick 1) (tick 3))) (print " ")
|
|
(print calls)
|
|
(println "")
|
|
0)
|