Jelajahi Sumber

Document string functions

David Peter 1 tahun lalu
induk
melakukan
a9cc74bac5

+ 3 - 2
book/build.py

@@ -78,7 +78,8 @@ def list_of_functions(file_name, document):
             links = []
             links = []
             for section in sections:
             for section in sections:
                 if title := section.get("title"):
                 if title := section.get("title"):
-                    links.append(f"[{title}](#{title.lower().replace(' ', '-')})")
+                    link = title.lower().replace(" ", "-").replace(",", "")
+                    links.append(f"[{title}](#{link})")
             print(f"{' · '.join(links)}\n", file=f, flush=True)
             print(f"{' · '.join(links)}\n", file=f, flush=True)
 
 
         for section in sections:
         for section in sections:
@@ -136,7 +137,7 @@ list_of_functions(
             },
             },
             {
             {
                 "title": "Number theory",
                 "title": "Number theory",
-                "modules": ["core::number_theory"],
+                "modules": ["math::number_theory"],
             },
             },
             {
             {
                 "title": "Numerical methods",
                 "title": "Numerical methods",

+ 2 - 2
book/src/conversion-functions.md

@@ -27,8 +27,8 @@ now() -> tz("Asia/Kathmandu")
 # Convert a number to a custom base
 # Convert a number to a custom base
 42 -> base(16)
 42 -> base(16)
 
 
-# Convert an ASCII code point number to a character
-78 -> chr
+# Convert a code point number to a character
+0x2764 -> chr
 
 
 # Convert a string to upper/lower case
 # Convert a string to upper/lower case
 "numbat is awesome" -> uppercase
 "numbat is awesome" -> uppercase

+ 35 - 13
book/src/list-functions-math.md

@@ -1,6 +1,6 @@
 # Mathematical functions
 # Mathematical functions
 
 
-[Basics](#basics) · [Transcendental functions](#transcendental-functions) · [Trigonometry](#trigonometry) · [Statistics](#statistics) · [Random sampling, distributions](#random-sampling,-distributions) · [Number theory](#number-theory) · [Numerical methods](#numerical-methods) · [Geometry](#geometry) · [Algebra](#algebra) · [Trigonometry (extra)](#trigonometry-(extra))
+[Basics](#basics) · [Transcendental functions](#transcendental-functions) · [Trigonometry](#trigonometry) · [Statistics](#statistics) · [Random sampling, distributions](#random-sampling-distributions) · [Number theory](#number-theory) · [Numerical methods](#numerical-methods) · [Geometry](#geometry) · [Algebra](#algebra) · [Trigonometry (extra)](#trigonometry-(extra))
 
 
 ## Basics
 ## Basics
 
 
@@ -14,7 +14,7 @@ fn id<A>(x: A) -> A
 ```
 ```
 
 
 ### `abs` (Absolute value)
 ### `abs` (Absolute value)
-Return the absolute value of the input, \\( |x| \\). This works for quantities, too: `abs(-5 m) = 5 m`.
+Return the absolute value \\( |x| \\) of the input. This works for quantities, too: `abs(-5 m) = 5 m`.
 More information [here](https://doc.rust-lang.org/std/primitive.f64.html#method.abs).
 More information [here](https://doc.rust-lang.org/std/primitive.f64.html#method.abs).
 
 
 ```nbt
 ```nbt
@@ -22,7 +22,7 @@ fn abs<T: Dim>(x: T) -> T
 ```
 ```
 
 
 ### `sqrt` (Square root)
 ### `sqrt` (Square root)
-Return the square root of the input, \\( \sqrt{x} \\): `sqrt(121 m^2) = 11 m`.
+Return the square root \\( \sqrt{x} \\) of the input: `sqrt(121 m^2) = 11 m`.
 More information [here](https://en.wikipedia.org/wiki/Square_root).
 More information [here](https://en.wikipedia.org/wiki/Square_root).
 
 
 ```nbt
 ```nbt
@@ -30,7 +30,7 @@ fn sqrt<D: Dim>(x: D^2) -> D
 ```
 ```
 
 
 ### `cbrt` (Cube root)
 ### `cbrt` (Cube root)
-Return the cube root of the input, \\( \sqrt[3]{x} \\): `cbrt(8 m^3) = 2 m`.
+Return the cube root \\( \sqrt[3]{x} \\) of the input: `cbrt(8 m^3) = 2 m`.
 More information [here](https://en.wikipedia.org/wiki/Cube_root).
 More information [here](https://en.wikipedia.org/wiki/Cube_root).
 
 
 ```nbt
 ```nbt
@@ -45,7 +45,7 @@ fn sqr<D: Dim>(x: D) -> D^2
 ```
 ```
 
 
 ### `round` (Rounding)
 ### `round` (Rounding)
-Round to the nearest integer. If the value is half-way between two integers, round away from 0.
+Round to the nearest integer. If the value is half-way between two integers, round away from \\( 0 \\).
 More information [here](https://doc.rust-lang.org/std/primitive.f64.html#method.round).
 More information [here](https://doc.rust-lang.org/std/primitive.f64.html#method.round).
 
 
 ```nbt
 ```nbt
@@ -53,7 +53,7 @@ fn round<T: Dim>(x: T) -> T
 ```
 ```
 
 
 ### `floor` (Floor function)
 ### `floor` (Floor function)
-Returns the largest integer less than or equal to `x`.
+Returns the largest integer less than or equal to \\( x \\).
 More information [here](https://doc.rust-lang.org/std/primitive.f64.html#method.floor).
 More information [here](https://doc.rust-lang.org/std/primitive.f64.html#method.floor).
 
 
 ```nbt
 ```nbt
@@ -61,7 +61,7 @@ fn floor<T: Dim>(x: T) -> T
 ```
 ```
 
 
 ### `ceil` (Ceil function)
 ### `ceil` (Ceil function)
-Returns the smallest integer greater than or equal to `x`.
+Returns the smallest integer greater than or equal to \\( x \\).
 More information [here](https://doc.rust-lang.org/std/primitive.f64.html#method.ceil).
 More information [here](https://doc.rust-lang.org/std/primitive.f64.html#method.ceil).
 
 
 ```nbt
 ```nbt
@@ -69,7 +69,7 @@ fn ceil<T: Dim>(x: T) -> T
 ```
 ```
 
 
 ### `mod` (Modulo)
 ### `mod` (Modulo)
-Calculates the least nonnegative remainder of `a (mod b)`.
+Calculates the least nonnegative remainder of \\( a (\mod b) \\).
 More information [here](https://doc.rust-lang.org/std/primitive.f64.html#method.rem_euclid).
 More information [here](https://doc.rust-lang.org/std/primitive.f64.html#method.rem_euclid).
 
 
 ```nbt
 ```nbt
@@ -293,7 +293,7 @@ fn rand_uniform<T: Dim>(a: T, b: T) -> T
 ```
 ```
 
 
 ### `rand_int` (Discrete uniform distribution sampling)
 ### `rand_int` (Discrete uniform distribution sampling)
-Uniformly samples the integers in the interval \\( [a, b] \\).
+Uniformly samples integers from the interval \\( [a, b] \\).
 More information [here](https://en.wikipedia.org/wiki/Discrete_uniform_distribution).
 More information [here](https://en.wikipedia.org/wiki/Discrete_uniform_distribution).
 
 
 ```nbt
 ```nbt
@@ -301,7 +301,7 @@ fn rand_int(a: Scalar, b: Scalar) -> Scalar
 ```
 ```
 
 
 ### `rand_bernoulli` (Bernoulli distribution sampling)
 ### `rand_bernoulli` (Bernoulli distribution sampling)
-Samples a Bernoulli random variable, that is, \\( 1 \\) with probability \\( p \\), \\( 0 \\) with probability \\( 1-p \\). The parameter \\( p \\) must be a probability (\\( 0 \le p \le 1 \\)).
+Samples a Bernoulli random variable. That is, \\( 1 \\) with probability \\( p \\) and \\( 0 \\) with probability \\( 1-p \\). The parameter \\( p \\) must be a probability (\\( 0 \le p \le 1 \\)).
 More information [here](https://en.wikipedia.org/wiki/Bernoulli_distribution).
 More information [here](https://en.wikipedia.org/wiki/Bernoulli_distribution).
 
 
 ```nbt
 ```nbt
@@ -367,7 +367,23 @@ fn rand_pareto<T: Dim>(α: Scalar, min: T) -> T
 
 
 ## Number theory
 ## Number theory
 
 
-Defined in: `core::number_theory`
+Defined in: `math::number_theory`
+
+### `gcd` (Greatest common divisor)
+The largest positive integer that divides each of the integers \\( a \\) and \\( b \\).
+More information [here](https://en.wikipedia.org/wiki/Greatest_common_divisor).
+
+```nbt
+fn gcd(a: Scalar, b: Scalar) -> Scalar
+```
+
+### `lcm` (Least common multiple)
+The smallest positive integer that is divisible by both \\( a \\) and \\( b \\).
+More information [here](https://en.wikipedia.org/wiki/Least_common_multiple).
+
+```nbt
+fn lcm(a: Scalar, b: Scalar) -> Scalar
+```
 
 
 ## Numerical methods
 ## Numerical methods
 
 
@@ -386,7 +402,7 @@ Find the root of the function \\( f \\) in the interval \\( [x_1, x_2] \\) using
 More information [here](https://en.wikipedia.org/wiki/Bisection_method).
 More information [here](https://en.wikipedia.org/wiki/Bisection_method).
 
 
 ```nbt
 ```nbt
-fn root_bisect<A: Dim, B: Dim>(f: Fn[(A) -> B], x1: A, x2: A, x_tol: A, y_tol: B) -> A
+fn root_bisect<X: Dim, Y: Dim>(f: Fn[(X) -> Y], x1: X, x2: X, x_tol: X, y_tol: Y) -> X
 ```
 ```
 
 
 ### `root_newton` (Newton's method)
 ### `root_newton` (Newton's method)
@@ -394,7 +410,7 @@ Find the root of the function \\( f(x) \\) and its derivative \\( f'(x) \\) usin
 More information [here](https://en.wikipedia.org/wiki/Newton%27s_method).
 More information [here](https://en.wikipedia.org/wiki/Newton%27s_method).
 
 
 ```nbt
 ```nbt
-fn root_newton<A: Dim, B: Dim>(f: Fn[(A) -> B], f_prime: Fn[(A) -> B / A], x0: A, y_tol: B) -> A
+fn root_newton<X: Dim, Y: Dim>(f: Fn[(X) -> Y], f_prime: Fn[(X) -> Y / X], x0: X, y_tol: Y) -> X
 ```
 ```
 
 
 ## Geometry
 ## Geometry
@@ -402,36 +418,42 @@ fn root_newton<A: Dim, B: Dim>(f: Fn[(A) -> B], f_prime: Fn[(A) -> B / A], x0: A
 Defined in: `math::geometry`
 Defined in: `math::geometry`
 
 
 ### `hypot2`
 ### `hypot2`
+The length of the hypotenuse of a right-angled triangle \\( \sqrt{x^2+y^2} \\).
 
 
 ```nbt
 ```nbt
 fn hypot2<T: Dim>(x: T, y: T) -> T
 fn hypot2<T: Dim>(x: T, y: T) -> T
 ```
 ```
 
 
 ### `hypot3`
 ### `hypot3`
+The Euclidean norm of a 3D vector \\( \sqrt{x^2+y^2+z^2} \\).
 
 
 ```nbt
 ```nbt
 fn hypot3<T: Dim>(x: T, y: T, z: T) -> T
 fn hypot3<T: Dim>(x: T, y: T, z: T) -> T
 ```
 ```
 
 
 ### `circle_area`
 ### `circle_area`
+The area of a circle, \\( \pi r^2 \\).
 
 
 ```nbt
 ```nbt
 fn circle_area<L: Dim>(radius: L) -> L^2
 fn circle_area<L: Dim>(radius: L) -> L^2
 ```
 ```
 
 
 ### `circle_circumference`
 ### `circle_circumference`
+The circumference of a circle, \\( 2\pi r \\).
 
 
 ```nbt
 ```nbt
 fn circle_circumference<L: Dim>(radius: L) -> L
 fn circle_circumference<L: Dim>(radius: L) -> L
 ```
 ```
 
 
 ### `sphere_area`
 ### `sphere_area`
+The surface area of a sphere, \\( 4\pi r^2 \\).
 
 
 ```nbt
 ```nbt
 fn sphere_area<L: Dim>(radius: L) -> L^2
 fn sphere_area<L: Dim>(radius: L) -> L^2
 ```
 ```
 
 
 ### `sphere_volume`
 ### `sphere_volume`
+The volume of a sphere, \\( \frac{4}{3}\pi r^3 \\).
 
 
 ```nbt
 ```nbt
 fn sphere_volume<L: Dim>(radius: L) -> L^3
 fn sphere_volume<L: Dim>(radius: L) -> L^3

+ 15 - 0
book/src/list-functions-strings.md

@@ -3,90 +3,105 @@
 Defined in: `core::strings`
 Defined in: `core::strings`
 
 
 ### `str_length`
 ### `str_length`
+The length of a string.
 
 
 ```nbt
 ```nbt
 fn str_length(s: String) -> Scalar
 fn str_length(s: String) -> Scalar
 ```
 ```
 
 
 ### `str_slice`
 ### `str_slice`
+Subslice of a string.
 
 
 ```nbt
 ```nbt
 fn str_slice(s: String, start: Scalar, end: Scalar) -> String
 fn str_slice(s: String, start: Scalar, end: Scalar) -> String
 ```
 ```
 
 
 ### `chr`
 ### `chr`
+Get a single-character string from a Unicode code point. Example: `0x2764 -> chr`.
 
 
 ```nbt
 ```nbt
 fn chr(n: Scalar) -> String
 fn chr(n: Scalar) -> String
 ```
 ```
 
 
 ### `lowercase`
 ### `lowercase`
+Convert a string to lowercase.
 
 
 ```nbt
 ```nbt
 fn lowercase(s: String) -> String
 fn lowercase(s: String) -> String
 ```
 ```
 
 
 ### `uppercase`
 ### `uppercase`
+Convert a string to uppercase.
 
 
 ```nbt
 ```nbt
 fn uppercase(s: String) -> String
 fn uppercase(s: String) -> String
 ```
 ```
 
 
 ### `str_append`
 ### `str_append`
+Concatenate two strings.
 
 
 ```nbt
 ```nbt
 fn str_append(a: String, b: String) -> String
 fn str_append(a: String, b: String) -> String
 ```
 ```
 
 
 ### `str_find`
 ### `str_find`
+Find the first occurrence of a substring in a string.
 
 
 ```nbt
 ```nbt
 fn str_find(haystack: String, needle: String) -> Scalar
 fn str_find(haystack: String, needle: String) -> Scalar
 ```
 ```
 
 
 ### `str_contains`
 ### `str_contains`
+Check if a string contains a substring.
 
 
 ```nbt
 ```nbt
 fn str_contains(haystack: String, needle: String) -> Bool
 fn str_contains(haystack: String, needle: String) -> Bool
 ```
 ```
 
 
 ### `str_replace`
 ### `str_replace`
+Replace all occurrences of a substring in a string.
 
 
 ```nbt
 ```nbt
 fn str_replace(s: String, pattern: String, replacement: String) -> String
 fn str_replace(s: String, pattern: String, replacement: String) -> String
 ```
 ```
 
 
 ### `str_repeat`
 ### `str_repeat`
+Repeat the input string `n` times.
 
 
 ```nbt
 ```nbt
 fn str_repeat(a: String, n: Scalar) -> String
 fn str_repeat(a: String, n: Scalar) -> String
 ```
 ```
 
 
 ### `bin`
 ### `bin`
+Get a binary representation of a number. Example: `42 -> bin`.
 
 
 ```nbt
 ```nbt
 fn bin(x: Scalar) -> String
 fn bin(x: Scalar) -> String
 ```
 ```
 
 
 ### `oct`
 ### `oct`
+Get an octal representation of a number. Example: `42 -> oct`.
 
 
 ```nbt
 ```nbt
 fn oct(x: Scalar) -> String
 fn oct(x: Scalar) -> String
 ```
 ```
 
 
 ### `dec`
 ### `dec`
+Get a decimal representation of a number.
 
 
 ```nbt
 ```nbt
 fn dec(x: Scalar) -> String
 fn dec(x: Scalar) -> String
 ```
 ```
 
 
 ### `hex`
 ### `hex`
+Get a hexadecimal representation of a number. Example: `2^31-1 -> hex`.
 
 
 ```nbt
 ```nbt
 fn hex(x: Scalar) -> String
 fn hex(x: Scalar) -> String
 ```
 ```
 
 
 ### `base`
 ### `base`
+Convert a number to the given base. Example: `42 -> base(16)`.
 
 
 ```nbt
 ```nbt
 fn base(b: Scalar) -> Fn[(Scalar) -> String]
 fn base(b: Scalar) -> Fn[(Scalar) -> String]

+ 7 - 7
numbat/modules/core/functions.nbt

@@ -3,17 +3,17 @@
 fn id<A>(x: A) -> A = x
 fn id<A>(x: A) -> A = x
 
 
 @name("Absolute value")
 @name("Absolute value")
-@description("Return the absolute value of the input, $|x|$. This works for quantities, too: `abs(-5 m) = 5 m`.")
+@description("Return the absolute value $|x|$ of the input. This works for quantities, too: `abs(-5 m) = 5 m`.")
 @url("https://doc.rust-lang.org/std/primitive.f64.html#method.abs")
 @url("https://doc.rust-lang.org/std/primitive.f64.html#method.abs")
 fn abs<T: Dim>(x: T) -> T
 fn abs<T: Dim>(x: T) -> T
 
 
 @name("Square root")
 @name("Square root")
-@description("Return the square root of the input, $\\sqrt\{x\}$: `sqrt(121 m^2) = 11 m`.")
+@description("Return the square root $\\sqrt\{x\}$ of the input: `sqrt(121 m^2) = 11 m`.")
 @url("https://en.wikipedia.org/wiki/Square_root")
 @url("https://en.wikipedia.org/wiki/Square_root")
 fn sqrt<D: Dim>(x: D^2) -> D = x^(1/2)
 fn sqrt<D: Dim>(x: D^2) -> D = x^(1/2)
 
 
 @name("Cube root")
 @name("Cube root")
-@description("Return the cube root of the input, $\\sqrt[3]\{x\}$: `cbrt(8 m^3) = 2 m`.")
+@description("Return the cube root $\\sqrt[3]\{x\}$ of the input: `cbrt(8 m^3) = 2 m`.")
 @url("https://en.wikipedia.org/wiki/Cube_root")
 @url("https://en.wikipedia.org/wiki/Cube_root")
 fn cbrt<D: Dim>(x: D^3) -> D = x^(1/3)
 fn cbrt<D: Dim>(x: D^3) -> D = x^(1/3)
 
 
@@ -22,21 +22,21 @@ fn cbrt<D: Dim>(x: D^3) -> D = x^(1/3)
 fn sqr<D: Dim>(x: D) -> D^2 = x^2
 fn sqr<D: Dim>(x: D) -> D^2 = x^2
 
 
 @name("Rounding")
 @name("Rounding")
-@description("Round to the nearest integer. If the value is half-way between two integers, round away from 0.")
+@description("Round to the nearest integer. If the value is half-way between two integers, round away from $0$.")
 @url("https://doc.rust-lang.org/std/primitive.f64.html#method.round")
 @url("https://doc.rust-lang.org/std/primitive.f64.html#method.round")
 fn round<T: Dim>(x: T) -> T
 fn round<T: Dim>(x: T) -> T
 
 
 @name("Floor function")
 @name("Floor function")
-@description("Returns the largest integer less than or equal to `x`.")
+@description("Returns the largest integer less than or equal to $x$.")
 @url("https://doc.rust-lang.org/std/primitive.f64.html#method.floor")
 @url("https://doc.rust-lang.org/std/primitive.f64.html#method.floor")
 fn floor<T: Dim>(x: T) -> T
 fn floor<T: Dim>(x: T) -> T
 
 
 @name("Ceil function")
 @name("Ceil function")
-@description("Returns the smallest integer greater than or equal to `x`.")
+@description("Returns the smallest integer greater than or equal to $x$.")
 @url("https://doc.rust-lang.org/std/primitive.f64.html#method.ceil")
 @url("https://doc.rust-lang.org/std/primitive.f64.html#method.ceil")
 fn ceil<T: Dim>(x: T) -> T
 fn ceil<T: Dim>(x: T) -> T
 
 
 @name("Modulo")
 @name("Modulo")
-@description("Calculates the least nonnegative remainder of `a (mod b)`.")
+@description("Calculates the least nonnegative remainder of $a (\\mod b)$.")
 @url("https://doc.rust-lang.org/std/primitive.f64.html#method.rem_euclid")
 @url("https://doc.rust-lang.org/std/primitive.f64.html#method.rem_euclid")
 fn mod<T: Dim>(a: T, b: T) -> T
 fn mod<T: Dim>(a: T, b: T) -> T

+ 20 - 0
numbat/modules/core/strings.nbt

@@ -2,17 +2,25 @@ use core::scalar
 use core::functions
 use core::functions
 use core::error
 use core::error
 
 
+@description("The length of a string")
 fn str_length(s: String) -> Scalar
 fn str_length(s: String) -> Scalar
 
 
+@description("Subslice of a string")
 fn str_slice(s: String, start: Scalar, end: Scalar) -> String
 fn str_slice(s: String, start: Scalar, end: Scalar) -> String
 
 
+@description("Get a single-character string from a Unicode code point. Example: `0x2764 -> chr`")
 fn chr(n: Scalar) -> String
 fn chr(n: Scalar) -> String
 
 
+@description("Convert a string to lowercase")
 fn lowercase(s: String) -> String
 fn lowercase(s: String) -> String
+
+@description("Convert a string to uppercase")
 fn uppercase(s: String) -> String
 fn uppercase(s: String) -> String
 
 
+@description("Concatenate two strings")
 fn str_append(a: String, b: String) -> String = "{a}{b}"
 fn str_append(a: String, b: String) -> String = "{a}{b}"
 
 
+@description("Find the first occurrence of a substring in a string")
 fn str_find(haystack: String, needle: String) -> Scalar =
 fn str_find(haystack: String, needle: String) -> Scalar =
   if str_length(haystack) == 0
   if str_length(haystack) == 0
     then -1
     then -1
@@ -22,9 +30,11 @@ fn str_find(haystack: String, needle: String) -> Scalar =
         then -1
         then -1
         else 1 + str_find(str_slice(haystack, 1, str_length(haystack)), needle)
         else 1 + str_find(str_slice(haystack, 1, str_length(haystack)), needle)
 
 
+@description("Check if a string contains a substring")
 fn str_contains(haystack: String, needle: String) -> Bool =
 fn str_contains(haystack: String, needle: String) -> Bool =
   str_find(haystack, needle) != -1
   str_find(haystack, needle) != -1
 
 
+@description("Replace all occurrences of a substring in a string")
 fn str_replace(s: String, pattern: String, replacement: String) -> String =
 fn str_replace(s: String, pattern: String, replacement: String) -> String =
   if pattern == ""
   if pattern == ""
     then s
     then s
@@ -34,6 +44,7 @@ fn str_replace(s: String, pattern: String, replacement: String) -> String =
                else str_append(str_slice(s, 0, 1), str_replace(str_slice(s, 1, str_length(s)), pattern, replacement))
                else str_append(str_slice(s, 0, 1), str_replace(str_slice(s, 1, str_length(s)), pattern, replacement))
            else s
            else s
 
 
+@description("Repeat the input string `n` times")
 fn str_repeat(a: String, n: Scalar) -> String =
 fn str_repeat(a: String, n: Scalar) -> String =
   if n > 0
   if n > 0
     then str_append(a, str_repeat(a, n - 1))
     then str_append(a, str_repeat(a, n - 1))
@@ -60,15 +71,24 @@ fn _number_in_base(x: Scalar, b: Scalar) -> String =
       then _digit_in_base(x, b)
       then _digit_in_base(x, b)
       else str_append(_number_in_base(floor(x / b), b), _digit_in_base(mod(x, b), b))
       else str_append(_number_in_base(floor(x / b), b), _digit_in_base(mod(x, b), b))
 
 
+@description("Get a binary representation of a number. Example: `42 -> bin`")
 fn bin(x: Scalar) -> String = if x < 0 then "-{bin(-x)}" else "0b{_number_in_base(x, 2)}"
 fn bin(x: Scalar) -> String = if x < 0 then "-{bin(-x)}" else "0b{_number_in_base(x, 2)}"
+
+@description("Get an octal representation of a number. Example: `42 -> oct`")
 fn oct(x: Scalar) -> String = if x < 0 then "-{oct(-x)}" else "0o{_number_in_base(x, 8)}"
 fn oct(x: Scalar) -> String = if x < 0 then "-{oct(-x)}" else "0o{_number_in_base(x, 8)}"
+
+@description("Get a decimal representation of a number.")
 fn dec(x: Scalar) -> String = _number_in_base(x, 10)
 fn dec(x: Scalar) -> String = _number_in_base(x, 10)
+
+@description("Get a hexadecimal representation of a number. Example: `2^31-1 -> hex`")
 fn hex(x: Scalar) -> String = if x < 0 then "-{hex(-x)}" else "0x{_number_in_base(x, 16)}"
 fn hex(x: Scalar) -> String = if x < 0 then "-{hex(-x)}" else "0x{_number_in_base(x, 16)}"
 
 
 # TODO: once we have anonymous functions / closures, we can implement base in a way
 # TODO: once we have anonymous functions / closures, we can implement base in a way
 # that it returns a partially-applied version of '_number_in_base'. This would allow
 # that it returns a partially-applied version of '_number_in_base'. This would allow
 # arbitrary 'x -> base(b)' conversions.
 # arbitrary 'x -> base(b)' conversions.
 fn _not_implemented(unused: Scalar) -> String = error("bases other than 2, 8, 10, and 16 are currently not implemented")
 fn _not_implemented(unused: Scalar) -> String = error("bases other than 2, 8, 10, and 16 are currently not implemented")
+
+@description("Convert a number to the given base. Example: `42 -> base(16)`")
 fn base(b: Scalar) -> Fn[(Scalar) -> String] =
 fn base(b: Scalar) -> Fn[(Scalar) -> String] =
   if b == 2
   if b == 2
     then bin
     then bin

+ 2 - 2
numbat/modules/math/distributions.nbt

@@ -17,7 +17,7 @@ fn rand_uniform<T: Dim>(a: T, b: T) -> T =
 
 
 @name("Discrete uniform distribution sampling")
 @name("Discrete uniform distribution sampling")
 @url("https://en.wikipedia.org/wiki/Discrete_uniform_distribution")
 @url("https://en.wikipedia.org/wiki/Discrete_uniform_distribution")
-@description("Uniformly samples the integers in the interval $[a, b]$.")
+@description("Uniformly samples integers from the interval $[a, b]$.")
 fn rand_int(a: Scalar, b: Scalar) -> Scalar =
 fn rand_int(a: Scalar, b: Scalar) -> Scalar =
     if a <= b
     if a <= b
     then floor( random() * (floor(b) - ceil(a) + 1) ) + ceil(a)
     then floor( random() * (floor(b) - ceil(a) + 1) ) + ceil(a)
@@ -25,7 +25,7 @@ fn rand_int(a: Scalar, b: Scalar) -> Scalar =
 
 
 @name("Bernoulli distribution sampling")
 @name("Bernoulli distribution sampling")
 @url("https://en.wikipedia.org/wiki/Bernoulli_distribution")
 @url("https://en.wikipedia.org/wiki/Bernoulli_distribution")
-@description("Samples a Bernoulli random variable, that is, $1$ with probability $p$, $0$ with probability $1-p$. The parameter $p$ must be a probability ($0 \le p \le 1$).")
+@description("Samples a Bernoulli random variable. That is, $1$ with probability $p$ and $0$ with probability $1-p$. The parameter $p$ must be a probability ($0 \le p \le 1$).")
 fn rand_bernoulli(p: Scalar) -> Scalar =
 fn rand_bernoulli(p: Scalar) -> Scalar =
     if p>=0 && p<=1
     if p>=0 && p<=1
     then (if random() < p
     then (if random() < p

+ 10 - 0
numbat/modules/math/geometry.nbt

@@ -1,14 +1,24 @@
 use core::functions
 use core::functions
 use math::constants
 use math::constants
 
 
+@description("The length of the hypotenuse of a right-angled triangle $\\sqrt\{x^2+y^2\}$.")
 fn hypot2<T: Dim>(x: T, y: T) -> T = sqrt(x^2 + y^2)
 fn hypot2<T: Dim>(x: T, y: T) -> T = sqrt(x^2 + y^2)
+
+@description("The Euclidean norm of a 3D vector $\\sqrt\{x^2+y^2+z^2\}$.")
 fn hypot3<T: Dim>(x: T, y: T, z: T) -> T = sqrt(x^2 + y^2 + z^2)
 fn hypot3<T: Dim>(x: T, y: T, z: T) -> T = sqrt(x^2 + y^2 + z^2)
 
 
 # The following functions use a generic dimension instead of
 # The following functions use a generic dimension instead of
 # 'Length' in order to allow for computations in pixels, for
 # 'Length' in order to allow for computations in pixels, for
 # example
 # example
 
 
+@description("The area of a circle, $\\pi r^2$.")
 fn circle_area<L: Dim>(radius: L) -> L^2 = π × radius^2
 fn circle_area<L: Dim>(radius: L) -> L^2 = π × radius^2
+
+@description("The circumference of a circle, $2\\pi r$.")
 fn circle_circumference<L: Dim>(radius: L) -> L = 2 π × radius
 fn circle_circumference<L: Dim>(radius: L) -> L = 2 π × radius
+
+@description("The surface area of a sphere, $4\\pi r^2$.")
 fn sphere_area<L: Dim>(radius: L) -> L^2 = 4 π × radius^2
 fn sphere_area<L: Dim>(radius: L) -> L^2 = 4 π × radius^2
+
+@description("The volume of a sphere, $\\frac\{4\}\{3\}\\pi r^3$.")
 fn sphere_volume<L: Dim>(radius: L) -> L^3 = 4/3 × π × radius^3
 fn sphere_volume<L: Dim>(radius: L) -> L^3 = 4/3 × π × radius^3

+ 2 - 0
numbat/modules/math/number_theory.nbt

@@ -2,6 +2,7 @@ use core::scalar
 use core::functions
 use core::functions
 
 
 @name("Greatest common divisor")
 @name("Greatest common divisor")
+@description("The largest positive integer that divides each of the integers $a$ and $b$.")
 @url("https://en.wikipedia.org/wiki/Greatest_common_divisor")
 @url("https://en.wikipedia.org/wiki/Greatest_common_divisor")
 fn gcd(a: Scalar, b: Scalar) -> Scalar =
 fn gcd(a: Scalar, b: Scalar) -> Scalar =
   if b == 0
   if b == 0
@@ -9,5 +10,6 @@ fn gcd(a: Scalar, b: Scalar) -> Scalar =
     else gcd(b, mod(a, b))
     else gcd(b, mod(a, b))
 
 
 @name("Least common multiple")
 @name("Least common multiple")
+@description("The smallest positive integer that is divisible by both $a$ and $b$.")
 @url("https://en.wikipedia.org/wiki/Least_common_multiple")
 @url("https://en.wikipedia.org/wiki/Least_common_multiple")
 fn lcm(a: Scalar, b: Scalar) -> Scalar = abs(a * b) / gcd(a, b)
 fn lcm(a: Scalar, b: Scalar) -> Scalar = abs(a * b) / gcd(a, b)

+ 3 - 3
numbat/modules/numerics/solve.nbt

@@ -4,7 +4,7 @@ use core::error
 @name("Bisection method")
 @name("Bisection method")
 @url("https://en.wikipedia.org/wiki/Bisection_method")
 @url("https://en.wikipedia.org/wiki/Bisection_method")
 @description("Find the root of the function $f$ in the interval $[x_1, x_2]$ using the bisection method. The function $f$ must be continuous and $f(x_1) \cdot f(x_2) < 0$.")
 @description("Find the root of the function $f$ in the interval $[x_1, x_2]$ using the bisection method. The function $f$ must be continuous and $f(x_1) \cdot f(x_2) < 0$.")
-fn root_bisect<A: Dim, B: Dim>(f: Fn[(A) -> B], x1: A, x2: A, x_tol: A, y_tol: B) -> A =
+fn root_bisect<X: Dim, Y: Dim>(f: Fn[(X) -> Y], x1: X, x2: X, x_tol: X, y_tol: Y) -> X =
   if abs(x1 - x2) < x_tol
   if abs(x1 - x2) < x_tol
     then (x1 + x2) / 2
     then (x1 + x2) / 2
     else if abs(f((x1 + x2) / 2)) < y_tol
     else if abs(f((x1 + x2) / 2)) < y_tol
@@ -14,7 +14,7 @@ fn root_bisect<A: Dim, B: Dim>(f: Fn[(A) -> B], x1: A, x2: A, x_tol: A, y_tol: B
         else root_bisect(f, (x1 + x2) / 2, x2, x_tol, y_tol)
         else root_bisect(f, (x1 + x2) / 2, x2, x_tol, y_tol)
   # TODO: move (x1 + x2) / 2 to a local variable once we support them
   # TODO: move (x1 + x2) / 2 to a local variable once we support them
 
 
-fn _root_newton_helper<A: Dim, B: Dim>(f: Fn[(A) -> B], f_prime: Fn[(A) -> B/A], x0: A, y_tol: B, max_iterations: Scalar) -> A =
+fn _root_newton_helper<X: Dim, Y: Dim>(f: Fn[(X) -> Y], f_prime: Fn[(X) -> Y / X], x0: X, y_tol: Y, max_iterations: Scalar) -> X =
   if max_iterations <= 0
   if max_iterations <= 0
     then error("root_newton: Maximum number of iterations reached. Try another initial guess?")
     then error("root_newton: Maximum number of iterations reached. Try another initial guess?")
     else if abs(f(x0)) < y_tol
     else if abs(f(x0)) < y_tol
@@ -24,5 +24,5 @@ fn _root_newton_helper<A: Dim, B: Dim>(f: Fn[(A) -> B], f_prime: Fn[(A) -> B/A],
 @name("Newton's method")
 @name("Newton's method")
 @url("https://en.wikipedia.org/wiki/Newton%27s_method") 
 @url("https://en.wikipedia.org/wiki/Newton%27s_method") 
 @description("Find the root of the function $f(x)$ and its derivative $f'(x)$ using Newton's method.")
 @description("Find the root of the function $f(x)$ and its derivative $f'(x)$ using Newton's method.")
-fn root_newton<A: Dim, B: Dim>(f: Fn[(A) -> B], f_prime: Fn[(A) -> B/A], x0: A, y_tol: B) -> A =
+fn root_newton<X: Dim, Y: Dim>(f: Fn[(X) -> Y], f_prime: Fn[(X) -> Y / X], x0: X, y_tol: Y) -> X =
   _root_newton_helper(f, f_prime, x0, y_tol, 10_000)
   _root_newton_helper(f, f_prime, x0, y_tol, 10_000)