From: Greg Burri Date: Tue, 3 Aug 2021 09:16:21 +0000 (+0200) Subject: Chapter 5 WIP X-Git-Url: http://git.euphorik.ch/index.cgi?a=commitdiff_plain;h=ba9af03dc60ca488ef9cf3d2b82ca8bf911f85cd;p=rust_in_action.git Chapter 5 WIP --- diff --git a/ch3-cubsat-ground-station/src/main.rs b/ch3-cubsat-ground-station/src/main.rs index b456ff8..7334bf0 100644 --- a/ch3-cubsat-ground-station/src/main.rs +++ b/ch3-cubsat-ground-station/src/main.rs @@ -1,32 +1,42 @@ #![cfg_attr(debug_assertions, allow(unused_variables, dead_code))] +use std::cell::RefCell; +use std::rc::Rc; + +type Message = String; + #[derive(Debug)] enum StatusMessage { Ok, } +#[derive(Debug)] +struct Mailbox { + messages: Vec, +} + #[derive(Debug)] struct CubeSat { id: u64, + mailbox: Mailbox, } -fn check_status(sat_id: CubeSat) -> StatusMessage { +#[derive(Debug)] +struct GroundStation { + radio_freq: f64 // [MHz]. +} + +fn check_status(sat_id: &CubeSat) -> StatusMessage { StatusMessage::Ok } fn main() { - let sat_a = CubeSat { id: 0 }; - let sat_b = CubeSat { id: 1 }; - let sat_c = CubeSat { id: 2 }; - - let a_status = check_status(sat_a); - let b_status = check_status(sat_b); - let c_status = check_status(sat_c); - println!("a: {:?}, b: {:?}, c: {:?}", a_status, b_status, c_status); - + let base: Rc> = + Rc::new( + RefCell::new( + GroundStation { radio_freq: 42.1 } + ) + ); - let a_status = check_status(sat_a); - let b_status = check_status(sat_b); - let c_status = check_status(sat_c); - println!("a: {:?}, b: {:?}, c: {:?}", a_status, b_status, c_status); + println!("base: {:?}", base); } diff --git a/ch5-data-in-depth/Cargo.lock b/ch5-data-in-depth/Cargo.lock new file mode 100644 index 0000000..33c8410 --- /dev/null +++ b/ch5-data-in-depth/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ch5-data-in-depth" +version = "0.1.0" diff --git a/ch5-data-in-depth/Cargo.toml b/ch5-data-in-depth/Cargo.toml new file mode 100644 index 0000000..3d2628b --- /dev/null +++ b/ch5-data-in-depth/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ch5-data-in-depth" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/ch5-data-in-depth/src/chip8.rs b/ch5-data-in-depth/src/chip8.rs new file mode 100644 index 0000000..0a36044 --- /dev/null +++ b/ch5-data-in-depth/src/chip8.rs @@ -0,0 +1,7 @@ + + +struct CPU { + current_operation: u16, + registers: [u8; 2], +} + diff --git a/ch5-data-in-depth/src/decode_f32.rs b/ch5-data-in-depth/src/decode_f32.rs new file mode 100644 index 0000000..74bb478 --- /dev/null +++ b/ch5-data-in-depth/src/decode_f32.rs @@ -0,0 +1,50 @@ +const BIAS: i32 = 127; +const RADIX: f32 = 2.0; + +pub fn print_f32(n: f32) { + let (sign, exp, frac) = to_parts(n); + let (sign_, exp_, mant) = decode(sign, exp, frac); + let n_ = from_parts(sign_, exp_, mant); + + println!("{} -> {}", n, n_); + println!("field | as bits | as real number"); + println!("sign | {:01b} | {}", sign, sign_); + println!("exponent | {:08b} | {}", exp, exp_); + println!("mantissa | {:023b} | {}", frac, mant); +} + +fn to_parts(n: f32) -> (u32, u32, u32) { + let bits = n.to_bits(); + + let sign = (bits >> 31) & 1; + let exponent = (bits >> 23) & 0xFF; + let fraction = bits & 0x7F_FF_FF; + + (sign, exponent, fraction) +} + +fn decode(sign: u32, exponent: u32, fraction: u32) -> (f32, f32, f32) { + let signed_1 = (-1.0f32).powf(sign as f32); + + let exponent = RADIX.powf(((exponent as i32) - BIAS) as f32); + + let mut mantissa: f32 = 1.0; + + // Mantissa is a sum of 1 + 2^(-1) + 2^(-2) + .. + 2^(-23) + for i in 0..23 { + let mask = 1 << i; + let one_at_bit_i = fraction & mask; + if one_at_bit_i != 0 { + let i_ = i as f32; + let weight = 2_f32.powf(i_ - 23.0); + mantissa += weight; + } + } + + (signed_1, exponent, mantissa) +} + +fn from_parts(sign: f32, exponent: f32, mantissa: f32) -> f32 { + sign * exponent * mantissa +} + diff --git a/ch5-data-in-depth/src/main.rs b/ch5-data-in-depth/src/main.rs new file mode 100644 index 0000000..7f26aeb --- /dev/null +++ b/ch5-data-in-depth/src/main.rs @@ -0,0 +1,26 @@ +#![cfg_attr(debug_assertions, allow(dead_code, unused_imports))] + +mod decode_f32; +mod q7; +mod chip8; + +use q7::Q7; + +fn test_decode_f32() { + let n: f32 = 42.42; + decode_f32::print_f32(n); +} + +fn test_q7() { + println!("{:?}", Q7::from(0.3)) +} + +fn test_chip() { + +} + +fn main() { + // test_decode_f32(); + // test_q7(); + test_chip(); +} diff --git a/ch5-data-in-depth/src/q7.rs b/ch5-data-in-depth/src/q7.rs new file mode 100644 index 0000000..63ad0dc --- /dev/null +++ b/ch5-data-in-depth/src/q7.rs @@ -0,0 +1,43 @@ +/// A type to encode a range from -1 to 1 into 8 bits. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Q7(i8); + +impl From for Q7 { + fn from(n: f64) -> Self { + if n >= 1.0 { + Q7(127) + } else if n <= -1.0 { + Q7(-128) + } else { + Q7((n * 128.0) as i8) + } + } +} + +impl From for f64 { + fn from(n: Q7) -> Self { + (n.0 as f64) * 2f64.powf(-7.0) // Same as / 128.0. + } +} + +impl From for Q7 { + fn from(n: f32) -> Self { + Q7::from(n as f64) + } +} + +impl From for f32 { + fn from(n: Q7) -> Self { + f64::from(n) as f32 + } +} + +mod tests { + use super::*; + + #[test] + fn simple_case() { + let a = 0.45; + assert_eq!(a, (f64::from(Q7::from(a)) * 100.0).round() / 100.0); + } +} \ No newline at end of file