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}
55
56pub fn read_boost_data<T: Float>(file_path: &str) -> Result<Vec<Case<T>>, StrErr> {
57    use std::fs::File;
58    use std::io::{BufRead, BufReader};
59    use std::path::Path;
60
61    let path = Path::new(file_path);
62    let file = File::open(path).map_err(|_| {
63         eprintln!("Test data not found: {file_path} Download from: https://github.com/p-sira/ellip/tree/main/tests/data");
64         "Test data not found."
65     })?;
66    let reader = BufReader::new(file);
67
68    let mut cases = vec![];
69
70    reader.lines().for_each(|line| {
71        let line = line.expect("Cannot read line");
72        let parts: Vec<&str> = line.split_whitespace().collect();
73        let case = Case {
74            inputs: parts[..parts.len() - 1]
75                .iter()
76                .map(|&v| {
77                    T::from_str_radix(v, 10)
78                        .unwrap_or_else(|_| panic!("Cannot parse input(s) as a number"))
79                })
80                .collect(),
81            expected: T::from_str_radix(parts[parts.len() - 1], 10)
82                .unwrap_or_else(|_| panic!("Cannot parse expected value as a number")),
83        };
84        cases.push(case);
85    });
86
87    Ok(cases)
88}