# MathUtils
A high-performance, zero-dependency Rust crate that mirrors JavaScript's built-in `Math` object with exact ECMAScript 2024 semantics.
[](https://crates.io)
[](#-documentation)
[](#-license)
---
## ✨ Features
- **Exact ECMAScript Semantics**: Full fidelity with JavaScript `Math`, including subtle IEEE 754 edge cases:
- `Math::round(-0.5) == -0.0` (tie-breaking towards $+\infty$)
- `Math::sign(-0.0) == -0.0` and `Math::sign(+0.0) == +0.0`
- `Math::pow(NaN, 0.0) == 1.0` and `Math::pow(1.0, Infinity) == NaN`
- `Math::hypot` with $\pm\infty$ overriding `NaN`
- **Complete Constant Set**: `E`, `LN10`, `LN2`, `LOG10E`, `LOG2E`, `PI`, `SQRT1_2`, `SQRT2` (with snake_case aliases).
- **All JavaScript Methods**: `abs`, `acos`, `acosh`, `asin`, `asinh`, `atan`, `atan2`, `atanh`, `cbrt`, `ceil`, `clz32`, `cos`, `cosh`, `exp`, `expm1`, `floor`, `fround`, `f16round` (ES2024), `hypot`, `imul`, `log`, `log1p`, `log10`, `log2`, `max`, `min`, `pow`, `random`, `round`, `sign`, `sin`, `sinh`, `sqrt`, `sumPrecise` (ES2024), `tan`, `tanh`, `trunc`.
- **Zero External Dependencies**: Pure Rust standard library.
- **Fast, Thread-Safe PRNG**: High-performance Xoshiro256++ generator for `Math::random()` with thread-local state and seedable testing support.
- **Variadic Macros**: `math_max!`, `math_min!`, `math_hypot!` providing variadic JavaScript-style calling ergonomics.
- **Clean `Math` Namespace**: Access all constants and methods directly through the `Math` struct (`Math::cos(...)`, `Math::PI`, `Math::round(...)`), mirroring JavaScript's syntax.
---
## 📦 Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
MathUtils = "1.0.1"
```
Or run via `cargo`:
```bash
cargo add MathUtils
```
---
## 🚀 Quick Start
```rust
use MathUtils::{Math, math_max, math_min, math_hypot};
fn main() {
// 1. Exact JavaScript Rounding
assert_eq!(Math::round(-0.5), -0.0);
assert_eq!(Math::round(1.5), 2.0);
assert_eq!(Math::round(-1.5), -1.0);
// 2. Constants & Trigonometry
println!("Pi: {}", Math::PI);
println!("Cos(0): {}", Math::cos(0.0));
println!("Atan2(0, -0): {}", Math::atan2(0.0, -0.0)); // Pi
// 3. Integer Operations & Type Coercion
assert_eq!(Math::imul(0xffff_ffffu32, 5), -5);
assert_eq!(Math::clz32(1000.0), 22);
// 4. IEEE 754 Float Conversions
assert_eq!(Math::fround(1.337), 1.3370000123977661);
assert_eq!(Math::f16round(Math::PI), 3.140625);
// 5. Compensated Exact Summation (ES2024 Math.sumPrecise)
let numbers = [1e16, 1.0, -1e16];
assert_eq!(Math::sumPrecise(&numbers), 1.0);
// 6. Variadic Macros
assert_eq!(math_max!(1.0, 99.5, -42.0), 99.5);
assert_eq!(math_min!(1.0, 99.5, -42.0), -42.0);
assert_eq!(math_hypot!(3.0, 4.0), 5.0);
// 7. Pseudo-random Number Generation
let r = Math::random();
println!("Random in [0, 1): {}", r);
}
```
---
## 📚 Documentation
You can generate and view the complete HTML API documentation locally by running:
```bash
cargo doc --no-deps --open
```
---
## 📖 API Reference
### Constants
| `Math::E` | `2.718281828459045` | Euler's constant and base of natural logarithms |
| `Math::LN10` / `Math::LN_10` | `2.302585092994046` | Natural logarithm of 10 |
| `Math::LN2` / `Math::LN_2` | `0.6931471805599453` | Natural logarithm of 2 |
| `Math::LOG10E` / `Math::LOG10_E` | `0.4342944819032518` | Base-10 logarithm of E |
| `Math::LOG2E` / `Math::LOG2_E` | `1.4426950408889634` | Base-2 logarithm of E |
| `Math::PI` | `3.141592653589793` | Ratio of circumference to diameter |
| `Math::SQRT1_2` / `Math::SQRT_1_2` | `0.7071067811865476` | Square root of 1/2 |
| `Math::SQRT2` / `Math::SQRT_2` | `1.4142135623730951` | Square root of 2 |
### Methods
| `abs` | `(x: f64) -> f64` | Absolute value (preserves `NaN`, converts `-0.0` to `+0.0`) |
| `acos` | `(x: f64) -> f64` | Arccosine in radians |
| `acosh` | `(x: f64) -> f64` | Hyperbolic arccosine |
| `asin` | `(x: f64) -> f64` | Arcsine in radians |
| `asinh` | `(x: f64) -> f64` | Hyperbolic arcsine |
| `atan` | `(x: f64) -> f64` | Arctangent in radians |
| `atanh` | `(x: f64) -> f64` | Hyperbolic arctangent |
| `atan2` | `(y: f64, x: f64) -> f64` | 4-quadrant arctangent of $y/x$ |
| `cbrt` | `(x: f64) -> f64` | Cube root |
| `ceil` | `(x: f64) -> f64` | Smallest integer $\ge x$ |
| `clz32` | `<T: ToJsUint32>(x: T) -> u32` | Number of leading zero bits in 32-bit binary representation |
| `cos` | `(x: f64) -> f64` | Cosine in radians |
| `cosh` | `(x: f64) -> f64` | Hyperbolic cosine |
| `exp` | `(x: f64) -> f64` | $e^x$ |
| `expm1` | `(x: f64) -> f64` | $e^x - 1$ |
| `floor` | `(x: f64) -> f64` | Largest integer $\le x$ |
| `fround` | `(x: f64) -> f64` | Round to nearest IEEE 754 32-bit float |
| `f16round` | `(x: f64) -> f64` | Round to nearest IEEE 754 16-bit half-precision float (ES2024) |
| `hypot` | `(values: &[f64]) -> f64` | Square root of sum of squares ($\pm\infty$ overrides `NaN`) |
| `hypot2` | `(x: f64, y: f64) -> f64` | 2-argument hypotenuse |
| `imul` | `<A: ToJsInt32, B: ToJsInt32>(a: A, b: B) -> i32` | 32-bit integer multiplication |
| `log` | `(x: f64) -> f64` | Natural logarithm $\ln(x)$ |
| `log1p` / `log_1p` | `(x: f64) -> f64` | $\ln(1 + x)$ |
| `log10` / `log_10` | `(x: f64) -> f64` | Base-10 logarithm |
| `log2` / `log_2` | `(x: f64) -> f64` | Base-2 logarithm |
| `max` | `(values: &[f64]) -> f64` | Maximum element (empty returns $-\infty$, preserves zero signs) |
| `max2` | `(a: f64, b: f64) -> f64` | 2-argument maximum |
| `min` | `(values: &[f64]) -> f64` | Minimum element (empty returns $+\infty$, preserves zero signs) |
| `min2` | `(a: f64, b: f64) -> f64` | 2-argument minimum |
| `pow` | `(base: f64, exponent: f64) -> f64` | $base^{exponent}$ with ECMA-262 edge-case handling |
| `random` | `() -> f64` | Pseudo-random float in $[0.0, 1.0)$ |
| `seed_random` | `(seed: u64)` | Reseed thread-local PRNG for deterministic testing |
| `round` | `(x: f64) -> f64` | ECMAScript half-up rounding (`round(-0.5) == -0.0`) |
| `sign` | `(x: f64) -> f64` | Sign of number (`+1.0`, `-1.0`, `+0.0`, `-0.0`, `NaN`) |
| `sin` | `(x: f64) -> f64` | Sine in radians |
| `sinh` | `(x: f64) -> f64` | Hyperbolic sine |
| `sqrt` | `(x: f64) -> f64` | Square root |
| `sumPrecise` / `sum_precise` | `<I>(items: I) -> f64` | Shewchuk exact compensated summation (ES2024) |
| `tan` | `(x: f64) -> f64` | Tangent in radians |
| `tanh` | `(x: f64) -> f64` | Hyperbolic tangent |
| `trunc` | `(x: f64) -> f64` | Truncate fractional digits |
---
## 🔍 JavaScript vs. Standard Rust Floating-Point Differences Handled
| `round(-0.5)` | `-1.0` (round half away from 0) | `-0.0` (round half toward $+\infty$) | Preserves `-0.0` sign |
| `round(-1.5)` | `-2.0` | `-1.0` | Ties break towards $+\infty$ |
| `sign(-0.0)` | `-1.0` | `-0.0` | Preserves zero signs |
| `pow(NaN, 0.0)` | `1.0` or `NaN` (platform dependent) | `1.0` | Explicitly mandated by ECMA-262 |
| `pow(1.0, Infinity)` | `1.0` (IEEE 754-2008) | `NaN` | Explicitly mandated by ECMA-262 |
| `pow(-1.0, Infinity)` | `1.0` (IEEE 754-2008) | `NaN` | Explicitly mandated by ECMA-262 |
| `hypot(&[Infinity, NaN])` | `NaN` in standard slices | `Infinity` | ECMA-262 specifies $\pm\infty$ overrides `NaN` |
| `max(&[])` | N/A (panics or returns `None`) | `-Infinity` | Matches JS `Math.max()` |
| `min(&[])` | N/A (panics or returns `None`) | `+Infinity` | Matches JS `Math.min()` |
---
## 📜 License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.