From 67cdcc2e12118becb823e20a40cc2687f2b8425a Mon Sep 17 00:00:00 2001 From: Adam Carpenter <53hornet@gmail.com> Date: Wed, 27 Mar 2019 15:32:37 -0400 Subject: Started Rust in Action MEAP. --- meap/meap-code/ch5/ch5-q/src/lib.rs | 76 +++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 meap/meap-code/ch5/ch5-q/src/lib.rs (limited to 'meap/meap-code/ch5/ch5-q/src') diff --git a/meap/meap-code/ch5/ch5-q/src/lib.rs b/meap/meap-code/ch5/ch5-q/src/lib.rs new file mode 100644 index 0000000..d05ca3a --- /dev/null +++ b/meap/meap-code/ch5/ch5-q/src/lib.rs @@ -0,0 +1,76 @@ +/// Q1_7 - single byte representation of a fixed point number with range [-1, 1]. +/// The name refers to the Texas Instrument representation +/// +/// References: +/// - English Wikipedia: "Q (number format)" https://en.wikipedia.org/wiki/Q_(number_format) +#[derive(Debug,Clone,Copy,PartialEq,Eq)] +pub struct Q7(i8); // tuple struct holding a i8 value + +impl From for Q7 { + fn from (n: f64) -> Self { + if n >= 1.0 { // out of bounds numbers are coerced to the maximum of the range + Q7(127) + } else if n <= -1.0 { + Q7(-128) + } else { + Q7((n * 128.0) as i8) // 128 == (2 ** 7) == pow(2,7) + } + } +} + +impl From for f64 { + fn from(n: Q7) -> f64 { + (n.0 as f64) * 2f64.powf(-7.0) // 0.0078125// (2 ** -7) // pow(2, -7) + } +} + +impl From for Q7 { + fn from (n: f32) -> Self { + Q7::from(n as f64) // conversion from f32 to f64 works perfectly + } +} + +impl From for f32 { + fn from(n: Q7) -> f32 { + f64::from(n) as f32 // conversion from f64 to f32 can result in undefined behavior, + // but not here as f32 can represent all values representable by Q7 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn out_of_bounds() { + assert_eq!(Q7::from(10.), Q7::from(1.)); + assert_eq!(Q7::from(-10.), Q7::from(-1.)); + } + + #[test] + fn f32_to_q7() { + let n1: f32 = 0.7; + let q1 = Q7::from(n1); + + let n2 = -0.4; + let q2 = Q7::from(n2); + + let n3 = 123.0; + let q3 = Q7::from(n3); + + assert_eq!(q1, Q7(89)); + assert_eq!(q2, Q7(-51)); + assert_eq!(q3, Q7(127)); + } + + #[test] + fn q7_to_f32() { + let q1 = Q7::from(0.7); + let n1 = f32::from(q1); + assert_eq!(n1, 0.6953125); + + let q2 = Q7::from(n1); // numbers that can be represented exactly by Q7 + let n2 = f32::from(q2); // can survive the transition between Q7 and f32 + assert_eq!(n1, n2); + } +} -- cgit v1.2.3