sx primitives: add trig/transcendental/bit-op math helpers
Adds sin/cos/tan + inverse + hyperbolic + inverse-hyperbolic, log/log2/log10/log1p, exp/expm1, cbrt, hypot (variadic), sign, fround/clz32/imul. All one-liners over Float.* / Int32.*. Needed by JS-on-SX to unblock built-ins/Math tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -144,6 +144,90 @@ let () =
|
||||
register "pow" (fun args ->
|
||||
match args with [a; b] -> Number (as_number a ** as_number b)
|
||||
| _ -> raise (Eval_error "pow: 2 args"));
|
||||
register "cbrt" (fun args ->
|
||||
match args with [a] -> Number (Float.cbrt (as_number a)) | _ -> raise (Eval_error "cbrt: 1 arg"));
|
||||
register "exp" (fun args ->
|
||||
match args with [a] -> Number (Float.exp (as_number a)) | _ -> raise (Eval_error "exp: 1 arg"));
|
||||
register "expm1" (fun args ->
|
||||
match args with [a] -> Number (Float.expm1 (as_number a)) | _ -> raise (Eval_error "expm1: 1 arg"));
|
||||
register "log" (fun args ->
|
||||
match args with [a] -> Number (Float.log (as_number a)) | _ -> raise (Eval_error "log: 1 arg"));
|
||||
register "log2" (fun args ->
|
||||
match args with [a] -> Number (Float.log (as_number a) /. Float.log 2.0) | _ -> raise (Eval_error "log2: 1 arg"));
|
||||
register "log10" (fun args ->
|
||||
match args with [a] -> Number (Float.log10 (as_number a)) | _ -> raise (Eval_error "log10: 1 arg"));
|
||||
register "log1p" (fun args ->
|
||||
match args with [a] -> Number (Float.log1p (as_number a)) | _ -> raise (Eval_error "log1p: 1 arg"));
|
||||
register "sin" (fun args ->
|
||||
match args with [a] -> Number (Float.sin (as_number a)) | _ -> raise (Eval_error "sin: 1 arg"));
|
||||
register "cos" (fun args ->
|
||||
match args with [a] -> Number (Float.cos (as_number a)) | _ -> raise (Eval_error "cos: 1 arg"));
|
||||
register "tan" (fun args ->
|
||||
match args with [a] -> Number (Float.tan (as_number a)) | _ -> raise (Eval_error "tan: 1 arg"));
|
||||
register "asin" (fun args ->
|
||||
match args with [a] -> Number (Float.asin (as_number a)) | _ -> raise (Eval_error "asin: 1 arg"));
|
||||
register "acos" (fun args ->
|
||||
match args with [a] -> Number (Float.acos (as_number a)) | _ -> raise (Eval_error "acos: 1 arg"));
|
||||
register "atan" (fun args ->
|
||||
match args with [a] -> Number (Float.atan (as_number a)) | _ -> raise (Eval_error "atan: 1 arg"));
|
||||
register "atan2" (fun args ->
|
||||
match args with [a; b] -> Number (Float.atan2 (as_number a) (as_number b))
|
||||
| _ -> raise (Eval_error "atan2: 2 args"));
|
||||
register "sinh" (fun args ->
|
||||
match args with [a] -> Number (Float.sinh (as_number a)) | _ -> raise (Eval_error "sinh: 1 arg"));
|
||||
register "cosh" (fun args ->
|
||||
match args with [a] -> Number (Float.cosh (as_number a)) | _ -> raise (Eval_error "cosh: 1 arg"));
|
||||
register "tanh" (fun args ->
|
||||
match args with [a] -> Number (Float.tanh (as_number a)) | _ -> raise (Eval_error "tanh: 1 arg"));
|
||||
register "asinh" (fun args ->
|
||||
match args with [a] -> Number (Float.asinh (as_number a)) | _ -> raise (Eval_error "asinh: 1 arg"));
|
||||
register "acosh" (fun args ->
|
||||
match args with [a] -> Number (Float.acosh (as_number a)) | _ -> raise (Eval_error "acosh: 1 arg"));
|
||||
register "atanh" (fun args ->
|
||||
match args with [a] -> Number (Float.atanh (as_number a)) | _ -> raise (Eval_error "atanh: 1 arg"));
|
||||
register "hypot" (fun args ->
|
||||
let square x = x *. x in
|
||||
let sum = List.fold_left (fun acc a -> acc +. square (as_number a)) 0.0 args in
|
||||
Number (Float.sqrt sum));
|
||||
register "sign" (fun args ->
|
||||
match args with
|
||||
| [a] ->
|
||||
let n = as_number a in
|
||||
Number (if Float.is_nan n then Float.nan
|
||||
else if n > 0.0 then 1.0
|
||||
else if n < 0.0 then -1.0
|
||||
else n)
|
||||
| _ -> raise (Eval_error "sign: 1 arg"));
|
||||
register "fround" (fun args ->
|
||||
match args with [a] -> Number (Int32.float_of_bits (Int32.bits_of_float (as_number a)))
|
||||
| _ -> raise (Eval_error "fround: 1 arg"));
|
||||
register "clz32" (fun args ->
|
||||
match args with
|
||||
| [a] ->
|
||||
let n = as_number a in
|
||||
let i = if Float.is_nan n || Float.is_infinite n then 0l
|
||||
else Int32.of_float (Float.rem n 4294967296.0) in
|
||||
if i = 0l then Number 32.0
|
||||
else
|
||||
let high_bit = Int32.shift_left 1l 31 in
|
||||
let count = ref 0 in
|
||||
let x = ref i in
|
||||
while Int32.logand !x high_bit = 0l do
|
||||
incr count;
|
||||
x := Int32.shift_left !x 1
|
||||
done;
|
||||
Number (float_of_int !count)
|
||||
| _ -> raise (Eval_error "clz32: 1 arg"));
|
||||
register "imul" (fun args ->
|
||||
match args with
|
||||
| [a; b] ->
|
||||
let tou32 f =
|
||||
if Float.is_nan f || Float.is_infinite f then 0l
|
||||
else Int32.of_float (Float.rem f 4294967296.0) in
|
||||
let ai = tou32 (as_number a) and bi = tou32 (as_number b) in
|
||||
let r = Int32.mul ai bi in
|
||||
Number (Int32.to_float r)
|
||||
| _ -> raise (Eval_error "imul: 2 args"));
|
||||
register "clamp" (fun args ->
|
||||
match args with
|
||||
| [x; lo; hi] ->
|
||||
|
||||
Reference in New Issue
Block a user