truecalc_core/eval/functions/math/randarray/
mod.rs1use crate::eval::coercion::to_number;
2use crate::eval::functions::check_arity;
3use crate::types::{ErrorKind, Value};
4
5fn lcg_sequence(count: usize) -> Vec<f64> {
8 let seed = std::time::SystemTime::now()
9 .duration_since(std::time::UNIX_EPOCH)
10 .map(|d| d.as_nanos() as u64)
11 .unwrap_or(12345);
12 let mut state = seed
14 .wrapping_mul(6_364_136_223_846_793_005)
15 .wrapping_add(1_442_695_040_888_963_407);
16 let mut out = Vec::with_capacity(count);
17 for _ in 0..count {
18 state = state
19 .wrapping_mul(6_364_136_223_846_793_005)
20 .wrapping_add(1_442_695_040_888_963_407);
21 let val = (state >> 32) as u32;
23 out.push((val as f64) / (u32::MAX as f64 + 1.0));
24 }
25 out
26}
27
28pub fn randarray_fn(args: &[Value]) -> Value {
34 if args.is_empty() {
35 let vals = lcg_sequence(1);
37 return Value::Number(vals[0]);
38 }
39 if let Some(err) = check_arity(args, 1, 5) {
40 return err;
41 }
42 let rows = match to_number(args[0].clone()) {
43 Err(e) => return e,
44 Ok(v) => v,
45 };
46 if rows <= 0.0 {
47 return Value::Error(ErrorKind::Num);
48 }
49 let rows = rows as usize;
50 let cols = if args.len() >= 2 {
51 match to_number(args[1].clone()) {
52 Err(e) => return e,
53 Ok(v) => {
54 if v <= 0.0 {
55 return Value::Error(ErrorKind::Num);
56 }
57 v as usize
58 }
59 }
60 } else {
61 1
62 };
63
64 let total = rows * cols;
65 let nums = lcg_sequence(total);
66 let outer: Vec<Value> = (0..rows)
68 .map(|r| {
69 let row: Vec<Value> = (0..cols)
70 .map(|c| Value::Number(nums[r * cols + c]))
71 .collect();
72 Value::Array(row)
73 })
74 .collect();
75 Value::Array(outer)
76}
77
78#[cfg(test)]
79mod tests;