Math Function Backends
Arithmetic and comparison operators work on both integers and doubles. When any operand is a double, the result is promoted to double (e.g., (+ 1 1.5) returns 2.5). +, -, *, / accept two or more arguments. mod supports doubles in the interpreter and JVM compiler but not in the WASM compiler.
Math function backend support
The math built-ins differ in how widely they are supported, because the WASM backend only has native instructions for a few operations:
sqrt,isqrt,gcd,lcm,signum,exptare supported on all three backends (interpreter, JVM, WASM) and through the compiledeval.sqrtuses the nativef64.sqrtinstruction.expis supported on all three backends. The interpreter and JVM useMath.exp; WASM has no native transcendental instruction, so it emits a software approximation in f64 (argument reduction by repeated squaring plus a Taylor polynomial), accurate to roughly 1e-6 relative error. The WASM result is therefore close to but not bit-identical toMath.exp((exp 0)is exactly1.0). This is enough to run, e.g., a sigmoid(/ 1.0 (+ 1.0 (exp (- 0 x))))compiled to WASM.logandtanhare supported on all three backends the same way asexp: the interpreter and JVM useMath.log/Math.tanh, and WASM emits software approximations --logextracts the binary exponent and evaluates a short polynomial series on the normalized mantissa (ln(x) = e*ln(2) + ln(m)), andtanhis derived from the softwareexpas(e^(2x)-1)/(e^(2x)+1)with the argument clamped so large inputs saturate to exactly±1.0. Both match the interpreter/JVM values closely but not bit-identically ((log 1)and(tanh 0)are exactly0.0). The IEEE edges oflogmatchMath.log(log(0.0)is-Infinity, a negative argument isNaN); WASM's(tanh -0.0)is0.0where the interpreter and JVM keep-0.0, the same class of edge as the WASMsignum.sin,cosandtanare supported on all three backends the same way: the interpreter and JVM useMath.sin/Math.cos/Math.tan, and WASM emits a software approximation -- Cody-Waite argument reduction (k = nearest(x * 2/pi),r = x - k*pi/2via a two-part split ofpi/2, the quadrantk mod 4selecting the sign/swap) plus Taylor polynomials forsin(r)/cos(r)on the reduced argument;tanis their ratio. Accuracy is ~1e-11 relative for|x|up to about1e6, after which the reduction's absolute error grows with the argument (documented likeexp's low-digit divergence; beyond|x| > 2^30a crude fold keeps the result finite but the value progressively loses significance, where the JVM's argument reduction stays exact). The zero and quadrant anchors are exact ((sin 0)is0.0,(cos 0)is1.0,(sin (/ pi 2))is1.0,(cos pi)is-1.0), andNaN/±Infinityarguments giveNaNeverywhere; WASM's(sin -0.0)and(tan -0.0)are0.0where the interpreter and JVM keep-0.0, the same class of edge as the WASMsignumandtanh.asin,acosandatanare supported on all three backends: the interpreter and JVM useMath.asin/Math.acos/Math.atan, and WASM emits a software approximation --atanfolds the argument by its odd symmetry, by the reciprocal identityatan(x) = pi/2 - atan(1/x)for|x| > 1(which also maps±Infinityto±pi/2for free), and by two half-angle steps, then evaluates a short Taylor series (~1e-15 relative error over the whole range);asin(x) = atan(x / sqrt((1-x)(1+x)))andacos(x) = 2*atan(sqrt((1-x)/(1+x)))derive from it.(atan 0),(asin 0)and(acos 1)are exactly0.0,(asin ±1)is exactly±pi/2and(acos -1)exactlypi; anasin/acosargument outside[-1, 1]isNaNeverywhere.sinhandcoshare supported on all three backends: the interpreter and JVM useMath.sinh/Math.cosh, and WASM derives both from the softwareexp--e = exp(|x|), then(e - 1/e)/2with the sign restored, or(e + 1/e)/2. For tiny arguments the subtraction would cancel, sosinhswitches to its odd Taylor series below|x| = 0.25. Accuracy follows the softwareexp: ~1e-7 relative for|x|up to ~20, degrading as the argument grows (likeexp's own divergence), and overflowing toInfinityslightly later than the JVM's 710.5.(sinh 0)is exactly0.0and(cosh 0)exactly1.0;(sinh ±Infinity)is±Infinityand(cosh ±Infinity)isInfinityeverywhere. With these, every transcendental built-in now works on all three backends.exptkeeps an exact rational result for an integer or ratio base raised to an integer exponent (with big-integer promotion in the interpreter and JVM); a negative exponent yields the reciprocal ((expt 2 -1)is1/2) and a float base/exponent usesMath.powand returns a float. The WASMexpt, like all WASM integer arithmetic, uses 31-bit values with no overflow promotion.isqrt,gcd,lcm,signumoperate on the i31 integer range in the WASM backend (no big-integer promotion); the interpreter and JVM promote to big integers as needed.randomis supported on all three backends. It returns a non-negative random number below the (positive) limit, of the same type as the limit (an integer limit yields an integer, a float limit a float). The integer and float paths are chosen from the literal shape of the argument, so use a float literal ((random 1.0)) when a float result is wanted. The interpreter and JVM draw fromMath.random(); the WASM backend draws real entropy from the WASIrandom_gethost function (the realwasi_snapshot_preview1.random_getin Preview 1 mode,wasi:random@0.3.0in--componentmode), so the sequence differs each run.randomis not available inside the compiledeval.logand,logior,logxor,lognot,ashare supported on all three backends. The interpreter and JVM compute on exactBigIntegervalues (ashshifts left for a non-negative count, right otherwise); the WASM backend uses the i31 integer range, so a result that overflows 31 bits is truncated.