Browse the docs

silk.num.numeric.

Generic helpers and numeric contracts for algorithms over primitive numbers.

When to use#

Bound a type parameter with Zero or One when generic code needs the additive or multiplicative identity of its number type, and with Float when it needs square roots, trigonometry, or other binary floating-point operations. Call Numeric.add to add two values of any primitive number type from generic code. Use the concrete number modules directly when an algorithm also needs width-specific conversion, overflow, bitwise, or formatting operations.

Details#

Every primitive integer and float type conforms to Zero and One. Only f32 and f64 conform to Float, whose operations call the functions of silk.num.f32 and silk.num.f64. A library number type, such as a fixed-point type, can conform in its own module. The helpers bound their type parameter with these interfaces or with the operator interfaces of silk.core.ops, such as T: Add<T, T>. The compiler selects the conformance during specialization. A helper adds no effect requirement and no runtime dispatch.

Gotchas#

Each helper keeps the overflow rule of the operator. Integer addition traps if the result is outside the range of the type.

Examples#

Add values through one generic contract#

silk
import silk.num.numeric { Numeric }
import silk.core.ops { Add }

fn total<T: Add<T, T>>(first: T, second: T, third: T) -> T {
  let partial = Numeric.add<T>(move first, move second)
  return Numeric.add<T>(move partial, move third)
}

pub fn main() -> i32 {
  let small: u8 = total<u8>(1, 2, 3)
  let large: i64 = total<i64>(40, 1, 1)
  if small != 6 || large != 42 {
    return 1
  }
  return 0
}

Compute a length for any float type#

silk
import silk.num.numeric { Float }
import silk.core.ops { Add, Multiply }
import silk.core.ownership { Copy }

fn length<T: Copy + Float + Add<T, T> + Multiply<T, T>>(x: T, y: T) -> T {
  return Float.sqrt(x * x + y * y)
}

pub fn main() -> i32 {
  let wide: f64 = length<f64>(3.0, 4.0)
  let narrow: f32 = length<f32>(6.0, 8.0)
  if wide != 5.0 || narrow != 10.0 {
    return 1
  }
  return 0
}

Import as Numeric with import silk.num.numeric { Numeric }.

Public declarations: 4.

Numeric#

silk
pub struct Numeric

The owner type of the generic numeric helpers. It has no fields and is never constructed.

Implementation Numeric#

silk
impl Numeric

Associated function add#

silk
pub fn add<T: Add<T, T>>(left: T, right: T) -> T

Returns left + right for any type T that has the + operator.

When to use#

Use add in generic code, or to pass addition as a named function.

Gotchas#

For an integer type, the program traps if the sum is outside the range of T.

Associated function zero#

silk
pub fn zero<T: Zero>() -> T

Returns the additive identity of T, such as 0 for an integer type or 0.0 for a float.

When to use#

Use zero when code must name the zero of a type that it writes as an argument, such as Numeric.zero<i32>(). Inside a generic body that bounds T: Zero, Zero.zero() gives the same value.

Associated function one#

silk
pub fn one<T: One>() -> T

Returns the multiplicative identity of T, such as 1 for an integer type or 1.0 for a float.

When to use#

Use one when code must name the one of a type that it writes as an argument, such as Numeric.one<f32>(). Inside a generic body that bounds T: One, One.one() gives the same value.

Zero#

silk
pub interface Zero

The additive identity of a number type.

When to use#

Bound a type parameter with Zero when generic code must start a sum, build an origin, or test for zero without a literal of the concrete type.

Details#

Every primitive integer type returns 0, and f32 and f64 return positive zero. A library number type, such as a fixed-point type, can implement Zero in its own module.

Operation zero#

silk
fn zero() -> Self

Returns the value that leaves any other value unchanged under addition.

One#

silk
pub interface One

The multiplicative identity of a number type.

When to use#

Bound a type parameter with One when generic code must build an identity transform, a unit scale, or another value that needs 1 of the concrete type.

Details#

Every primitive integer type returns 1, and f32 and f64 return 1.0. A library number type, such as a fixed-point type, can implement One in its own module.

Operation one#

silk
fn one() -> Self

Returns the value that leaves any other value unchanged under multiplication.

Float#

silk
pub interface Float

The binary floating-point operations that generic geometry and numeric code needs.

When to use#

Bound a type parameter with Float when generic code needs square roots, trigonometry, rounding, or finiteness tests and must work for both f32 and f64.

Details#

f32 and f64 conform, and each operation calls the function of the same name in silk.num.f32 or silk.num.f64. So each operation returns the same bits on every target and gives the canonical quiet NaN for every NaN result. Angles are in radians.

Gotchas#

Float does not include Zero or One. Bound with T: Float + Zero + One when generic code also needs those values.

Operation sqrt#

silk
fn sqrt(value: Self) -> Self

Returns the square root of value. Negative nonzero inputs and NaN return NaN.

Operation abs#

silk
fn abs(value: Self) -> Self

Returns the magnitude of value, which clears the sign bit.

Operation floor#

silk
fn floor(value: Self) -> Self

Returns the largest integer value that is not greater than value.

Operation ceil#

silk
fn ceil(value: Self) -> Self

Returns the smallest integer value that is not less than value.

Operation round#

silk
fn round(value: Self) -> Self

Returns the nearest integer value to value, with halfway cases away from zero.

Operation trunc#

silk
fn trunc(value: Self) -> Self

Returns the integer part of value, which discards the fraction toward zero.

Operation min#

silk
fn min(left: Self, right: Self) -> Self

Returns the smaller of left and right, with negative zero below positive zero. A NaN operand gives NaN.

Operation max#

silk
fn max(left: Self, right: Self) -> Self

Returns the larger of left and right, with positive zero above negative zero. A NaN operand gives NaN.

Operation sin#

silk
fn sin(value: Self) -> Self

Returns the sine of value, an angle in radians.

Operation cos#

silk
fn cos(value: Self) -> Self

Returns the cosine of value, an angle in radians.

Operation tan#

silk
fn tan(value: Self) -> Self

Returns the tangent of value, an angle in radians.

Operation atan2#

silk
fn atan2(y: Self, x: Self) -> Self

Returns the angle in radians from the positive x axis to the point (x, y), in [-pi, pi].

Operation hypot#

silk
fn hypot(x: Self, y: Self) -> Self

Returns sqrt(x * x + y * y) without overflow or underflow in the intermediate squares.

Operation fma#

silk
fn fma(left: Self, right: Self, addend: Self) -> Self

Returns left * right + addend with one rounding.

Operation isFinite#

silk
fn isFinite(value: Self) -> bool

Returns true when value is neither infinite nor NaN.

Operation isNaN#

silk
fn isNaN(value: Self) -> bool

Returns true when value is NaN.

Implementation Zero for u8#

silk
impl Zero for u8

Operation zero#

silk
fn zero() -> u8

Implementation Zero for u16#

silk
impl Zero for u16

Operation zero#

silk
fn zero() -> u16

Implementation Zero for u32#

silk
impl Zero for u32

Operation zero#

silk
fn zero() -> u32

Implementation Zero for u64#

silk
impl Zero for u64

Operation zero#

silk
fn zero() -> u64

Implementation Zero for usize#

silk
impl Zero for usize

Operation zero#

silk
fn zero() -> usize

Implementation Zero for i8#

silk
impl Zero for i8

Operation zero#

silk
fn zero() -> i8

Implementation Zero for i16#

silk
impl Zero for i16

Operation zero#

silk
fn zero() -> i16

Implementation Zero for i32#

silk
impl Zero for i32

Operation zero#

silk
fn zero() -> i32

Implementation Zero for i64#

silk
impl Zero for i64

Operation zero#

silk
fn zero() -> i64

Implementation Zero for isize#

silk
impl Zero for isize

Operation zero#

silk
fn zero() -> isize

Implementation Zero for f32#

silk
impl Zero for f32

Operation zero#

silk
fn zero() -> f32

Implementation Zero for f64#

silk
impl Zero for f64

Operation zero#

silk
fn zero() -> f64

Implementation One for u8#

silk
impl One for u8

Operation one#

silk
fn one() -> u8

Implementation One for u16#

silk
impl One for u16

Operation one#

silk
fn one() -> u16

Implementation One for u32#

silk
impl One for u32

Operation one#

silk
fn one() -> u32

Implementation One for u64#

silk
impl One for u64

Operation one#

silk
fn one() -> u64

Implementation One for usize#

silk
impl One for usize

Operation one#

silk
fn one() -> usize

Implementation One for i8#

silk
impl One for i8

Operation one#

silk
fn one() -> i8

Implementation One for i16#

silk
impl One for i16

Operation one#

silk
fn one() -> i16

Implementation One for i32#

silk
impl One for i32

Operation one#

silk
fn one() -> i32

Implementation One for i64#

silk
impl One for i64

Operation one#

silk
fn one() -> i64

Implementation One for isize#

silk
impl One for isize

Operation one#

silk
fn one() -> isize

Implementation One for f32#

silk
impl One for f32

Operation one#

silk
fn one() -> f32

Implementation One for f64#

silk
impl One for f64

Operation one#

silk
fn one() -> f64

Implementation Float for f32#

silk
impl Float for f32

Operation sqrt#

silk
fn sqrt(value: f32) -> f32

Operation abs#

silk
fn abs(value: f32) -> f32

Operation floor#

silk
fn floor(value: f32) -> f32

Operation ceil#

silk
fn ceil(value: f32) -> f32

Operation round#

silk
fn round(value: f32) -> f32

Operation trunc#

silk
fn trunc(value: f32) -> f32

Operation sin#

silk
fn sin(value: f32) -> f32

Operation cos#

silk
fn cos(value: f32) -> f32

Operation tan#

silk
fn tan(value: f32) -> f32

Operation min#

silk
fn min(left: f32, right: f32) -> f32

Operation max#

silk
fn max(left: f32, right: f32) -> f32

Operation atan2#

silk
fn atan2(y: f32, x: f32) -> f32

Operation hypot#

silk
fn hypot(x: f32, y: f32) -> f32

Operation fma#

silk
fn fma(left: f32, right: f32, addend: f32) -> f32

Operation isFinite#

silk
fn isFinite(value: f32) -> bool

Operation isNaN#

silk
fn isNaN(value: f32) -> bool

Implementation Float for f64#

silk
impl Float for f64

Operation sqrt#

silk
fn sqrt(value: f64) -> f64

Operation abs#

silk
fn abs(value: f64) -> f64

Operation floor#

silk
fn floor(value: f64) -> f64

Operation ceil#

silk
fn ceil(value: f64) -> f64

Operation round#

silk
fn round(value: f64) -> f64

Operation trunc#

silk
fn trunc(value: f64) -> f64

Operation sin#

silk
fn sin(value: f64) -> f64

Operation cos#

silk
fn cos(value: f64) -> f64

Operation tan#

silk
fn tan(value: f64) -> f64

Operation min#

silk
fn min(left: f64, right: f64) -> f64

Operation max#

silk
fn max(left: f64, right: f64) -> f64

Operation atan2#

silk
fn atan2(y: f64, x: f64) -> f64

Operation hypot#

silk
fn hypot(x: f64, y: f64) -> f64

Operation fma#

silk
fn fma(left: f64, right: f64, addend: f64) -> f64

Operation isFinite#

silk
fn isFinite(value: f64) -> bool

Operation isNaN#

silk
fn isNaN(value: f64) -> bool

Category: Numbers.

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.

View the source of this page