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