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
6
7use num_traits::Float;
8
9use crate::{StrErr, test_report::Case};
10
11pub fn parse_wolfram_str<T: Float>(s: &str) -> Result<T, StrErr> {
12    Ok(match s.trim() {
13        "Infinity" => T::infinity(),
14        "-Infinity" => T::neg_infinity(),
15        "ComplexInfinity" => T::infinity(),
16        "Indeterminate" => T::nan(),
17        "NaN" => T::nan(),
18        _ => T::from(s.parse::<f64>().map_err(|_| "Cannot parse float")?)
19            .expect("Cannot parse float"),
20    })
21}
22
23/// Reads wolfram data from file and returns a vector of Cases
24pub fn read_wolfram_data<T: Float>(file_path: &str) -> Result<Vec<Case<T>>, StrErr> {
25    use csv::ReaderBuilder;
26    use std::fs::File;
27    use std::path::Path;
28
29    let path = Path::new(file_path);
30    let file = File::open(path).map_err(|_| {
31         eprintln!("Test data not found: {file_path} Download from: https://github.com/p-sira/ellip/tree/main/tests/data");
32         "Test data not found."
33     })?;
34    let mut reader = ReaderBuilder::new().has_headers(false).from_reader(file);
35
36    let mut results = Vec::new();
37
38    for record in reader.records() {
39        let row = record.expect("Cannot read row");
40        let len = row.len();
41
42        let inputs = row
43            .iter()
44            .take(len - 1)
45            .map(|s| parse_wolfram_str(s).expect(&format!("Cannot parse data {s}")))
46            .collect();
47        let expected = {
48            let s = &row[len - 1];
49            parse_wolfram_str(s).expect(&format!("Cannot parse data {s}"))
50        };
51        results.push(Case { inputs, expected });
52    }
53
54    Ok(results)
55}
56
57pub fn read_boost_data<T: Float>(
58    file_path: &str,
59) -> Result<Vec<Case<T>>, StrErr> {
60    use std::fs::File;
61    use std::io::{BufRead, BufReader};
62    use std::path::Path;
63
64    let path = Path::new(file_path);
65    let file = File::open(path).map_err(|_| {
66         eprintln!("Test data not found: {file_path} Download from: https://github.com/p-sira/ellip/tree/main/tests/data");
67         "Test data not found."
68     })?;
69    let reader = BufReader::new(file);
70
71    let mut cases = vec![];
72
73    reader.lines().for_each(|line| {
74        let line = line.expect("Cannot read line");
75        let parts: Vec<&str> = line.split_whitespace().collect();
76        let case = Case {
77            inputs: parts[..parts.len() - 1]
78                .iter()
79                .map(|&v| T::from_str_radix(v, 10).unwrap_or_else(|_| panic!("Cannot parse input(s) as a number")))
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}