;;;; The rest of libm, at both widths — what math.flan and math2.flan left out. ;;;; ;;;; The rule those two set holds here unchanged and is the only reason this ;;;; file looks the way it does: none of these is correctly rounded under ;;;; IEEE-754 except sqrt, fabs, the rounding three and fmod, so every value ;;;; below is one whose answer is exact in binary — zero, one, a power of two, ;;;; a perfect square, a perfect cube. A case that pinned glibc's last bit ;;;; would pass here and fail on wasi-libc. ;;;; ;;;; The acceptance table builds this at -O0 as well, and that run is the one ;;;; that matters: at -O2 LLVM folds a libm call over two literals and leaves ;;;; no symbol to resolve, which is how a missing -lm hid the first time. (defn show [x f32] () (print x) (print " ")) (defn show64 [x f64] () (print x) (print " ")) (defn main [] i32 ;; The f32 half. tan, the three inverses, the three logarithms and exp. (show (tan-f32 0.0)) ; 0 (show (asin-f32 0.0)) ; 0 (show (acos-f32 1.0)) ; 0 (show (atan-f32 0.0)) ; 0 (show (log-f32 1.0)) ; 0 (show (log2-f32 8.0)) ; 3 (show (log10-f32 1000.0)) ; 3 (show (exp-f32 0.0)) ; 1 (println "") (show (fmod-f32 7.0 4.0)) ; 3 ;; The sign follows the dividend and not the divisor, which is the line a ;; caller reaching for a modulo gets wrong. Written down as a case. (show (fmod-f32 -1.0 3.0)) ; -1 (show (hypot-f32 3.0 4.0)) ; 5 (show (cbrt-f32 27.0)) ; 3 ;; The negative root, where (pow-f32 x 0.33333334) would be NaN: pow goes ;; through a logarithm and cbrt does not. (show (cbrt-f32 -8.0)) ; -2 (show (abs-f32 -2.5)) ; 2.5 (println "") ;; The f64 half, at the same exact values. This block is the whole point of ;; the f64 face existing: before it, every one of these was a cast down to ;; f32 and back, and the cast down is where the precision went. (show64 (sqrt-f64 16.0)) ; 4 (show64 (sin-f64 0.0)) ; 0 (show64 (cos-f64 0.0)) ; 1 (show64 (tan-f64 0.0)) ; 0 (show64 (asin-f64 0.0)) ; 0 (show64 (acos-f64 1.0)) ; 0 (show64 (atan-f64 0.0)) ; 0 (show64 (atan2-f64 0.0 1.0)) ; 0 (println "") (show64 (log-f64 1.0)) ; 0 (show64 (log2-f64 1024.0)) ; 10 (show64 (log10-f64 100.0)) ; 2 (show64 (exp-f64 0.0)) ; 1 (show64 (pow-f64 2.0 10.0)) ; 1024 (show64 (fmod-f64 7.0 4.0)) ; 3 (show64 (hypot-f64 3.0 4.0)) ; 5 (show64 (cbrt-f64 8.0)) ; 2 (show64 (abs-f64 -1.5)) ; 1.5 (println "") ;; The f64 rounding family, which is libm's where the f32 one is Flan's — ;; and it agrees with the Flan one where they overlap: half away from zero, ;; so -2.5 goes to -3 and not to -2. (show64 (floor-f64 -2.5)) ; -3 (show64 (ceil-f64 -2.5)) ; -2 (show64 (round-f64 -2.5)) ; -3 (show64 (round-f64 2.5)) ; 3 (println "") ;; Integer magnitude, one per width. (print (abs-i32 -7)) (print " ") ; 7 (print (abs-i64 (i64 -7))) (print " ") ; 7 (print (abs-i32 7)) (print " ") ; 7 ;; tau is 2pi at both widths. Pinning the relation rather than the digits is ;; what catches a constant written to too few of them. (print (= tau-f32 (* 2.0 pi-f32))) (print " ") (print (= tau-f64 (* 2.0 pi-f64))) (println "") ;; pi is the one value here that can be pinned without pinning a libm: it is ;; a literal the compiler rounds, so it is the same on every target. (println (and (> pi-f64 3.14159265) (< pi-f64 3.14159266))) 0)