So the idea is to have a function that returns a closure of degree n with random coefficients. This might be useful for comparing root finding methods, as we can automate the creation of a function to evaluate, for example. Appending any operations to a closure's return would be an even more powerful resource, so let me know if there is some way to do that.
The code should look as following:
use rand::Rng;
fn create_func(n: u8) -> impl Fn(f64) -> f64 {
let mut cst = vec![];
for _ in 0..n{
cst.push(rand::thread_rng().gen_range(0..=20) as f64);
// establish the coefficients by randomly generating them
}
move |x| cst[0]*x + cst[1]*x.powf(1.) + /*...*/ cst[n- 1]*x.powf(n as f64)
}
So obviously the last part isn't really a valid way of expressing the rest of the closure we want to return, but I hope you get the idea.
You're looking for a sum, so turn your sequence into an iterator that will be summed.
move |x| {
cst.iter()
.zip(0..=n as i32)
.map(|(&c, exp)| c * x.powi(exp))
.sum()
}
For each item, you need the element from cst
(iter
) and its exponent (zip
). You can construct terms one at a time from those (map
), and then sum all terms together (sum
).
I've also fixed your number of terms (yours doesn't have the x^0 term) and used sample_iter
, which is faster than calling thread_rng
every time. And I've switched to powi
since all the exponents are integers.
pub fn create_func(n: u8) -> impl Fn(f64) -> f64 {
let cst: Vec<f64> = rand::thread_rng()
.sample_iter(rand::distributions::Uniform::new_inclusive(0, 20))
.map(|n| n as f64)
.take(n as usize + 1)
.collect();
move |x| {
cst.iter()
.zip(0..=n as i32)
.map(|(&c, exp)| c * x.powi(exp))
.sum()
}
}