ellip_dev_utils/
parser.rs

1/*
2 * Ellip is licensed under The 3-Clause BSD, see LICENSE.
3 * Copyright 2025 Sira Pornsiriprasert <code@psira.me>
4 */
5
6use num_traits::Float;
7
8use crate::{StrErr, test_report::Case};
9
10pub fn parse_wolfram_str<T: Float>(s: &str) -> Result<T, StrErr> {
11    Ok(match s.trim() {
12        "Infinity" => T::infinity(),
13        "-Infinity" => T::neg_infinity(),
14        "ComplexInfinity" => T::infinity(),
15        "Indeterminate" => T::nan(),
16        "NaN" => T::nan(),
17        _ => T::from(s.parse::<f64>().map_err(|_| "Cannot parse float")?)
18            .expect("Cannot parse float"),
19    })
20}
21
22/// Reads wolfram data from file and returns a vector of Cases
23pub fn read_wolfram_data<T: Float>(file_path: &str) -> Result<Vec<Case<T>>, StrErr> {
24    use csv::ReaderBuilder;
25    use std::fs::File;
26    use std::path::Path;
27
28    let path = Path::new(file_path);
29    let file = File::open(path).map_err(|_| {
30         eprintln!("Test data not found: {file_path} Download from: https://github.com/p-sira/ellip/tree/main/tests/data");
31         "Test data not found."
32     })?;
33    let mut reader = ReaderBuilder::new().has_headers(false).from_reader(file);
34
35    let mut results = Vec::new();
36
37    for record in reader.records() {
38        let row = record.expect("Cannot read row");
39        let len = row.len();
40
41        let inputs = row
42            .iter()
43            .take(len - 1)
44            .map(|s| parse_wolfram_str(s).expect(&format!("Cannot parse data {s}")))
45            .collect();
46        let expected = {
47            let s = &row[len - 1];
48            parse_wolfram_str(s).expect(&format!("Cannot parse data {s}"))
49        };
50        results.push(Case { inputs, expected });
51    }
52
53    Ok(results)
54}