Step 8: numeric tower — exact/inexact predicates + truncate/remainder/modulo
7 new R7RS primitives on the float-based tower (Number of float unchanged): - exact? / inexact? — integer detection via Float.is_integer - exact->inexact / inexact->exact — identity / round-to-integer - truncate — toward zero (floor for positive, ceil for negative) - remainder — sign follows dividend (= Float.rem) - modulo — sign follows divisor 8 new tests (2658/2658 pass). No type system, VM, compiler, or parser changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -150,6 +150,35 @@ let () =
|
||||
let x = as_number x and lo = as_number lo and hi = as_number hi in
|
||||
Number (Float.max lo (Float.min hi x))
|
||||
| _ -> raise (Eval_error "clamp: 3 args"));
|
||||
register "truncate" (fun args ->
|
||||
match args with
|
||||
| [a] -> let n = as_number a in Number (if n >= 0.0 then floor n else ceil n)
|
||||
| _ -> raise (Eval_error "truncate: 1 arg"));
|
||||
register "remainder" (fun args ->
|
||||
match args with
|
||||
| [a; b] -> Number (Float.rem (as_number a) (as_number b))
|
||||
| _ -> raise (Eval_error "remainder: 2 args"));
|
||||
register "modulo" (fun args ->
|
||||
match args with
|
||||
| [a; b] ->
|
||||
let a = as_number a and b = as_number b in
|
||||
let r = Float.rem a b in
|
||||
Number (if r = 0.0 || (r > 0.0) = (b > 0.0) then r else r +. b)
|
||||
| _ -> raise (Eval_error "modulo: 2 args"));
|
||||
register "exact?" (fun args ->
|
||||
match args with [Number f] -> Bool (Float.is_integer f) | [_] -> Bool false
|
||||
| _ -> raise (Eval_error "exact?: 1 arg"));
|
||||
register "inexact?" (fun args ->
|
||||
match args with [Number f] -> Bool (not (Float.is_integer f)) | [_] -> Bool false
|
||||
| _ -> raise (Eval_error "inexact?: 1 arg"));
|
||||
register "exact->inexact" (fun args ->
|
||||
match args with [Number n] -> Number n | [a] -> Number (as_number a)
|
||||
| _ -> raise (Eval_error "exact->inexact: 1 arg"));
|
||||
register "inexact->exact" (fun args ->
|
||||
match args with
|
||||
| [Number n] -> if Float.is_integer n then Number n else Number (Float.round n)
|
||||
| [a] -> Number (Float.round (as_number a))
|
||||
| _ -> raise (Eval_error "inexact->exact: 1 arg"));
|
||||
register "parse-int" (fun args ->
|
||||
let parse_leading_int s =
|
||||
let len = String.length s in
|
||||
|
||||
Reference in New Issue
Block a user