diff options
Diffstat (limited to 'meap/meap-code/ch5')
27 files changed, 857 insertions, 0 deletions
diff --git a/meap/meap-code/ch5/ch5-cpu1/Cargo.lock b/meap/meap-code/ch5/ch5-cpu1/Cargo.lock new file mode 100644 index 0000000..2baaa64 --- /dev/null +++ b/meap/meap-code/ch5/ch5-cpu1/Cargo.lock @@ -0,0 +1,4 @@ +[[package]]
+name = "ch5-cpu1"
+version = "0.1.0"
+
diff --git a/meap/meap-code/ch5/ch5-cpu1/Cargo.toml b/meap/meap-code/ch5/ch5-cpu1/Cargo.toml new file mode 100644 index 0000000..060a235 --- /dev/null +++ b/meap/meap-code/ch5/ch5-cpu1/Cargo.toml @@ -0,0 +1,6 @@ +[package]
+name = "ch5-cpu1"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
diff --git a/meap/meap-code/ch5/ch5-cpu1/src/main.rs b/meap/meap-code/ch5/ch5-cpu1/src/main.rs new file mode 100644 index 0000000..c934c13 --- /dev/null +++ b/meap/meap-code/ch5/ch5-cpu1/src/main.rs @@ -0,0 +1,60 @@ +const ARITHMETIC_AND_LOGIC: u8 = 0x8;
+const HALT: u8 = 0x0; // <1>
+const ADD_XY: u8 = 0x4;
+
+struct CPU {
+ // current_operation: u16, // <2>
+ registers: [u8; 16], // <3>
+ position_in_memory: usize, // <4>
+ memory: [u8; 4096], // <5>
+}
+
+impl CPU {
+ fn run(&mut self) {
+ loop {
+ let op_byte1 = self.memory[self.position_in_memory] as u16; // <6>
+ let op_byte2 = self.memory[self.position_in_memory + 1] as u16; // <6>
+ let raw_op = op_byte1 << 8 | op_byte2; // <7>
+
+ let op_major = ((raw_op & 0xF000) >> 12) as u8;
+ let x = ((raw_op & 0x0F00) >> 8) as u8;
+ let y = ((raw_op & 0x00F0) >> 4) as u8;
+ let op_minor = (raw_op & 0x000F) as u8;
+
+ self.position_in_memory += 2; // <8>
+
+ match (op_major, op_minor) {
+ (HALT, HALT) => { return; }, // <9>
+ (ARITHMETIC_AND_LOGIC, ADD_XY) => self.add_xy(x, y),
+ _ => unimplemented!("opcode {:04x}", raw_op), // <10>
+ }
+ }
+ }
+
+ fn add_xy(&mut self, x: u8, y: u8) {
+ self.registers[x as usize] += self.registers[y as usize];
+ }
+}
+
+fn main() {
+ let mut cpu = CPU {
+ registers: [0; 16],
+ memory: [0; 4096],
+ position_in_memory: 0,
+ };
+
+ cpu.registers[0] = 5;
+ cpu.registers[1] = 10;
+ cpu.registers[2] = 10; // <11>
+ cpu.registers[3] = 10; // <11>
+
+ cpu.memory[0] = 0x80; cpu.memory[1] = 0x14; // <12>
+ cpu.memory[2] = 0x80; cpu.memory[3] = 0x24; // <13>
+ cpu.memory[4] = 0x80; cpu.memory[5] = 0x34; // <14>
+
+ cpu.run();
+
+ assert_eq!(cpu.registers[0], 35);
+
+ println!("5 + 10 + 10 + 10 = {}", cpu.registers[0]);
+}
\ No newline at end of file diff --git a/meap/meap-code/ch5/ch5-cpu2/Cargo.lock b/meap/meap-code/ch5/ch5-cpu2/Cargo.lock new file mode 100644 index 0000000..eda929e --- /dev/null +++ b/meap/meap-code/ch5/ch5-cpu2/Cargo.lock @@ -0,0 +1,4 @@ +[[package]]
+name = "ch5-cpu2"
+version = "0.1.0"
+
diff --git a/meap/meap-code/ch5/ch5-cpu2/Cargo.toml b/meap/meap-code/ch5/ch5-cpu2/Cargo.toml new file mode 100644 index 0000000..9b115b5 --- /dev/null +++ b/meap/meap-code/ch5/ch5-cpu2/Cargo.toml @@ -0,0 +1,6 @@ +[package]
+name = "ch5-cpu2"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
diff --git a/meap/meap-code/ch5/ch5-cpu2/src/main.rs b/meap/meap-code/ch5/ch5-cpu2/src/main.rs new file mode 100644 index 0000000..8271ca8 --- /dev/null +++ b/meap/meap-code/ch5/ch5-cpu2/src/main.rs @@ -0,0 +1,60 @@ +const HALT: u8 = 0x0;
+const ARITHMETIC_AND_LOGIC: u8 = 0x8;
+const ADD_XY: u8 = 0x4;
+
+struct CPU {
+ // current_operation: u16, // no longer needed
+ registers: [u8; 16], // increase number of registers to 16 (0..F), as per CHIP-8
+ position_in_memory: usize, // add a program counter.. using a usize to simplify array indexing
+ memory: [u8; 4096], // give the system 4kb memory
+}
+
+impl CPU {
+ fn run(&mut self) {
+ loop {
+ let op_byte1 = self.memory[self.position_in_memory] as u16; //
+ let op_byte2 = self.memory[self.position_in_memory + 1] as u16; //
+ let raw_op = op_byte1 << 8 | op_byte2;
+
+ self.position_in_memory += 2;
+
+ let op_major = ((raw_op & 0xF000) >> 12) as u8;
+ let x = ((raw_op & 0x0F00) >> 8) as u8;
+ let y = ((raw_op & 0x00F0) >> 4) as u8;
+ let op_minor = (raw_op & 0x000F) as u8;
+
+ match (op_major, op_minor) {
+ (HALT, HALT) => { return; },
+ (ARITHMETIC_AND_LOGIC, ADD_XY) => self.add_xy(x, y),
+ _ => unimplemented!("opcode {:04x}", raw_op), // this macro is useful when you are debugging, as it will promptly indicate that you have made a typo
+ }
+ }
+ }
+
+ fn add_xy(&mut self, x: u8, y: u8) {
+ self.registers[x as usize] += self.registers[y as usize];
+ }
+}
+
+fn main() {
+ let mut cpu = CPU {
+ registers: [0; 16],
+ memory: [0; 4096],
+ position_in_memory: 0,
+ };
+
+ cpu.registers[0] = 5;
+ cpu.registers[1] = 10;
+ cpu.registers[2] = 10; // initialise a few more registers
+ cpu.registers[3] = 10; //
+
+ cpu.memory[0] = 0x80; cpu.memory[1] = 0x14; // 0x8014 -> ADD register 1 to register 0
+ cpu.memory[2] = 0x80; cpu.memory[3] = 0x24; // 0x8014 -> ADD register 2 to register 0
+ cpu.memory[4] = 0x80; cpu.memory[5] = 0x34; // 0x8014 -> ADD register 3 to register 0
+
+ cpu.run();
+
+ assert_eq!(cpu.registers[0], 35);
+
+ println!("5 + 10 + 10 + 10 = {}", cpu.registers[0]);
+}
diff --git a/meap/meap-code/ch5/ch5-cpu3/Cargo.lock b/meap/meap-code/ch5/ch5-cpu3/Cargo.lock new file mode 100644 index 0000000..6262526 --- /dev/null +++ b/meap/meap-code/ch5/ch5-cpu3/Cargo.lock @@ -0,0 +1,4 @@ +[[package]]
+name = "ch5-cpu3"
+version = "0.1.0"
+
diff --git a/meap/meap-code/ch5/ch5-cpu3/Cargo.toml b/meap/meap-code/ch5/ch5-cpu3/Cargo.toml new file mode 100644 index 0000000..1f964df --- /dev/null +++ b/meap/meap-code/ch5/ch5-cpu3/Cargo.toml @@ -0,0 +1,6 @@ +[package]
+name = "ch5-cpu3"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
diff --git a/meap/meap-code/ch5/ch5-cpu3/src/main.rs b/meap/meap-code/ch5/ch5-cpu3/src/main.rs new file mode 100644 index 0000000..903ef23 --- /dev/null +++ b/meap/meap-code/ch5/ch5-cpu3/src/main.rs @@ -0,0 +1,88 @@ +struct CPU {
+ registers: [u8; 16],
+ position_in_memory: usize,
+ memory: [u8; 4096],
+ stack: [u16; 16],
+ stack_pointer: usize,
+}
+
+impl CPU {
+ fn run(&mut self) {
+ loop {
+ let op_byte1 = self.memory[self.position_in_memory] as u16;
+ let op_byte2 = self.memory[self.position_in_memory + 1] as u16;
+ let opcode = op_byte1 << 8 | op_byte2;
+
+ let x = ((opcode & 0x0F00) >> 8) as u8;
+ let y = ((opcode & 0x00F0) >> 4) as u8;
+ let op_minor = (opcode & 0x000F) as u8;
+ let addr = opcode & 0x0FFF;
+
+ self.position_in_memory += 2;
+
+ match opcode {
+ 0x0000 => { return; },
+ 0x00EE => { self.ret(); },
+ 0x2000...0x2FFF => { self.call(addr); },
+ 0x8000...0x8FFF => {
+ match op_minor {
+ 4 => { self.add_xy(x, y); }
+ _ => { unimplemented!("opcode: {:04x}", opcode); },
+ }
+ },
+ _ => unimplemented!("opcode {:04x}", opcode),
+ }
+ }
+ }
+
+ fn call(&mut self, addr: u16) {
+ let sp = self.stack_pointer;
+ let stack = &mut self.stack;
+
+ if sp > stack.len() {
+ panic!("Stack overflow!")
+ }
+
+ stack[sp] = self.position_in_memory as u16;
+ self.stack_pointer += 1;
+ self.position_in_memory = addr as usize;
+ }
+ fn ret(&mut self) {
+ if self.stack_pointer == 0 {
+ panic!("Stack underflow");
+ }
+
+ self.stack_pointer -= 1;
+ self.position_in_memory = self.stack[self.stack_pointer] as usize;
+ }
+
+ fn add_xy(&mut self, x: u8, y: u8) {
+ self.registers[x as usize] += self.registers[y as usize];
+ }
+}
+
+fn main() {
+ let mut cpu = CPU {
+ registers: [0; 16],
+ memory: [0; 4096],
+ position_in_memory: 0,
+ stack: [0; 16],
+ stack_pointer: 0,
+ };
+
+ cpu.registers[0] = 5;
+ cpu.registers[1] = 10;
+
+ cpu.memory[0x000] = 0x21; cpu.memory[0x001] = 0x00;
+ cpu.memory[0x002] = 0x21; cpu.memory[0x003] = 0x00;
+
+ cpu.memory[0x100] = 0x80; cpu.memory[0x101] = 0x14;
+ cpu.memory[0x102] = 0x80; cpu.memory[0x103] = 0x14;
+ cpu.memory[0x104] = 0x00; cpu.memory[0x105] = 0xEE;
+
+ cpu.run();
+
+ assert_eq!(cpu.registers[0], 45);
+
+ println!("5 + (10 * 2) + (10 * 2) = {}", cpu.registers[0]);
+}
\ No newline at end of file diff --git a/meap/meap-code/ch5/ch5-f32-as-u32.rs b/meap/meap-code/ch5/ch5-f32-as-u32.rs new file mode 100644 index 0000000..b23cf89 --- /dev/null +++ b/meap/meap-code/ch5/ch5-f32-as-u32.rs @@ -0,0 +1,8 @@ +fn main() {
+ let a: f32 = 42.42;
+ let frankentype: u32 = unsafe {
+ std::mem::transmute(a) // <1>
+ };
+
+ println!("{:032b}", frankentype); // <2>
+}
\ No newline at end of file diff --git a/meap/meap-code/ch5/ch5-fixed-width.rs b/meap/meap-code/ch5/ch5-fixed-width.rs new file mode 100644 index 0000000..fa0b867 --- /dev/null +++ b/meap/meap-code/ch5/ch5-fixed-width.rs @@ -0,0 +1,34 @@ +use num::{Float};
+
+/// 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)
+struct Q1_7(i8); // tuple struct holding a i8 value
+
+impl From<T: Float> for Q1_7 {
+ fn from (n:T) -> Self {
+ let val = if n > 1.0 { // out of bounds numbers are coerced to the maximum of the range
+ 1
+ } else if n < -1.0 {
+ -1
+ } else {
+ n * (2**7)
+ }
+
+ Q1_7(val as i8)
+ }
+}
+
+impl From for U: Float {
+ fn from(q: Q1_7) -> U {
+ q.0 * (2 ** -7)
+ }
+}
+
+mod tests {
+ use super::*;
+
+ test
+}
\ No newline at end of file diff --git a/meap/meap-code/ch5/ch5-genfib/Cargo.lock b/meap/meap-code/ch5/ch5-genfib/Cargo.lock new file mode 100644 index 0000000..83a7013 --- /dev/null +++ b/meap/meap-code/ch5/ch5-genfib/Cargo.lock @@ -0,0 +1,102 @@ +[root]
+name = "genfib"
+version = "0.1.0"
+dependencies = [
+ "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "num"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-bigint 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-complex 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.1.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-complex"
+version = "0.1.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-iter"
+version = "0.1.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.1.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-bigint 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rand"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-serialize"
+version = "0.3.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"
+"checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40"
+"checksum num-bigint 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "5e2955fede25639c4f4f797e864b7585f20d98069c45e0c86b1d22a808eb9f77"
+"checksum num-complex 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "3534898d8a1f6b16c12f9fc2f4eaabc7ecdcc55f267213caa8988fdc7d60ff94"
+"checksum num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "21e4df1098d1d797d27ef0c69c178c3fab64941559b290fcae198e0825c9c8b5"
+"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
+"checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44"
+"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
+"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
+"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
diff --git a/meap/meap-code/ch5/ch5-genfib/Cargo.toml b/meap/meap-code/ch5/ch5-genfib/Cargo.toml new file mode 100644 index 0000000..1324537 --- /dev/null +++ b/meap/meap-code/ch5/ch5-genfib/Cargo.toml @@ -0,0 +1,7 @@ +[package]
+name = "genfib"
+version = "0.1.0"
+authors = ["Tim"]
+
+[dependencies]
+num = "0.1"
diff --git a/meap/meap-code/ch5/ch5-genfib/src/main.rs b/meap/meap-code/ch5/ch5-genfib/src/main.rs new file mode 100644 index 0000000..e3c95e0 --- /dev/null +++ b/meap/meap-code/ch5/ch5-genfib/src/main.rs @@ -0,0 +1,17 @@ +extern crate num;
+
+use num::{Integer, Unsigned};
+
+fn fibonacci<T: Integer + Unsigned>(n: T) -> T {
+ match n {
+ 0 => 0,
+ 1 => 1,
+ _ => n + fibonacci(n-1),
+ }
+}
+
+fn main() {
+ let n = 10;
+ println!("{}", fibonacci(n as u16));
+ println!("{}", fibonacci(n as u64));
+}
diff --git a/meap/meap-code/ch5/ch5-impossible-add.rs b/meap/meap-code/ch5/ch5-impossible-add.rs new file mode 100644 index 0000000..f7f238d --- /dev/null +++ b/meap/meap-code/ch5/ch5-impossible-add.rs @@ -0,0 +1,5 @@ +fn main() {
+ let (a, b) = (200, 200);
+ let c: u8 = a + b; // <1>
+ println!("200 + 200 = {}", c);
+}
\ No newline at end of file diff --git a/meap/meap-code/ch5/ch5-message-store/Cargo.lock b/meap/meap-code/ch5/ch5-message-store/Cargo.lock new file mode 100644 index 0000000..e5df836 --- /dev/null +++ b/meap/meap-code/ch5/ch5-message-store/Cargo.lock @@ -0,0 +1,4 @@ +[root]
+name = "ch5-message-store"
+version = "0.1.0"
+
diff --git a/meap/meap-code/ch5/ch5-message-store/Cargo.toml b/meap/meap-code/ch5/ch5-message-store/Cargo.toml new file mode 100644 index 0000000..4fb4bc0 --- /dev/null +++ b/meap/meap-code/ch5/ch5-message-store/Cargo.toml @@ -0,0 +1,6 @@ +[package]
+name = "ch5-message-store"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
diff --git a/meap/meap-code/ch5/ch5-message-store/src/main.rs b/meap/meap-code/ch5/ch5-message-store/src/main.rs new file mode 100644 index 0000000..e790a57 --- /dev/null +++ b/meap/meap-code/ch5/ch5-message-store/src/main.rs @@ -0,0 +1,93 @@ +
+#[derive(Debug)]
+struct CubeSat {
+ id: u64,
+}
+
+#[derive(Debug)]
+enum StatusMessage {
+ Ok,
+}
+
+#[derive(Debug)]
+struct Mailbox {
+ messages: Vec<Message>,
+}
+
+#[derive(Debug)]
+struct Message {
+ to: u64,
+ content: String,
+}
+
+struct GroundStation {}
+
+impl Mailbox {
+ fn post(&mut self, to: &CubeSat, msg: Message) {
+ self.messages.push(msg);
+ }
+
+ fn deliver(&mut self, recipient: &CubeSat) -> Option<Message> {
+ for i in 0..self.messages.len() {
+ if self.messages[i].to == recipient.id {
+ let msg = self.messages.remove(i);
+ return Some(msg);
+ }
+ }
+
+ None
+ }
+}
+
+impl GroundStation {
+ fn connect(&self, sat_id: u64) -> CubeSat {
+ CubeSat {
+ id: sat_id,
+ }
+ }
+
+ fn send(&self, mailbox: &mut Mailbox, to: &CubeSat, msg: Message) {
+ mailbox.post(to, msg);
+ }
+}
+
+impl CubeSat {
+ fn recv(&self, mailbox: &mut Mailbox) -> Option<Message> {
+ mailbox.deliver(&self)
+ }
+}
+
+// fn main() {
+// let base = GroundStation {};
+// let mut sat_a = CubeSat { id: 0, mailbox: Mailbox { messages: vec![] } };
+// let mut sat_b = CubeSat { id: 1, mailbox: Mailbox { messages: vec![] } };
+// let mut sat_c = CubeSat { id: 2, mailbox: Mailbox { messages: vec![] } };
+
+// }
+
+/// Returns a vector of CubeSat IDs
+fn fetch_sat_ids() -> Vec<u64> {
+ vec![1,2,3]
+}
+
+
+fn main() {
+ let mut mail = Mailbox { messages: vec![] };
+
+ let base = GroundStation {};
+
+ let sat_ids = fetch_sat_ids();
+
+ for sat_id in &sat_ids {
+ let sat = base.connect(sat_id);
+ let msg = Message { to: sat_id, content: String::from("hello") };
+ base.send(&mut mail, &sat, msg);
+ }
+
+ for sat_id in &sat_ids {
+ let sat = base.connect(sat_id);
+
+ let msg = sat.recv(&mut mail);
+ println!("{:?}: {:?}", sat, msg);
+ }
+}
\ No newline at end of file diff --git a/meap/meap-code/ch5/ch5-q/Cargo.lock b/meap/meap-code/ch5/ch5-q/Cargo.lock new file mode 100644 index 0000000..3ac932f --- /dev/null +++ b/meap/meap-code/ch5/ch5-q/Cargo.lock @@ -0,0 +1,127 @@ +[root]
+name = "ch5-q"
+version = "0.1.0"
+dependencies = [
+ "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bitflags"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "fuchsia-zircon"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "num"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-complex"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-iter"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.1.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rand"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-serialize"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
+"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
+"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
+"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"
+"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525"
+"checksum num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "8fd0f8dbb4c0960998958a796281d88c16fbe68d87b1baa6f31e2979e81fd0bd"
+"checksum num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "503e668405c5492d67cf662a81e05be40efe2e6bcf10f7794a07bd9865e704e6"
+"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
+"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
+"checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790"
+"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
+"checksum rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "61efcbcd9fa8d8fbb07c84e34a8af18a1ff177b449689ad38a6e9457ecc7b2ae"
+"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
diff --git a/meap/meap-code/ch5/ch5-q/Cargo.toml b/meap/meap-code/ch5/ch5-q/Cargo.toml new file mode 100644 index 0000000..ffd0826 --- /dev/null +++ b/meap/meap-code/ch5/ch5-q/Cargo.toml @@ -0,0 +1,7 @@ +[package]
+name = "ch5-q"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
+num = "*"
\ No newline at end of file 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<f64> 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<Q7> for f64 {
+ fn from(n: Q7) -> f64 {
+ (n.0 as f64) * 2f64.powf(-7.0) // 0.0078125// (2 ** -7) // pow(2, -7)
+ }
+}
+
+impl From<f32> for Q7 {
+ fn from (n: f32) -> Self {
+ Q7::from(n as f64) // conversion from f32 to f64 works perfectly
+ }
+}
+
+impl From<Q7> 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);
+ }
+}
diff --git a/meap/meap-code/ch5/ch5-sat-messaging/msg-with-refs/Cargo.lock b/meap/meap-code/ch5/ch5-sat-messaging/msg-with-refs/Cargo.lock new file mode 100644 index 0000000..79da38d --- /dev/null +++ b/meap/meap-code/ch5/ch5-sat-messaging/msg-with-refs/Cargo.lock @@ -0,0 +1,4 @@ +[root]
+name = "msg-with-refs"
+version = "0.1.0"
+
diff --git a/meap/meap-code/ch5/ch5-sat-messaging/msg-with-refs/Cargo.toml b/meap/meap-code/ch5/ch5-sat-messaging/msg-with-refs/Cargo.toml new file mode 100644 index 0000000..699bbde --- /dev/null +++ b/meap/meap-code/ch5/ch5-sat-messaging/msg-with-refs/Cargo.toml @@ -0,0 +1,6 @@ +[package]
+name = "msg-with-refs"
+version = "0.1.0"
+authors = ["Tim McNamara <code@timmcnamara.co.nz>"]
+
+[dependencies]
diff --git a/meap/meap-code/ch5/ch5-sat-messaging/msg-with-refs/src/main.rs b/meap/meap-code/ch5/ch5-sat-messaging/msg-with-refs/src/main.rs new file mode 100644 index 0000000..394f6cd --- /dev/null +++ b/meap/meap-code/ch5/ch5-sat-messaging/msg-with-refs/src/main.rs @@ -0,0 +1,51 @@ +#[derive(Debug)]
+enum StatusCode {
+ Ok,
+}
+
+#[derive(Debug)]
+struct Mailbox {
+ messages: Vec<Message>,
+}
+
+type Message = String;
+
+#[derive(Debug)]
+struct CubeSat {
+ id: u64,
+ mailbox: Mailbox,
+}
+
+impl CubeSat {
+ fn recv(&mut self) -> Option<Message> {
+ self.mailbox.messages.pop()
+ }
+}
+
+struct GroundStation;
+
+impl GroundStation {
+ fn send(&self, to: &mut CubeSat, msg: Message) {
+ to.mailbox.messages.push(msg);
+ }
+}
+
+fn main() {
+ let base = GroundStation {};
+ let mut sat_a = CubeSat { id: 0, mailbox: Mailbox { messages: vec![] } };
+ let mut sat_b = CubeSat { id: 1, mailbox: Mailbox { messages: vec![] } };
+ let mut sat_c = CubeSat { id: 2, mailbox: Mailbox { messages: vec![] } };
+
+ println!("t0: {:?}", sat_a);
+
+ // sat_a.mailbox.messages.push(Message::from("hi"));
+
+ base.send(&mut sat_a, Message::from("hello there!"));
+
+ println!("t1: {:?}", sat_a);
+
+ let msg = sat_a.recv();
+ //println!("{:?}", msg);
+
+ println!("t2: {:?}", sat_a);
+}
diff --git a/meap/meap-code/ch5/ch5-to-oblivion.rs b/meap/meap-code/ch5/ch5-to-oblivion.rs new file mode 100644 index 0000000..1bfee53 --- /dev/null +++ b/meap/meap-code/ch5/ch5-to-oblivion.rs @@ -0,0 +1,11 @@ +fn main() {
+ let mut i: u16 = 0;
+ print!("{:}..", i);
+ loop {
+ i += 1000;
+ print!("{}..", i);
+ if i % 10000 == 0 {
+ print!{"\n"}
+ }
+ }
+}
\ No newline at end of file diff --git a/meap/meap-code/ch5/ch5-u8-to-mock-rand.rs b/meap/meap-code/ch5/ch5-u8-to-mock-rand.rs new file mode 100644 index 0000000..46ac91a --- /dev/null +++ b/meap/meap-code/ch5/ch5-u8-to-mock-rand.rs @@ -0,0 +1,17 @@ +// fn mock_rand(n: u8) -> f32 {
+// (n as f32) / 255.
+// }
+
+fn mock_rand(n: u8) -> f32 {
+ let base: u32 = 0b0_01111110_00000000000000000000000; // <1> Underscores mark the sign/mantissa/exponent boundaries
+ let large_n = (n as u32) << 15; // <2> Align the input byte `n` to 32 bits, then increase its value by shifting its bits 15 places to the left
+ let f32_bits = base | large_n; // <3> Take a bitwise OR, merging the base with the input byte
+ let m = f32::from_bits(f32_bits);// <4> Interpret `f32_bits` (which is type `u32`) as an `f32`
+ 2.0 * ( m - 0.5 ) // <5> Normalize the output range
+}
+
+fn main() {
+ println!("max of input range: {:08b} -> {}", 0xff, mock_rand(0xff));
+ println!("mid of input range: {:08b} -> {}", 0x77, mock_rand(0x77));
+ println!("min of input range: {:08b} -> {}", 0x00, mock_rand(0x00));
+}
\ No newline at end of file diff --git a/meap/meap-code/ch5/ch5-visualising-f32.rs b/meap/meap-code/ch5/ch5-visualising-f32.rs new file mode 100644 index 0000000..6de5526 --- /dev/null +++ b/meap/meap-code/ch5/ch5-visualising-f32.rs @@ -0,0 +1,44 @@ +const BIAS: i32 = 127; // <1> Similar constants are accessible via the `std::f32` module
+const RADIX: f32 = 2.0; // <1>
+
+fn main() { // <2> main() can live happily at the beginning of a file
+ let n: f32 = 42.42;
+
+ let (signbit, exponent, fraction) = deconstruct_f32(n); // <3> Here the three components of `n` are extracted, with each one being an uninterpreted sequence of bits
+ println!("{} -> [sign:{:01b}, exponent:{:08b}, mantissa:{:023b}] -> tbc", n, signbit, exponent, fraction);
+
+ let (sign, exponent, mantissa) = decode_f32_parts(signbit, exponent, fraction); // <4> Each component is interpreted according to the standard
+ let reconstituted_n = f32_from_parts(sign, exponent, mantissa); // <5> The original value is produced from those three components
+ println!("{} -> [sign:{}, exponent:{}, mantissa:{:?}] -> {}", n, signbit, exponent, mantissa, reconstituted_n);
+}
+
+fn deconstruct_f32(n: f32) -> (u32, u32, u32) {
+ let n_: u32 = unsafe { std::mem::transmute(n) };
+
+ let sign = (n_ >> 31) & 1; // <2> strip 31 unwanted bits away by shifting them into nowhere, leaving only the sign bit
+ let exponent = (n_ >> 23) & 0xff; // <3> filter out the top bit with a logical AND mask, then strip 23 unwanted bits away
+ let fraction = 0b00000000_01111111_11111111_11111111 & n_; // <4> only retain the 23 "`least significant`" bits via a mask
+
+ (sign, exponent, fraction) // <5> The mantissa part is called a fraction here, as it becomes the mantissa once it's decoded
+}
+
+fn decode_f32_parts(sign: u32, exponent: u32, fraction: u32) -> (f32, f32, f32) {
+ let signed_1 = (-1.0_f32).powf(sign as f32); // <6> Convert the sign bit to 1.0 or -1.0. Parentheses are required around `-1.0_f32` to clarify operator precedence as method calls rank higher than unary minus.
+
+ let exponent = (exponent as i32) - BIAS; // <7> We need to do a bit of a type dance here. `exponent` must become an `i32` in case subtracting the `BIAS` results in a negative number. Then it needs to be cast as a `f32`, so that it can be used for exponentiation.
+ let exponent = RADIX.powf(exponent as f32); // <7>
+
+ let mut mantissa: f32 = 1.0; // <8> We start by assuming that the implicit 24th bit is set. That has the upshot of defaulting the mantissa's value as 1.
+ for i in 0..23_u32 { // <9> We provide a concrete type here to ensure that the bit patterns that are generated by the mask are defined
+ let one_at_bit_i = 1 << i; // <10> At each iteration, create an AND mask of a single bit in the position that we're currently interested in.
+ if (one_at_bit_i & fraction) != 0 { // <11> Any non-zero result means that the bit is present within `fraction`
+ mantissa += 2_f32.powf((i as f32) - 23.0); // <11> To arrive at the decimal value of the bit at `i`, we find 2^i-23^. -23 means that the result gets smaller when `i` is close to 0, as desired.
+ }
+ }
+
+ (signed_1, exponent, mantissa)
+}
+
+fn f32_from_parts(sign: f32, exponent: f32, mantissa: f32) -> f32 { // <12> This code cheats a bit by using `f32` values in intermediate steps. Hopefully it is a forgivable offense.
+ sign * exponent * mantissa
+}
\ No newline at end of file |