Loading s4prg_rust_02_params...
let bm = s4::Benchmark::new("starting_occurrence");
bm.record("this solution", 2.0, |t| { // ... prepare parameters if needed ... s4::bm_call!(t, my_function(param1, param2, ...)); });
|t| { ... }autant de fois que nécessaire pour que le temps total de mesure atteigne au moins la durée choisie.
bm.record("another solution", 2.0, |t| { // ... prepare parameters if needed ... t.add(|| { s4::bm_call!(my_function_a(param_a1, param_a2, ...)); s4::bm_call!(my_function_b(param_b1, param_b2, ...)); }); });
t.add(|| { ... })est pris en compte dans la mesure.
s4::bm_call!( ... )sert à éviter que le compilateur n'élimine des opérations qu'il juge inutiles lorsqu'elles sont artificiellement répétées en boucle par l'outil bm (voir
rustup doc --std 'core::hint::black_box').
println!("{}", bm);
fn starting_occurrence( word_occurrences: Vec<(String, u64)>, character: char, ) -> u64 { word_occurrences .iter() .filter_map(|(word, occurrence)| { word.chars() .next() .filter(|c| *c == character) .and(Some(occurrence)) }) .sum() }
&Vec<...>).
bm.record("ref+drop", 2.0, |t| { let word_occurrences = word_occurrences.clone(); // not measured t.add(|| { // these two lines of code are considered in the measure s4::bm_call!(starting_occurrence_ref(&word_occurrences, 'z')); drop(word_occurrences); // free allocated resources }); });
&[...]).
Option<f64>) représentant les éventuelles solutions de l'équation.
gnuplot -p -e 'set term x11; plot [-4:0] 0, 2*x**2+8*x+6, 2*x**2+8*x+8, 2*x**2+8*x+10'
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#[allow(unused_imports)] use crate::s4;
pub const SECTIONS: &[fn()] = &[ section_1, section_2, section_3, section_4, section_5, section_6, ];
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fn starting_occurrence( word_occurrences: Vec<(String, u64)>, character: char, ) -> u64 { word_occurrences .iter() .filter_map(|(word, occurrence)| { word.chars() .next() .filter(|c| *c == character) .and(Some(occurrence)) }) .sum() }
fn section_1() { println!("\n~~~~ chapter 2, section 1 ~~~~"); let bm = s4::Benchmark::new("starting_occurrence"); bm.record("load", 2.0, |t| { s4::bm_call!( t, starting_occurrence(s4::load_word_occurrences(), 'z') ); }); let word_occurrences = s4::load_word_occurrences(); bm.record("clone", 2.0, |t| { s4::bm_call!(t, starting_occurrence(word_occurrences.clone(), 'z')); }); bm.record("move", 2.0, |t| { let word_occurrences = word_occurrences.clone(); // not measured s4::bm_call!(t, starting_occurrence(word_occurrences, 'z')); }); // section 2 bm.record("ref", 2.0, |t| { s4::bm_call!(t, starting_occurrence_ref(&word_occurrences, 'z')); }); bm.record("ref+drop", 2.0, |t| { let word_occurrences = word_occurrences.clone(); // not measured t.add(|| { // these two lines of code are considered in the measure s4::bm_call!(starting_occurrence_ref(&word_occurrences, 'z')); drop(word_occurrences); // free allocated resources }); }); // section 3 bm.record("slice", 2.0, |t| { s4::bm_call!( t, starting_occurrence_slice(word_occurrences.as_slice(), 'z') ); }); println!("{}", bm); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fn show_ref_params( pu: &u32, pf: &f64, pt: &[u16; 3], pv: &Vec<u16>, ps: &String, ) { s4::show_mem!(" pu", pu); s4::show_mem!(" pf", pf); s4::show_mem!(" pt", pt); s4::show_mem!(" pv", pv); s4::show_mem!(" ps", ps); s4::show_mem!("*pu", *pu); s4::show_mem!("*pf", *pf); s4::show_mem!("*pt", *pt); s4::show_mem!("*pv", *pv); s4::show_mem!("*ps", *ps); }
#[allow(clippy::ptr_arg)] fn starting_occurrence_ref( word_occurrences: &Vec<(String, u64)>, character: char, ) -> u64 { word_occurrences .iter() .filter_map(|(word, occurrence)| { word.chars() .next() .filter(|c| *c == character) .and(Some(occurrence)) }) .sum() }
fn section_2() { println!("\n~~~~ chapter 2, section 2 ~~~~"); let u = 98765_u32; let f = 12.34_f64; let t = [99_u16, 98, 97]; let v = vec![88_u16, 87, 86]; let s = "Short".to_owned(); s4::show_mem!(" u", u); s4::show_mem!(" f", f); s4::show_mem!(" t", t); s4::show_mem!(" v", v); s4::show_mem!(" s", s); s4::show_mem!("t[0]", t[0]); s4::show_mem!("v[0]", v[0]); s4::show_mem!("s[0]", s.as_bytes()[0]); println!("~~~~~~~~"); show_ref_params(&u, &f, &t, &v, &s); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fn show_slice_params( pt: &[u16], pv: &[u16], ps: &str, ) { s4::show_mem!(" st", pt); println!(" ({:?}, {})", pt.as_ptr(), pt.len()); s4::show_mem!(" sv", pv); println!(" ({:?}, {})", pv.as_ptr(), pv.len()); s4::show_mem!(" ss", ps); println!(" ({:?}, {})", ps.as_ptr(), ps.len()); }
fn starting_occurrence_slice( word_occurrences: &[(String, u64)], character: char, ) -> u64 { word_occurrences .iter() .filter_map(|(word, occurrence)| { word.chars() .next() .filter(|c| *c == character) .and(Some(occurrence)) }) .sum() }
fn section_3() { println!("\n~~~~ chapter 2, section 3 ~~~~"); let t = [99_u16, 98, 97]; let v = vec![88_u16, 87, 86]; let s = "Short".to_owned(); s4::show_mem!(" t", t); s4::show_mem!(" v", v); s4::show_mem!(" s", s); s4::show_mem!("t[0]", t[0]); s4::show_mem!("v[0]", v[0]); s4::show_mem!("s[0]", s.as_bytes()[0]); println!("~~~~~~~~"); show_slice_params(t.as_slice(), v.as_slice(), s.as_str()); println!("~~~~~~~~ changing parameters"); show_slice_params(v.as_slice(), t.as_slice(), "literal string!"); println!("~~~~~~~~ partial slices"); show_slice_params(&v[1..3], &v[0..2], &s[1..4]); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// fn extend_arithmetic_sequence(mut seq: Vec<f64>) { fn extend_arithmetic_sequence(seq: &mut Vec<f64>) { let n = seq.len(); if n >= 2 { let v1 = seq[n - 1]; let v2 = seq[n - 2]; seq.push(v1 + (v1 - v2)); } }
fn invert_values(values: &mut [f64]) { for v in values.iter_mut() { *v = 1.0 / *v; } }
fn section_4() { println!("\n~~~~ chapter 2, section 4 ~~~~"); let mut v = vec![10.0, 12.5, 15.0]; println!("initial v: {:?}", v); // extend_arithmetic_sequence(v); extend_arithmetic_sequence(&mut v); println!("extended v: {:?}", v); invert_values(v.as_mut_slice()); println!("inverted v: {:?}", v); let mut t = [2.0, 4.0, 8.0, 16.0]; println!("initial t: {:?}", t); invert_values(t.as_mut_slice()); println!("inverted t: {:?}", t); invert_values(&mut t[2..4]); println!("partially inverted t: {:?}", t); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#[derive(Debug, Clone)] struct SecondDegree { coefs: [f64; 3], delta: f64, solutions: [Option<f64>; 2], }
fn solve_second_degree(sd: &mut SecondDegree) { let [a, b, c] = sd.coefs; sd.delta = b * b - 4.0 * a * c; sd.solutions[0] = if sd.delta >= 0.0 { Some((-b - sd.delta.sqrt()) / (2.0 * a)) } else { None }; sd.solutions[1] = if sd.delta > 0.0 { Some((-b + sd.delta.sqrt()) / (2.0 * a)) } else { None }; }
fn compute_second_degree( sd: &SecondDegree, x: f64, ) -> f64 { let [a, b, c] = sd.coefs; (a * x + b) * x + c }
fn section_5() { println!("\n~~~~ chapter 2, section 5 ~~~~"); let mut sd = SecondDegree { coefs: [2.0, 8.0, 6.0], delta: 0.0, solutions: [None, None], }; println!("{:?}", sd); for _ in 0..3 { solve_second_degree(&mut sd); println!("{:?} ~~> {} {:?}", sd.coefs, sd.delta, sd.solutions); for i in 0..9 { let x = (i as f64) * 0.5 - 4.0; println!("{} ~~> {}", x, compute_second_degree(&sd, x)); } sd.coefs[2] += 2.0; } println!("{:?}", sd); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mod equation { #[derive(Debug, Clone)] pub struct SecondDegree { coefs: [f64; 3], delta: f64, solutions: [Option<f64>; 2], }
impl SecondDegree { pub fn new( a: f64, b: f64, c: f64, ) -> Self { if false { // initial version, without translate_x() neither solve() let delta = b * b - 4.0 * a * c; let solutions = [ if delta >= 0.0 { Some((-b - delta.sqrt()) / (2.0 * a)) } else { None }, if delta > 0.0 { Some((-b + delta.sqrt()) / (2.0 * a)) } else { None }, ]; Self { coefs: [a, b, c], delta, solutions, } } else { // rely on private function solve() // instead of duplicating the code let mut sd = Self { coefs: [a, b, c], delta: 0.0, solutions: [None, None], }; sd.solve(); sd } }
pub fn coefs(&self) -> &[f64; 3] { &self.coefs }
pub fn delta(&self) -> f64 { self.delta }
pub fn solutions(&self) -> &[Option<f64>; 2] { &self.solutions }
pub fn compute( &self, x: f64, ) -> f64 { let [a, b, c] = self.coefs; (a * x + b) * x + c }
pub fn translate_y( &mut self, dy: f64, ) { self.coefs[2] += dy; self.solve(); }
fn solve(&mut self) { let [a, b, c] = self.coefs; self.delta = b * b - 4.0 * a * c; self.solutions[0] = if self.delta >= 0.0 { Some((-b - self.delta.sqrt()) / (2.0 * a)) } else { None }; self.solutions[1] = if self.delta > 0.0 { Some((-b + self.delta.sqrt()) / (2.0 * a)) } else { None }; } } }
fn section_6() { println!("\n~~~~ chapter 2, section 6 ~~~~"); let mut sd = equation::SecondDegree::new(2.0, 8.0, 6.0); println!("{:?}", sd); for _ in 0..3 { println!("{:?} ~~> {} {:?}", sd.coefs(), sd.delta(), sd.solutions()); for i in 0..9 { let x = (i as f64) * 0.5 - 4.0; println!("{} ~~> {}", x, sd.compute(x)); } sd.translate_y(2.0); } println!("{:?}", sd); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~