1use anyhow::Result;
2
3use super::{ArgCount, FunctionCategory, FunctionSignature, SqlFunction};
4use crate::data::datatable::DataValue;
5
6pub struct PiFunction;
8
9impl SqlFunction for PiFunction {
10 fn signature(&self) -> FunctionSignature {
11 FunctionSignature {
12 name: "PI",
13 category: FunctionCategory::Constant,
14 arg_count: ArgCount::Fixed(0),
15 description: "Returns the value of π (pi)",
16 returns: "FLOAT",
17 examples: vec!["SELECT PI()", "SELECT radius * 2 * PI() AS circumference"],
18 }
19 }
20
21 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
22 self.validate_args(args)?;
23 Ok(DataValue::Float(std::f64::consts::PI))
24 }
25}
26
27pub struct EFunction;
29
30impl SqlFunction for EFunction {
31 fn signature(&self) -> FunctionSignature {
32 FunctionSignature {
33 name: "E",
34 category: FunctionCategory::Constant,
35 arg_count: ArgCount::Fixed(0),
36 description: "Returns Euler's number (e ≈ 2.71828)",
37 returns: "FLOAT",
38 examples: vec!["SELECT E()", "SELECT POW(E(), x) AS exp_x"],
39 }
40 }
41
42 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
43 self.validate_args(args)?;
44 Ok(DataValue::Float(std::f64::consts::E))
45 }
46}
47
48pub struct MeFunction;
50
51pub struct MassElectronFunction;
53
54impl SqlFunction for MeFunction {
55 fn signature(&self) -> FunctionSignature {
56 FunctionSignature {
57 name: "ME",
58 category: FunctionCategory::Constant,
59 arg_count: ArgCount::Fixed(0),
60 description: "Returns the mass of an electron in kg (9.10938356 × 10^-31)",
61 returns: "FLOAT",
62 examples: vec!["SELECT ME()", "SELECT mass / ME() AS electron_masses"],
63 }
64 }
65
66 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
67 self.validate_args(args)?;
68 Ok(DataValue::Float(9.1093837015e-31))
69 }
70}
71
72impl SqlFunction for MassElectronFunction {
73 fn signature(&self) -> FunctionSignature {
74 FunctionSignature {
75 name: "MASS_ELECTRON",
76 category: FunctionCategory::Constant,
77 arg_count: ArgCount::Fixed(0),
78 description: "Alias for ME() - Returns the mass of an electron in kg",
79 returns: "FLOAT",
80 examples: vec!["SELECT MASS_ELECTRON()"],
81 }
82 }
83
84 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
85 self.validate_args(args)?;
86 Ok(DataValue::Float(9.1093837015e-31))
87 }
88}
89
90pub struct TauFunction;
92
93impl SqlFunction for TauFunction {
94 fn signature(&self) -> FunctionSignature {
95 FunctionSignature {
96 name: "TAU",
97 category: FunctionCategory::Constant,
98 arg_count: ArgCount::Fixed(0),
99 description: "Returns tau (τ = 2π = 6.28318...)",
100 returns: "FLOAT",
101 examples: vec!["SELECT TAU()", "SELECT radius * TAU() as circumference"],
102 }
103 }
104
105 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
106 self.validate_args(args)?;
107 Ok(DataValue::Float(2.0 * std::f64::consts::PI))
108 }
109}
110
111pub struct PhiFunction;
113
114impl SqlFunction for PhiFunction {
115 fn signature(&self) -> FunctionSignature {
116 FunctionSignature {
117 name: "PHI",
118 category: FunctionCategory::Constant,
119 arg_count: ArgCount::Fixed(0),
120 description: "Returns the golden ratio φ (1.61803...)",
121 returns: "FLOAT",
122 examples: vec!["SELECT PHI()", "SELECT width * PHI() as golden_height"],
123 }
124 }
125
126 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
127 self.validate_args(args)?;
128 Ok(DataValue::Float(1.618033988749895)) }
130}
131
132pub struct HbarFunction;
134
135impl SqlFunction for HbarFunction {
136 fn signature(&self) -> FunctionSignature {
137 FunctionSignature {
138 name: "HBAR",
139 category: FunctionCategory::Constant,
140 arg_count: ArgCount::Fixed(0),
141 description: "Returns the reduced Planck constant ħ in J⋅s (1.055 × 10⁻³⁴)",
142 returns: "FLOAT",
143 examples: vec!["SELECT HBAR()", "SELECT HBAR() / (2 * PI()) as h_bar"],
144 }
145 }
146
147 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
148 self.validate_args(args)?;
149 Ok(DataValue::Float(1.054571817e-34))
150 }
151}
152
153const PI_DIGITS: &str = include_str!("pi_10000_digits.txt");
156
157pub struct PiDigitsFunction;
159
160impl SqlFunction for PiDigitsFunction {
161 fn signature(&self) -> FunctionSignature {
162 FunctionSignature {
163 name: "PI_DIGITS",
164 category: FunctionCategory::Constant,
165 arg_count: ArgCount::Fixed(1),
166 description: "Returns π (pi) to N decimal places as a string (up to 10,000 digits)",
167 returns: "STRING",
168 examples: vec![
169 "SELECT PI_DIGITS(10)",
170 "SELECT PI_DIGITS(100)",
171 "SELECT PI_DIGITS(1000)",
172 ],
173 }
174 }
175
176 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
177 self.validate_args(args)?;
178
179 let places = match &args[0] {
180 DataValue::Integer(n) => *n as usize,
181 DataValue::Float(f) => *f as usize,
182 _ => anyhow::bail!("PI_DIGITS requires an integer argument"),
183 };
184
185 if places == 0 {
186 return Ok(DataValue::String("3".to_string()));
187 }
188
189 if places > 10000 {
190 anyhow::bail!("PI_DIGITS: Maximum 10,000 decimal places supported");
191 }
192
193 let result = if places <= PI_DIGITS.len() - 2 {
196 PI_DIGITS[..2 + places].to_string()
198 } else {
199 PI_DIGITS.to_string()
200 };
201
202 Ok(DataValue::String(result))
203 }
204}
205
206pub struct PiDigitFunction;
208
209impl SqlFunction for PiDigitFunction {
210 fn signature(&self) -> FunctionSignature {
211 FunctionSignature {
212 name: "PI_DIGIT",
213 category: FunctionCategory::Constant,
214 arg_count: ArgCount::Fixed(1),
215 description: "Returns the Nth decimal digit of π (1-indexed, up to 10,000 digits)",
216 returns: "INTEGER",
217 examples: vec![
218 "SELECT PI_DIGIT(1)",
219 "SELECT PI_DIGIT(10)",
220 "SELECT n, PI_DIGIT(n) FROM RANGE(1, 10)",
221 ],
222 }
223 }
224
225 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
226 self.validate_args(args)?;
227
228 let position = match &args[0] {
229 DataValue::Integer(n) => *n as usize,
230 DataValue::Float(f) => *f as usize,
231 _ => anyhow::bail!("PI_DIGIT requires an integer argument"),
232 };
233
234 if position == 0 {
235 anyhow::bail!("PI_DIGIT: Position must be >= 1 (1-indexed)");
236 }
237
238 if position > 10000 {
239 anyhow::bail!("PI_DIGIT: Maximum position is 10,000");
240 }
241
242 let char_index = 1 + position; if let Some(ch) = PI_DIGITS.chars().nth(char_index) {
247 if let Some(digit) = ch.to_digit(10) {
248 return Ok(DataValue::Integer(digit as i64));
249 }
250 }
251
252 anyhow::bail!("PI_DIGIT: Could not extract digit at position {}", position)
253 }
254}
255
256#[cfg(test)]
257mod tests {
258 use super::*;
259
260 #[test]
261 fn test_pi_function() {
262 let func = PiFunction;
263 let result = func.evaluate(&[]).unwrap();
264 match result {
265 DataValue::Float(val) => assert!((val - std::f64::consts::PI).abs() < 1e-10),
266 _ => panic!("Expected Float"),
267 }
268 }
269
270 #[test]
271 fn test_pi_with_args_fails() {
272 let func = PiFunction;
273 let result = func.evaluate(&[DataValue::Float(1.0)]);
274 assert!(result.is_err());
275 }
276
277 #[test]
278 fn test_e_function() {
279 let func = EFunction;
280 let result = func.evaluate(&[]).unwrap();
281 match result {
282 DataValue::Float(val) => assert!((val - std::f64::consts::E).abs() < 1e-10),
283 _ => panic!("Expected Float"),
284 }
285 }
286
287 #[test]
288 fn test_me_function() {
289 let func = MeFunction;
290 let result = func.evaluate(&[]).unwrap();
291 match result {
292 DataValue::Float(val) => assert!((val - 9.1093837015e-31).abs() < 1e-40),
293 _ => panic!("Expected Float"),
294 }
295 }
296}