runmat_runtime/
constants.rs

1//! Mathematical constants and special values
2//!
3//! This module provides language-compatible mathematical constants like pi, e, inf, nan, etc.
4//! These are registered as global constants that can be accessed as variables.
5
6use runmat_builtins::Value;
7use runmat_macros::runtime_builtin;
8
9/// Logical scalar true (language-compatible)
10#[runtime_builtin(name = "true")]
11fn true_builtin() -> Result<bool, String> {
12    Ok(true)
13}
14
15/// Logical scalar false (language-compatible)
16#[runtime_builtin(name = "false")]
17fn false_builtin() -> Result<bool, String> {
18    Ok(false)
19}
20
21/// Mathematical constant π (pi)
22#[runtime_builtin(name = "pi")]
23fn pi_builtin() -> Result<f64, String> {
24    Ok(std::f64::consts::PI)
25}
26
27/// Mathematical constant e (Euler's number)
28#[runtime_builtin(name = "e")]
29fn e_builtin() -> Result<f64, String> {
30    Ok(std::f64::consts::E)
31}
32
33/// Positive infinity
34#[runtime_builtin(name = "inf")]
35fn inf_builtin() -> Result<f64, String> {
36    Ok(f64::INFINITY)
37}
38
39/// Not-a-Number (NaN)
40#[runtime_builtin(name = "nan")]
41fn nan_builtin() -> Result<f64, String> {
42    Ok(f64::NAN)
43}
44
45/// Machine epsilon for double precision
46#[runtime_builtin(name = "eps")]
47fn eps_builtin() -> Result<f64, String> {
48    Ok(f64::EPSILON)
49}
50
51/// Alternative name for infinity (language compatibility)
52#[runtime_builtin(name = "Inf")]
53fn inf_language_builtin() -> Result<f64, String> {
54    Ok(f64::INFINITY)
55}
56
57/// Alternative name for NaN (language compatibility)
58#[runtime_builtin(name = "NaN")]
59fn nan_language_builtin() -> Result<f64, String> {
60    Ok(f64::NAN)
61}
62
63/// Mathematical constant √2
64#[runtime_builtin(name = "sqrt2")]
65fn sqrt2_builtin() -> Result<f64, String> {
66    Ok(std::f64::consts::SQRT_2)
67}
68
69/// Mathematical constant ln(2)
70#[runtime_builtin(name = "log2")]
71fn log2_const_builtin() -> Result<f64, String> {
72    Ok(std::f64::consts::LN_2)
73}
74
75/// Mathematical constant ln(10)
76#[runtime_builtin(name = "log10")]
77fn log10_const_builtin() -> Result<f64, String> {
78    Ok(std::f64::consts::LN_10)
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn test_pi_constant() {
87        let result = pi_builtin().unwrap();
88        assert!((result - std::f64::consts::PI).abs() < f64::EPSILON);
89    }
90
91    #[test]
92    fn test_e_constant() {
93        let result = e_builtin().unwrap();
94        assert!((result - std::f64::consts::E).abs() < f64::EPSILON);
95    }
96
97    #[test]
98    fn test_inf_constant() {
99        let result = inf_builtin().unwrap();
100        assert!(result.is_infinite() && result.is_sign_positive());
101    }
102
103    #[test]
104    fn test_nan_constant() {
105        let result = nan_builtin().unwrap();
106        assert!(result.is_nan());
107    }
108
109    #[test]
110    fn test_eps_constant() {
111        let result = eps_builtin().unwrap();
112        assert_eq!(result, f64::EPSILON);
113    }
114
115    #[test]
116    fn test_true_false_builtins() {
117        assert!(true_builtin().unwrap());
118        assert!(!false_builtin().unwrap());
119    }
120
121    #[test]
122    fn test_language_compatibility() {
123        // Test language-style names
124        assert_eq!(inf_language_builtin().unwrap(), inf_builtin().unwrap());
125        assert!(nan_language_builtin().unwrap().is_nan());
126    }
127}
128
129// Register constants that can be accessed as variables (not functions)
130runmat_builtins::inventory::submit! {
131    runmat_builtins::Constant {
132        name: "pi",
133        value: Value::Num(std::f64::consts::PI),
134    }
135}
136
137runmat_builtins::inventory::submit! {
138    runmat_builtins::Constant {
139        name: "e",
140        value: Value::Num(std::f64::consts::E),
141    }
142}
143
144runmat_builtins::inventory::submit! {
145    runmat_builtins::Constant {
146        name: "inf",
147        value: Value::Num(f64::INFINITY),
148    }
149}
150
151runmat_builtins::inventory::submit! {
152    runmat_builtins::Constant {
153        name: "Inf",
154        value: Value::Num(f64::INFINITY),
155    }
156}
157
158runmat_builtins::inventory::submit! {
159    runmat_builtins::Constant {
160        name: "nan",
161        value: Value::Num(f64::NAN),
162    }
163}
164
165runmat_builtins::inventory::submit! {
166    runmat_builtins::Constant {
167        name: "NaN",
168        value: Value::Num(f64::NAN),
169    }
170}
171
172runmat_builtins::inventory::submit! {
173    runmat_builtins::Constant {
174        name: "eps",
175        value: Value::Num(f64::EPSILON),
176    }
177}
178
179runmat_builtins::inventory::submit! {
180    runmat_builtins::Constant {
181        name: "sqrt2",
182        value: Value::Num(std::f64::consts::SQRT_2),
183    }
184}
185
186// Register logical constants so bare identifiers resolve without requiring a call
187runmat_builtins::inventory::submit! {
188    runmat_builtins::Constant {
189        name: "true",
190        value: Value::Bool(true),
191    }
192}
193
194runmat_builtins::inventory::submit! {
195    runmat_builtins::Constant {
196        name: "false",
197        value: Value::Bool(false),
198    }
199}