1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use crate::defaults::DimVec;
use std::{
cmp::Ordering::{self, Equal, Greater, Less},
fs::File,
path::Path,
str::FromStr,
};
pub fn add(a: &DimVec<f32>, b: &DimVec<f32>) -> DimVec<f32> {
a.iter().zip(b).map(|(aa, bb)| aa + bb).collect()
}
pub fn add_to(a: &mut DimVec<f32>, b: &DimVec<f32>) {
a.iter_mut().zip(b).for_each(|(aa, bb)| *aa += bb);
}
pub fn dot_product(a: &DimVec<f32>, b: &DimVec<f32>) -> f32 {
a.iter()
.zip(b)
.fold(0.0, |start, (aa, &bb)| start + aa * bb)
}
pub trait ApproxEq {
fn approx_eq(&self, other: &Self) -> bool;
}
pub trait ApproxCmp {
fn approx_partial_cmp(&self, other: &Self) -> Option<Ordering>;
fn approx_cmp(&self, other: &Self) -> Ordering;
}
impl ApproxEq for f32 {
fn approx_eq(&self, other: &f32) -> bool {
(self - other).abs() <= std::f32::EPSILON
}
}
impl ApproxCmp for f32 {
fn approx_partial_cmp(&self, other: &f32) -> Option<Ordering> {
match (self < other, self > other, self.approx_eq(other)) {
(false, false, false) => None,
(false, true, false) => Some(Greater),
(true, false, false) => Some(Less),
(true, true, false) | (_, _, true) => Some(Equal),
}
}
fn approx_cmp(&self, other: &f32) -> Ordering {
self.approx_partial_cmp(other).expect(&format!(
"No f32-comparison for {} and {} possible.",
self, other
))
}
}
impl ApproxEq for DimVec<f32> {
fn approx_eq(&self, other: &DimVec<f32>) -> bool {
self.iter()
.zip(other)
.fold(true, |acc, (aa, bb)| acc && aa.approx_eq(bb))
}
}
pub fn open_file<P: AsRef<Path> + ?Sized>(path: &P) -> Result<File, String> {
let path = path.as_ref();
match File::open(path) {
Ok(file) => Ok(file),
Err(_) => Err(format!("No such file {}", path.display())),
}
}
pub fn open_new_file<P: AsRef<Path> + ?Sized>(path: &P) -> Result<File, String> {
let path = path.as_ref();
if path.exists() {
return Err(format!(
"Provided file {} does already exist. Please remove it.",
path.display()
));
}
match File::create(path) {
Ok(file) => Ok(file),
Err(e) => Err(format!("{}", e)),
}
}
pub fn init_logging(max_log_level: &str, mut modules: Vec<&str>) -> Result<(), String> {
let mut builder = env_logger::Builder::new();
builder.filter(None, log::LevelFilter::Warn);
let max_log_level = log::LevelFilter::from_str(&max_log_level.to_ascii_uppercase())
.ok()
.ok_or(format!(
"The provided max-log-level {} is not supported.",
max_log_level
))?;
modules.push(env!("CARGO_PKG_NAME"));
for module in modules {
builder.filter(Some(module), max_log_level);
}
if let Ok(filters) = std::env::var("RUST_LOG") {
builder.parse_filters(&filters);
}
if let Ok(write_style) = std::env::var("RUST_LOG_STYLE") {
builder.parse_write_style(&write_style);
}
builder.init();
Ok(())
}