ellip_dev_utils/
parser.rs1use 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
23pub 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}