;;;; The prelude's rounding, and sqrt. ;;;; ;;;; Every input is one a plausible wrong implementation gets wrong. The ;;;; negatives are the whole point: a floor written as a bare cast truncates ;;;; toward zero and answers -2 for -2.5, and a round written as ;;;; (floor-f32 (+ x 0.5)) answers -2 for -2.5 as well, where C's round says ;;;; -3. The exact halves appear on both signs for that reason. The values ;;;; that are already integers check that the correction does *not* fire — ;;;; a floor that always subtracts one turns 3.0 into 2.0 — and 16777216.0 is ;;;; past 2^24, where an f32 has no fractional bits and the guard, not the ;;;; cast, has to produce the answer. (defn show [x f32] (print-f64 (f64 x)) (print-str " ")) (defn main [] i32 ;; floor: down on both signs, and unmoved on the integers. (show (floor-f32 2.7)) (show (floor-f32 2.0)) (show (floor-f32 2.3)) (show (floor-f32 -2.7)) (show (floor-f32 -2.0)) (show (floor-f32 -2.3)) (show (floor-f32 0.5)) (show (floor-f32 -0.5)) (newline) ;; ceil: up on both signs. -2.7 must give -2, which is where a ceil written ;; as "floor plus one" goes wrong. (show (ceil-f32 2.7)) (show (ceil-f32 2.0)) (show (ceil-f32 2.3)) (show (ceil-f32 -2.7)) (show (ceil-f32 -2.0)) (show (ceil-f32 -2.3)) (show (ceil-f32 0.5)) (show (ceil-f32 -0.5)) (newline) ;; Zero keeps its sign through floor, which is what the (= x 0.0) guard in ;; it is for and the only place that guard is observable: the cast it skips ;; would turn -0.0 into +0.0, and %g prints the difference. Drop the guard ;; and the third column here reads 0 instead of -0. (show (floor-f32 0.0)) (show (ceil-f32 0.0)) (show (floor-f32 -0.0)) (newline) ;; round: half away from zero on both signs, so -2.5 is -3 and not -2. (show (round-f32 2.4)) (show (round-f32 2.5)) (show (round-f32 2.6)) (show (round-f32 -2.4)) (show (round-f32 -2.5)) (show (round-f32 -2.6)) (show (round-f32 0.5)) (show (round-f32 -0.5)) (newline) ;; Past 2^24 there is no fraction left; the answer is the input, and the ;; cast that would produce it is out of i32's range on the way there. (show (floor-f32 16777216.0)) (show (ceil-f32 16777216.0)) (show (round-f32 16777216.0)) (show (floor-f32 -16777216.0)) (newline) ;; sqrt, including the two values a wrong-sense iteration still passes ;; (0 and 1) and one that is not a perfect square. (show (sqrt-f32 0.0)) (show (sqrt-f32 1.0)) (show (sqrt-f32 4.0)) (show (sqrt-f32 2.0)) (show (sqrt-f32 0.25)) (show (sqrt-f32 1e6)) (newline) ;; A squared distance through sqrt, which is what a game actually calls it ;; for: 3-4-5 exactly, so a last-bit error would show. (show (sqrt-f32 (+ (* 3.0 3.0) (* 4.0 4.0)))) (newline) 0)