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
use derivative::Derivative;
use std::marker::PhantomData;
use crate::traits::AsF64;
use crate::types::Scales;
#[derive(Derivative)]
#[derivative(Debug)]
pub struct Function<X: AsF64, Y: AsF64, F: Fn(X) -> Y> {
#[derivative(Debug = "ignore")]
f: F,
#[derivative(Debug = "ignore")]
_x: PhantomData<X>,
#[derivative(Debug = "ignore")]
_y: PhantomData<Y>,
}
impl<X: AsF64, Y: AsF64, F: Fn(X) -> Y> Function<X, Y, F> {
pub fn new(f: F) -> Function<X, Y, F> {
Function {
f,
_x: PhantomData,
_y: PhantomData,
}
}
pub fn at(&self, x: f64) -> f64 {
(self.f)(X::from_f64(x)).as_f64()
}
pub fn pt(&self, x: f64) -> (f64, f64) {
let y = self.at(x);
(x, y)
}
pub fn rng(&self, x_i: u32, x_f: u32) -> Vec<f64> {
(x_i..=x_f)
.map(|x| (self.f)(X::from_f64(x.as_f64())).as_f64())
.collect()
}
pub fn rng_x(&self, x_i: u32, x_f: u32) -> Vec<(u32, f64)> {
(x_i..=x_f)
.map(|x| (x, (self.f)(X::from_f64(x.as_f64())).as_f64()))
.collect()
}
pub fn rng_x_scale(&self, x_i: u32, x_f: u32, scales: &Scales) -> Vec<(f64, f64)> {
(x_i..=x_f)
.map(|x| {
(
x as f64 * scales.x,
(self.f)(X::from_f64(x.as_f64() * scales.x)).as_f64() * scales.y,
)
})
.collect()
}
}
impl<X: AsF64 + Copy, Y: AsF64, F: Fn(X) -> Y> IntoIterator for Function<X, Y, F> {
type Item = Y;
type IntoIter = FunctionIntoIterator<X, Y, F>;
fn into_iter(self) -> Self::IntoIter {
FunctionIntoIterator {
func: self,
x: X::from_f64(0_f64),
}
}
}
pub struct FunctionIntoIterator<X: AsF64, Y: AsF64, F: Fn(X) -> Y> {
func: Function<X, Y, F>,
x: X,
}
impl<X: AsF64 + Copy, Y: AsF64, F: Fn(X) -> Y> Iterator for FunctionIntoIterator<X, Y, F> {
type Item = Y;
fn next(&mut self) -> Option<Y> {
let res = self.func.at(self.x.as_f64());
self.x = X::from_f64(self.x.as_f64() + 1.0);
Some(Y::from_f64(res))
}
}
#[macro_export]
macro_rules! func {
(|$x:ident| $code:expr) => {
tgraph::Function::new(|$x: f64| -> f64 { $code } as fn(f64) -> f64)
};
($e:expr) => {
tgraph::Function::new($e)
};
($x:ident -> $code:expr) => {
tgraph::Function::new(|$x: f64| -> f64 { $code } as fn(f64) -> f64)
};
($x:ident [$xt:ty] -> $code:expr) => {
tgraph::Function::new(|$x: $xt| -> f64 { $code } as fn($xt) -> f64)
};
($x:ident [$xt:ty] -> $code:expr => [$yt:ty]) => {
tgraph::Function::new(|$x: $xt| -> $yt { $code } as fn($xt) -> $yt)
};
($x:ident -> $code:expr => [$yt:ty]) => {
tgraph::Function::new(|$x: f64| -> $yt { $code } as fn(f64) -> $yt)
};
}