mech-math 0.3.3

Math library for the Mech language
Documentation
math/mod
===============================================================================

%% Element-wise remainder (modulo)

1. Usage
-------------------------------------------------------------------------------

```mech:disabled
Y := math/mod(X1, X2)
```

2. Description
-------------------------------------------------------------------------------

Computes the element-wise remainder of dividing `X1` by `X2`. Inputs may be scalars, vectors, or matrices. When one input is a scalar and the other is an array, the scalar is applied to every element (scalar broadcasting). Vector–matrix row/column operations follow the rules in **Details**.

> Note: For floating-point inputs, this operation uses **remainder** semantics (like many programming languages), where the sign of the result typically follows the dividend (`X1`). For integers, it is the integer remainder. Division by zero is not allowed.

3. Input
-------------------------------------------------------------------------------

| Argument | Kind                                   | Description                                                                 |
|----------|----------------------------------------|-----------------------------------------------------------------------------|
| `X1`     | `int`, `uint`, `float`, `[T]`, `[[T]]` | Dividend. Supports scalars, vectors, and matrices.                          |
| `X2`     | `int`, `uint`, `float`, `[T]`, `[[T]]` | Divisor. Must be shape-compatible with `X1` under broadcasting.             |

**Supported scalar types**: `i8`, `i16`, `i32`, `i64`, `i128`, `u8`, `u16`, `u32`, `u64`, `u128`, `f32`, `f64`.

4. Output
-------------------------------------------------------------------------------

| Argument | Kind            | Description                                                                     |
|----------|-----------------|---------------------------------------------------------------------------------|
| `Y`      | matches input   | Element-wise remainder of `X1 % X2`. The shape of `Y` follows broadcasting.     |

5. Examples
-------------------------------------------------------------------------------

(a) Remainder of two scalars (integers)

```mech:ex1
y := math/mod(17, 5)        // 2
```

(b) Remainder with negatives (sign follows dividend)

```mech:ex2
y1 := math/mod(-17, 5)      // -2
y2 := math/mod(17, -5)      // 2
```

(c) Floating-point remainder

```mech:ex3
y := math/mod(5.5, 2.0)     // 1.5
```

(d) Vector-by-vector

```mech:ex4
a := [10, 20, 30]
b := [3,  7,  8]
y := math/mod(a, b)         // [1, 6, 6]
```

(e) Matrix-by-matrix

```mech:ex5
m1 := [10, 20; 31, 42]
m2 := [ 4,  6;  5,  9]
y  := math/mod(m1, m2)      // [2, 2; 1, 6]
```

(f) Matrix by scalar (scalar broadcasting)

```mech:ex6
m := [10, 20; 31, 42]
y := math/mod(m, 7)         // [3, 6; 3, 0]
```

(g) Column-vector with matrix (broadcast by columns)

```mech:ex7
v := [2, 5]                 // length 2 column vector
m := [10, 21; 33, 44]       // 2x2
y := math/mod(m, v)         // [[0, 1]; [3, 4]]
```

(h) Row-vector with matrix (broadcast by rows)

```mech:ex8
r := [4, 6]
m := [10, 21; 33, 44]
y := math/mod(r, m)         // [[4%10, 6%21]; [4%33, 6%44]] => [[4, 6]; [4, 6]]
```

6. Details
-------------------------------------------------------------------------------

**Element-wise semantics.** Remainder is computed per element. Shapes must either match exactly or be compatible via broadcasting.

**Broadcasting rules.**
- **Scalar % Array or Array % Scalar:** The scalar is applied to every element.
- **Matrix % Column Vector / Column Vector % Matrix:** A length-`m` vector can be used with an `m×n` matrix column-wise.
- **Matrix % Row Vector / Row Vector % Matrix:** A length-`n` vector can be used with an `m×n` matrix row-wise.

**Integer vs floating-point.**
- **Integers:** Computes the integer remainder. `x % 0` is invalid and raises an error.
- **Floats:** Computes the floating-point remainder. The result typically has the same sign as `x`. Remainder by zero is invalid.

**Common uses.**
- Index wrapping, periodic patterns, bucketization, and phase folding.

**Errors.**
- Division (modulus) by zero.
- Shape mismatch that cannot be resolved by broadcasting.
- Unsupported type combination.