lyng/docs/math.md

7.1 KiB

Operators

Precedence

Same as in C++.

Priority Operations
Highest
0
power, not, calls, indexing, dot,...
1 % * /
2 + -
3 bit shifts << >>
4 <=> (1)
5 <= >= < >
6 == !=
7 bitwise and &
8 bitwise xor ^
9 bitwise or |
10 &&
11
lowest
||
Bitwise operators
available only for Int values. For mixed Int/Real numeric expressions, bitwise operators are not defined.
Bitwise NOT ~x
unary operator that inverts all bits of a 64‑bit signed integer (Int). It follows two's‑complement rules, so ~x is numerically equal to -(x + 1). Examples: ~0 == -1, ~1 == -2, ~(-1) == 0.

Examples:

5 & 3    // -> 1
5 | 3    // -> 7
5 ^ 3    // -> 6
~0       // -> -1
1 << 3   // -> 8
8 >> 3   // -> 1

Notes:

  • Shifts operate on 64-bit signed integers (Int is 64-bit). Right shift >> is arithmetic (sign-propagating).
  • Shift count is masked to the range 0..63, similar to the JVM/Kotlin behavior (e.g., 1 << 65 equals 1 << 1).
(1)
Shuttle operator: a <=> b returns 0 if a == b, negative Int if a < b and positive Int otherwise. It is necessary to override shuttle operator to make a class comparable.

Operators

+ - * / % : if both operand is Int, calculates as int. Otherwise, as real:

// integer division:
3 / 2
>>> 1

but:

3 / 2.0
>>> 1.5

Round and range

The following functions return the argument unchanged if it is Int.

For Decimal:

  • floor(x), ceil(x), and round(x) currently use exact decimal operations
  • the result stays Decimal

For Real, the result is a transformed Real.

name description
floor(x) Computes the largest integer value not greater than x
ceil(x) Computes the least integer value value not less than x
round(x) Rounds x
x.roundToInt() shortcut to round(x).toInt()

Lyng math functions

Decimal note:

  • all scalar math helpers accept Decimal
  • abs(x) stays exact for Decimal
  • pow(x, y) is exact for Decimal when y is an integral exponent
  • the remaining Decimal cases currently use a temporary bridge: Decimal -> Real -> host math -> Decimal
  • this is temporary; native decimal implementations are planned
name meaning
sin(x) sine
cos(x) cosine
tan(x) tangent
asin(x) sin^{-1}(x)
acos(x) cos^{-1}(x)
atan(x) tg^{-1}(x)
sinh(x) hyperbolic sine
cosh(x) hyperbolic cosine
tanh(x) hyperbolic tangent
asinh(x) sinh^{-1}(x)
acosh(x) cosh^{-1}(x)
atanh(x) tgh^{-1}(x)
ln(x) ln(x), log_e(x)
exp(x) e^x
log10(x) log_{10}(x)
pow(x, y) {x^y}
sqrt(x) \sqrt {x}
abs(x) absolute value of x. Int if x is Int, Decimal if x is Decimal, Real otherwise
clamp(x, range) limit x to be inside range boundaries

For example:

assert( sin(π/2) == 1.0)
assert( cos(π/2) < 0.000001)
assert( abs(ln(exp(1))) - 1 < 0.00001)

// abs() keeps the argument type:
assert( abs(-1) is Int)
assert( abs(-2.21) == 2.21 )

import lyng.decimal

// Decimal-aware math works too. Some functions are exact, some still bridge through Real temporarily:
assert( (abs("-2.5".d) as Decimal).toStringExpanded() == "2.5" )
assert( (floor("2.9".d) as Decimal).toStringExpanded() == "2" )
assert( sin("0.5".d) is Decimal )

// clamp() limits value to the range:
assert( clamp(15, 0..10) == 10 )
assert( clamp(-5, 0..10) == 0 )
assert( 5.clamp(0..10) == 5 )
>>> void

Linear algebra: lyng.matrix

For vectors and dense matrices, import lyng.matrix:

import lyng.matrix

It provides:

  • Vector
  • Matrix
  • vector(values)
  • matrix(rows)

Core operations include:

  • matrix addition and subtraction
  • matrix-matrix multiplication
  • matrix-vector multiplication
  • transpose
  • determinant
  • inverse
  • linear solve
  • vector dot, norm, normalize, cross, outer product

Example:

import lyng.matrix

val a: Matrix = matrix([[1, 2, 3], [4, 5, 6]])
val b: Matrix = matrix([[7, 8], [9, 10], [11, 12]])
val product: Matrix = a * b
assertEquals([[58.0, 64.0], [139.0, 154.0]], product.toList())

Matrices also support two-axis bracket indexing and slicing:

import lyng.matrix

val m: Matrix = matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
assertEquals(6.0, m[1, 2])
val sub: Matrix = m[0..1, 1..2]
assertEquals([[2.0, 3.0], [5.0, 6.0]], sub.toList())

See Matrix for the full API.

Random values

Lyng stdlib provides a global random singleton and deterministic seeded generators:

name meaning
Random.nextInt() random Int from full platform range
Random.nextFloat() random Real in [0,1)
Random.next(range) random value from the given finite range
Random.seeded(seed) creates deterministic generator
SeededRandom.nextInt() deterministic random Int
SeededRandom.nextFloat() deterministic random Real in [0,1)
SeededRandom.next(range) deterministic random value from range

Examples:

val rng = Random.seeded(1234)
assert( rng.next(1..10) in 1..10 )
assert( rng.next('a'..<'f') in 'a'..<'f' )
assert( rng.next(0.0..<1.0) >= 0.0 )
assert( rng.next(0.0..<1.0) < 1.0 )
>>> void

Scientific constant

name meaning
Math.PI: Real or π 3.1415926...