1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//! Declarative macros providing JavaScript-like variadic function invocation.
//!
//! In JavaScript, functions such as `Math.max()`, `Math.min()`, and `Math.hypot()` accept an
//! arbitrary number of arguments (e.g., `Math.max(1, 5, 2, 9, -3)`). In Rust, functions have a fixed
//! arity. These macros bridge that gap by accepting 0, 1, 2, or $N$ arguments of any numeric type,
//! automatically casting them to `f64` and applying the exact ECMAScript rules.
/// Computes the maximum value among zero or more numeric arguments.
///
/// Mirrors JavaScript's variadic `Math.max(...values)`.
///
/// # Behavior
///
/// - **Zero arguments (`math_max!()`)**: Returns $-\infty$ (`f64::NEG_INFINITY`), exactly matching JavaScript.
/// - **One argument (`math_max!(x)`)**: Returns `x as f64`.
/// - **Two arguments (`math_max!(x, y)`)**: Evaluates `Math::max2(x, y)`.
/// - **Multiple arguments (`math_max!(a, b, c, ...)`)**: Evaluates `Math::max(&[a, b, c, ...])`.
/// - **Special Values**:
/// - If any argument is `NaN`, returns `NaN`.
/// - If comparing `+0.0` and `-0.0`, `+0.0` is strictly chosen as the maximum (`math_max!(-0.0, 0.0) == 0.0`).
///
/// # Examples
///
/// ```
/// use MathUtils::math_max;
///
/// // Zero arguments yields negative infinity:
/// assert_eq!(math_max!(), f64::NEG_INFINITY);
///
/// // Single value:
/// assert_eq!(math_max!(42.0), 42.0);
///
/// // Multiple integer and float expressions:
/// assert_eq!(math_max!(1.5, 9.8, -3.2, 14.0, 7.1), 14.0);
/// assert_eq!(math_max!(10, 20, 5), 20.0);
///
/// // Handling NaN:
/// assert!(math_max!(1.0, f64::NAN, 5.0).is_nan());
///
/// // Positive zero is greater than negative zero:
/// let res = math_max!(-0.0, 0.0);
/// assert_eq!(res, 0.0);
/// assert!(res.is_sign_positive());
/// ```
/// Computes the minimum value among zero or more numeric arguments.
///
/// Mirrors JavaScript's variadic `Math.min(...values)`.
///
/// # Behavior
///
/// - **Zero arguments (`math_min!()`)**: Returns $+\infty$ (`f64::INFINITY`), exactly matching JavaScript.
/// - **One argument (`math_min!(x)`)**: Returns `x as f64`.
/// - **Two arguments (`math_min!(x, y)`)**: Evaluates `Math::min2(x, y)`.
/// - **Multiple arguments (`math_min!(a, b, c, ...)`)**: Evaluates `Math::min(&[a, b, c, ...])`.
/// - **Special Values**:
/// - If any argument is `NaN`, returns `NaN`.
/// - If comparing `+0.0` and `-0.0`, `-0.0` is strictly chosen as the minimum (`math_min!(0.0, -0.0) == -0.0`).
///
/// # Examples
///
/// ```
/// use MathUtils::math_min;
///
/// // Zero arguments yields positive infinity:
/// assert_eq!(math_min!(), f64::INFINITY);
///
/// // Single value:
/// assert_eq!(math_min!(42.0), 42.0);
///
/// // Multiple values:
/// assert_eq!(math_min!(1.5, 9.8, -3.2, 14.0, 7.1), -3.2);
/// assert_eq!(math_min!(10, 20, 5), 5.0);
///
/// // Handling NaN:
/// assert!(math_min!(1.0, f64::NAN, 5.0).is_nan());
///
/// // Negative zero is less than positive zero:
/// let res = math_min!(0.0, -0.0);
/// assert_eq!(res, 0.0);
/// assert!(res.is_sign_negative());
/// ```
/// Computes the square root of the sum of squares of zero or more numbers ($\sqrt{x_1^2 + x_2^2 + \dots + x_n^2}$).
///
/// Mirrors JavaScript's variadic `Math.hypot(...values)`.
///
/// # Behavior
///
/// - **Zero arguments (`math_hypot!()`)**: Returns `0.0`.
/// - **One argument (`math_hypot!(x)`)**: Returns the absolute value $|x|$.
/// - **Two or more arguments**: Computes $\sqrt{\sum x_i^2}$ using intermediate scaling to avoid overflow or underflow.
/// - **Special Values**:
/// - If any argument is $+-\infty$, returns $+\infty$ (even if another argument is `NaN`).
/// - If any argument is `NaN` and no argument is infinite, returns `NaN`.
///
/// # Examples
///
/// ```
/// use MathUtils::math_hypot;
///
/// // 2D Euclidean distance (Pythagorean 3-4-5 triangle):
/// assert_eq!(math_hypot!(3.0, 4.0), 5.0);
///
/// // 3D Euclidean distance:
/// assert_eq!(math_hypot!(1.0, 2.0, 2.0), 3.0);
///
/// // Empty arguments:
/// assert_eq!(math_hypot!(), 0.0);
///
/// // Infinity overrides NaN:
/// assert_eq!(math_hypot!(f64::INFINITY, f64::NAN), f64::INFINITY);
/// ```