Math & Arithmetic
Domain & error policy
Sema's numeric error behavior follows one rule, split by type:
- Integer division or modulo by zero raises an error.
(/ 1 0),(modulo 7 0), and(mod 7 0)all raise (division by zero/modulo by zero). Integers have no infinity or NaN to return, so the failure surfaces where it happens. - Floating-point follows IEEE 754 — overflow and undefined real-domain results return
inf,-inf, orNaNinstead of raising:
(/ 1.0 0) ; => inf
(/ -1.0 0) ; => -inf
(/ 0.0 0.0) ; => NaN
(log 0) ; => -inf
(log -1) ; => NaN
(pow 0 0) ; => 1
(pow 2 -1) ; => 1/2This matches the hardware and mainstream numeric languages, so NaN propagates and inf accumulates rather than forcing error handling around every operation. If you need to reject these, test with math/nan? / math/infinite? explicitly.
No integer overflow — Sema has a full numeric tower, so exact integer arithmetic never wraps. A result beyond
i64range promotes to an arbitrary-precision bignum:(+ 9223372036854775807 1)→9223372036854775808,(* 1000000000000 1000000000000)→1000000000000000000000000. Exact division yields rationals ((/ 1 3)→1/3) and(sqrt -1)→0+1i. (See ADR #64 and the numeric-tower ADR.)
The Numeric Tower
Sema implements the full R7RS numeric tower, a nested hierarchy of number types:
integer ⊂ rational ⊂ real ⊂ complexEvery integer is a rational, every rational is real, every real is complex — so complex? is true for every number, and integer? is the narrowest test. Two independent axes describe a value: its level in the tower (integer / rational / real / complex) and its exactness (exact vs. inexact).
- Exact numbers — integers (any size — they promote to bignums instead of overflowing), exact rationals like
1/3, and complex numbers whose parts are both exact — carry no rounding error. - Inexact numbers — floats and any complex with a floating-point part — follow IEEE 754.
- Exactness contagion: an operation is exact only when all its operands are exact; a single float makes the whole result inexact. This is why
(/ 1 3)is the exact1/3but(/ 1.0 3)is0.3333….
Literal grammar
The reader parses each tower type directly, and every literal round-trips through print → read:
| Form | Example | Reads as |
|---|---|---|
| Rational | 1/3, 3/6 (→ 1/2) | exact ratio, reduced to lowest terms |
| Complex (rectangular) | 3+4i, 1.5+2.5i, 3-4i | real + imaginary part |
| Pure imaginary | +i, -i, 2i, -2i | 0 ± ni |
| Radix prefix | #xFF (255), #o17 (15), #b1010 (10), #d42 | base 16 / 8 / 2 / 10 integer |
| Exactness prefix | #e1.5 (→ 3/2), #i1/2 (→ 0.5) | force exact / inexact |
| Combined | #e#xFF, #x#eFF | radix + exactness, either order |
| Bignum | 99999999999999999999999999 | out-of-range integer literals become bignums |
See the reader internals for the full grammar.
Basic Arithmetic
+
Add numbers together. Accepts any number of arguments.
(+ 1 2 3) ; => 6
(+ 10) ; => 10
(+) ; => 0-
Subtract numbers. With one argument, negates. With multiple, subtracts left to right.
(- 10 3) ; => 7
(- 10 3 2) ; => 5
(- 5) ; => -5*
Multiply numbers together.
(* 4 5) ; => 20
(* 2 3 4) ; => 24
(*) ; => 1/
Divide numbers. Exact-by-exact division is exact: it yields a reduced rational when the result is not a whole number (so (/ 10 3) is 10/3, not 3.333…), collapsing back to an integer when the denominator reduces to 1. A float operand makes the result a float (inexact contagion). For truncated integer division use quotient (or its math/quotient alias).
(/ 10 2) ;; => 5
(/ 10 3) ;; => 10/3
(/ 10 4) ;; => 5/2
(/ 10.0 3) ;; => 3.3333333333333335mod
Modulo. On exact integers this is floored division — the result takes the sign of the divisor, per R7RS — so (mod -7 2) is 1, not -1. (Float operands keep the IEEE truncated %, whose sign follows the dividend.) For the truncated integer counterpart whose sign follows the dividend, use remainder.
(mod 10 3) ; => 1
(mod 7 2) ; => 1
(mod -7 2) ; => 1Comparison
<
Less than. Supports chaining.
(< 1 2) ; => #t
(< 1 2 3) ; => #t
(< 3 2) ; => #f>
Greater than.
(> 3 2) ; => #t
(> 1 2) ; => #f<=
Less than or equal.
(<= 1 2) ; => #t
(<= 2 2) ; => #t>=
Greater than or equal.
(>= 3 2) ; => #t
(>= 2 2) ; => #t=
Equality. For numbers this is numeric equality (so (= 1 1.0) is #t); for non-numbers it falls back to structural equality. Unlike < / >, comparing non-numbers does not error.
(= 1 1) ; => #t
(= 1 1.0) ; => #t
(= 1 2) ; => #f
(= "abc" "abc") ; => #t (structural, not an error)Numeric Utilities
abs
Absolute value.
(abs -5) ; => 5
(abs 3) ; => 3
(abs -3.14) ; => 3.14min
Return the smallest of 1 or more numbers (the no-arg case errors).
(min 1 2 3) ;; => 1
(min 5) ;; => 5
(min) ;; error: Arity error: min expects 1+ args, got 0max
Return the largest of 1 or more numbers (the no-arg case errors).
(max 1 2 3) ;; => 3
(max 5) ;; => 5
(max) ;; error: Arity error: max expects 1+ args, got 0pow
Raise a number to a power.
(pow 2 10) ; => 1024
(pow 3 3) ; => 27sqrt
Square root. The square root of an exact perfect square is returned exactly ((sqrt 16) is 4, not 4.0); otherwise the result is an inexact float. The square root of a negative number is complex.
(sqrt 16) ; => 4
(sqrt 2) ; => 1.4142135623730951
(sqrt -1) ; => 0+1ilog
Natural logarithm.
(log 1) ; => 0.0
(log 100) ; => 4.605...floor
Round down toward negative infinity. Exactness-preserving: a float argument rounds to a float (3.7 → 3.0), while an exact rational rounds to an exact integer (7/2 → 3).
(floor 3.7) ; => 3.0
(floor -2.3) ; => -3.0
(floor 7/2) ; => 3ceil
Round up toward positive infinity. Exactness-preserving, like floor.
(ceil 3.2) ; => 4.0
(ceil -2.7) ; => -2.0
(ceil 7/2) ; => 4round
Round to the nearest integer, ties to even (banker's rounding). Exactness-preserving: a float rounds to a float, an exact rational to an exact integer.
(round 3.5) ; => 4.0
(round 3.4) ; => 3.0
(round 7/2) ; => 4math/round-to
Round to places decimal places, returning a float (where round only rounds to a whole integer).
(math/round-to 3.14159 2) ; => 3.14
(math/round-to 0.46666 3) ; => 0.467math/format-fixed
Format a number as a fixed-decimal string, padding trailing zeros to places digits — for money/metrics display where math/round-to (a float, which drops trailing zeros) isn't enough.
(math/format-fixed 1.2 3) ; => "1.200"
(math/format-fixed 3.14159 2) ; => "3.14"Trigonometry
sin
Sine (argument in radians).
(sin 0) ; => 0.0
(sin pi) ; => ~0.0cos
Cosine (argument in radians).
(cos 0) ; => 1.0
(cos pi) ; => -1.0math/tan
Tangent (argument in radians).
(math/tan 0) ; => 0.0
(math/tan (/ pi 4)); => ~1.0math/asin
Inverse sine. Returns radians.
(math/asin 1) ; => ~1.5707 (π/2)
(math/asin 0) ; => 0.0math/acos
Inverse cosine. Returns radians.
(math/acos 0) ; => ~1.5707 (π/2)
(math/acos 1) ; => 0.0math/atan
Inverse tangent. Returns radians.
(math/atan 1) ; => ~0.7854 (π/4)
(math/atan 0) ; => 0.0math/atan2
Two-argument inverse tangent. Returns the angle in radians between the positive x-axis and the point (x, y).
(math/atan2 1 1) ; => ~0.7854 (π/4)
(math/atan2 0 -1) ; => ~3.1416 (π)Hyperbolic Functions
math/sinh
Hyperbolic sine.
(math/sinh 0) ; => 0.0
(math/sinh 1) ; => 1.1752...math/cosh
Hyperbolic cosine.
(math/cosh 0) ; => 1.0
(math/cosh 1) ; => 1.5430...math/tanh
Hyperbolic tangent.
(math/tanh 0) ; => 0.0
(math/tanh 1) ; => 0.7615...Exponential & Logarithmic
math/exp
Euler's number raised to a power (e^x).
(math/exp 1) ; => 2.71828...
(math/exp 0) ; => 1.0math/log10
Base-10 logarithm.
(math/log10 100) ; => 2.0
(math/log10 1000) ; => 3.0math/log2
Base-2 logarithm.
(math/log2 8) ; => 3.0
(math/log2 1024) ; => 10.0Integer Division
These operate on exact integers, are bignum-aware (they promote past i64 automatically), and raise on a zero divisor. Each has a slash-namespaced alias (math/quotient, math/remainder, math/gcd, math/lcm) that is the identical function.
quotient
Truncated integer division: n ÷ d rounded toward zero, so (quotient -7 2) is -3 (not floored to -4), per R7RS. Alias: math/quotient.
(quotient 10 3) ; => 3
(quotient -7 2) ; => -3
(quotient 100000000000000000000 7) ; => 14285714285714285714remainder
Remainder of truncated division: the result takes the sign of the dividend n. Pairs with quotient so that (+ (* (quotient n d) d) (remainder n d)) reconstructs n. Contrast mod, whose sign follows the divisor. Alias: math/remainder.
(remainder 10 3) ; => 1
(remainder -7 2) ; => -1
(remainder 7 -2) ; => 1gcd
Greatest common divisor — the largest non-negative integer dividing every argument. Variadic and sign-independent; (gcd) is 0. Alias: math/gcd.
(gcd 12 8) ; => 4
(gcd 15 10 25) ; => 5
(gcd -12 8) ; => 4
(gcd) ; => 0lcm
Least common multiple — the smallest non-negative integer every argument divides. Variadic and sign-independent; 0 if any argument is 0; (lcm) is 1. Alias: math/lcm.
(lcm 4 6) ; => 12
(lcm 2 3 4) ; => 12
(lcm 0 5) ; => 0
(lcm) ; => 1Exactness & Rationals
Utilities for moving between exact and inexact forms and for working with exact rationals. See The Numeric Tower for the underlying model.
exact
Convert a number to its exact form. A finite float becomes the exact rational it actually represents (reduced, and normalized to an integer when the denominator is 1); already-exact numbers pass through. inexact->exact is the longer R7RS spelling.
(exact 0.5) ; => 1/2
(exact 2.0) ; => 2
(exact 1/3) ; => 1/3
(exact 3.14159) ; => 3537115888337719/1125899906842624The last result is exact but surprising: 3.14159 is not representable in binary, so exact returns the precise fraction the double stores. Use rationalize for a tidy approximation.
inexact
Convert a number to inexact (floating-point) form — an exact rational becomes its nearest f64, and each part of a complex becomes a float. exact->inexact is the longer R7RS spelling.
(inexact 1/3) ; => 0.3333333333333333
(inexact 42) ; => 42.0
(inexact 3+4i) ; => 3.0+4.0iexact->inexact
R7RS spelling of inexact — identical behavior.
(exact->inexact 1/3) ; => 0.3333333333333333
(exact->inexact 42) ; => 42.0inexact->exact
R7RS spelling of exact — identical behavior.
(inexact->exact 0.5) ; => 1/2
(inexact->exact 2.0) ; => 2
(inexact->exact 0.1) ; => 3602879701896397/360287970189639680.1 shows the caveat: it has no finite binary expansion, so its exact value is that large power-of-two fraction, not 1/10.
numerator
Numerator of an exact rational, taken in lowest terms (the sign lives on the numerator). An integer n is n/1. A float or complex argument raises a type error — convert with exact first.
(numerator 22/7) ; => 22
(numerator -6/4) ; => -3
(numerator 42) ; => 42denominator
Denominator of an exact rational, in lowest terms. An integer's denominator is 1.
(denominator 22/7) ; => 7
(denominator -6/4) ; => 2
(denominator 42) ; => 1rationalize
Find the simplest rational within tol of x (smallest denominator in [x-|tol|, x+|tol|]), per R7RS. Exactness follows contagion: the result is exact only when both arguments are exact.
(rationalize 1/3 1/1000) ; => 1/3
(rationalize (exact 3.14159) 1/100) ; => 22/7
(rationalize 3.14159 1/100) ; => 3.142857142857143
(rationalize 1/2 0.01) ; => 0.5The last two show contagion — an inexact x or an inexact tol gives an inexact (float) answer.
exact-integer-sqrt
Exact integer square root of a non-negative integer. Returns a two-element list (s r) with s = ⌊√n⌋ and s*s + r = n; exact even for bignums.
(exact-integer-sqrt 17) ; => (4 1)
(exact-integer-sqrt 100) ; => (10 0)
(exact-integer-sqrt 15241578750190521) ; => (123456789 0)Complex Numbers
A complex number a+bi has a real and an imaginary part. A complex whose imaginary part is exact zero collapses to a real, so real? is true for 3+0i. Polar conversions run through sin/cos/atan2 in floating point, so make-polar, magnitude, and angle are always inexact.
make-rectangular
Construct a complex from a real and an imaginary part. An exact-zero imaginary part collapses to the real; an inexact zero (0.0) stays complex.
(make-rectangular 3 4) ; => 3+4i
(make-rectangular 1/3 1/2) ; => 1/3+1/2i
(make-rectangular 2 0) ; => 2
(make-rectangular 3 0.0) ; => 3+0.0imake-polar
Construct a complex from magnitude r and angle θ (radians): r·cos θ + r·sin θ·i. Always inexact.
(make-polar 2 0) ; => 2.0+0.0i
(make-polar 5 (math/atan2 3 4)) ; => 4.0+3.0ireal-part
Real part of a number (the number itself for a real). Preserves exactness.
(real-part 3+4i) ; => 3
(real-part 5i) ; => 0
(real-part 2.5) ; => 2.5imag-part
Imaginary part of a number (exact 0 for any real). Preserves exactness.
(imag-part 3+4i) ; => 4
(imag-part 5i) ; => 5
(imag-part 2.5) ; => 0magnitude
Magnitude (modulus, absolute value). For a complex a+bi this is √(a²+b²), computed in floating point (so it is inexact); for a real it is the absolute value and preserves exactness.
(magnitude 3+4i) ; => 5.0
(magnitude -5) ; => 5
(magnitude 1/3) ; => 1/3angle
Angle (argument) of a complex in radians, in (-π, π]: atan2(b, a). Always inexact — a positive real gives 0.0, a negative real gives π.
(angle 3+4i) ; => 0.9272952180016122
(angle 5) ; => 0.0
(angle -5) ; => 3.141592653589793Number ↔ String
number->string
Render any number in the tower as a string. An optional radix of 2, 8, 10, or 16 selects the output base — but a non-decimal radix accepts only exact integers.
(number->string 42) ; => "42"
(number->string 1/3) ; => "1/3"
(number->string 3+4i) ; => "3+4i"
(number->string 255 16) ; => "ff"
(number->string 5 2) ; => "101"string->number
Parse a string as a number, returning #f (never an error) on invalid input. The default radix 10 accepts the whole tower (integers, rationals, floats, complex); a radix of 2, 8, or 16 parses an integer in that base.
(string->number "42") ; => 42
(string->number "1/3") ; => 1/3
(string->number "3+4i") ; => 3+4i
(string->number "ff" 16) ; => 255
(string->number "nope") ; => #fRandom Numbers
math/random
Return a random float between 0.0 (inclusive) and 1.0 (exclusive).
(math/random) ; => 0.7291... (varies)math/random-int
Return a random integer in a range (inclusive on both ends).
(math/random-int 1 100) ; => 42 (varies)
(math/random-int 0 9) ; => 7 (varies)Interpolation & Clamping
math/clamp
Clamp a value to a range.
(math/clamp 15 0 10) ; => 10
(math/clamp -5 0 10) ; => 0
(math/clamp 5 0 10) ; => 5math/sign
Return the sign of a number: -1, 0, or 1.
(math/sign -5) ; => -1
(math/sign 0) ; => 0
(math/sign 42) ; => 1math/lerp
Linear interpolation between two values. (math/lerp a b t) returns a + (b - a) * t.
(math/lerp 0 100 0.5) ; => 50.0
(math/lerp 0 100 0.25) ; => 25.0
(math/lerp 10 20 0.0) ; => 10.0math/map-range
Map a value from one range to another. (math/map-range value in-min in-max out-min out-max).
(math/map-range 5 0 10 0 100) ; => 50.0
(math/map-range 0.5 0 1 0 255) ; => 127.5Angle Conversion
math/degrees->radians
Convert degrees to radians.
(math/degrees->radians 180) ; => 3.14159...
(math/degrees->radians 90) ; => 1.5707...math/radians->degrees
Convert radians to degrees.
(math/radians->degrees pi) ; => 180.0
(math/radians->degrees 1) ; => 57.295...Numeric Predicates
even?
Test if an integer is even.
(even? 4) ; => #t
(even? 3) ; => #fodd?
Test if an integer is odd.
(odd? 3) ; => #t
(odd? 4) ; => #fpositive?
Test if a number is positive.
(positive? 1) ; => #t
(positive? -1) ; => #f
(positive? 0) ; => #fnegative?
Test if a number is negative.
(negative? -1) ; => #t
(negative? 1) ; => #fzero?
Test if a number is zero.
(zero? 0) ; => #t
(zero? 1) ; => #fmath/nan?
Test if a value is NaN (not a number).
(math/nan? math/nan) ; => #t
(math/nan? 42) ; => #fmath/infinite?
Test if a value is infinite.
(math/infinite? math/infinity) ; => #t
(math/infinite? 42) ; => #fConstants
pi
The mathematical constant π (3.14159...).
pi ; => 3.141592653589793e
Euler's number (2.71828...).
e ; => 2.718281828459045math/infinity
Positive infinity.
math/infinity ; => Infmath/nan
Not a number.
math/nan ; => NaNScheme Aliases
modulo
Alias for mod.
(modulo 10 3) ; => 1expt
Alias for pow (Scheme name for exponentiation). With exact integer arguments the result is exact and bignum-aware — no overflow — and a negative exponent yields an exact rational.
(expt 2 10) ; => 1024
(expt 2 100) ; => 1267650600228229401496703205376
(expt 2 -1) ; => 1/2ceiling
Alias for ceil (exactness-preserving, so a float rounds to a float).
(ceiling 3.2) ; => 4.0truncate
Round toward zero (drop the fractional part). Exactness-preserving: a float truncates to a float, an exact rational to an exact integer.
(truncate 3.7) ; => 3.0
(truncate -3.7) ; => -3.0
(truncate 7/2) ; => 3Bitwise Operations
bit/and
Bitwise AND.
(bit/and 5 3) ; => 1
(bit/and 15 9) ; => 9bit/or
Bitwise OR.
(bit/or 5 3) ; => 7
(bit/or 8 4) ; => 12bit/xor
Bitwise XOR.
(bit/xor 5 3) ; => 6bit/not
Bitwise NOT (complement).
(bit/not 5) ; => -6bit/shift-left
Left bit shift.
(bit/shift-left 1 4) ; => 16
(bit/shift-left 3 2) ; => 12bit/shift-right
Right bit shift.
(bit/shift-right 16 2) ; => 4
(bit/shift-right 8 1) ; => 4