Compare commits
	
		
			12 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4c994a8fef | |||
| aef2dc3760 | |||
| 52065cbc37 | |||
| ed4a9f08cd | |||
| f522eab9bf | |||
| ca91c2ea56 | |||
| 7ab69ecbe8 | |||
| 1e505683cb | |||
| 289b87a556 | |||
| 81f190dc60 | |||
| 75670b9de9 | |||
| 31143cac1d | 
| @ -5,12 +5,17 @@ edition = "2021" | ||||
| 
 | ||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||
| 
 | ||||
| [profile.dev.package."*"] # + | ||||
| opt-level = "z"     # Optimize library for size | ||||
| 
 | ||||
| [profile.release] | ||||
| opt-level = 'z'     # Optimize for size | ||||
| #opt-level = 'z'     # Optimize for size | ||||
| opt-level = 3       # Optimize for speed | ||||
| lto = true          # Enable link-time optimization | ||||
| codegen-units = 1   # Reduce number of codegen units to increase optimizations | ||||
| panic = 'abort'     # Abort on panic | ||||
| strip = true        # Strip symbols from binary* | ||||
| 
 | ||||
| [dependencies] | ||||
| text_io = "0.1.12" | ||||
| text_io = "0.1.12" | ||||
| tabled = "0.14.0" | ||||
| @ -1,5 +1,5 @@ | ||||
| use std::fmt; | ||||
| use std::fmt::Formatter; | ||||
| use std::collections::VecDeque; | ||||
| use std::{cmp, fmt}; | ||||
| 
 | ||||
| fn capitalise(s: &str) -> String { | ||||
|     let mut c = s.chars(); | ||||
| @ -10,51 +10,113 @@ fn capitalise(s: &str) -> String { | ||||
| } | ||||
| 
 | ||||
| /// A basic register capable of storing binary data.
 | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct BasicRegister { | ||||
|     /// A [Vec] that stores the binary data of the register.
 | ||||
|     memory: Vec<bool>, | ||||
|     /// A [VecDeque] that stores the binary data of the register.
 | ||||
|     memory: VecDeque<bool>, | ||||
| } | ||||
| 
 | ||||
| impl BasicRegister { | ||||
|     pub fn l_shift(&mut self) { | ||||
|         let mut res: Vec<bool> = vec![false; self.memory.len()]; | ||||
|     /// Adjusts a register to a given size in bits.
 | ||||
|     pub fn adjusted_by_size(&mut self, resulting_size: usize) -> Self { | ||||
|         let current_memory_size: usize = self.memory.len(); | ||||
|         let difference: i32 = current_memory_size as i32 - resulting_size as i32; | ||||
| 
 | ||||
|         res[..(self.memory.len() - 1)] | ||||
|             .copy_from_slice(&self.memory[1..((self.memory.len() - 1) + 1)]); | ||||
| 
 | ||||
|         self.memory = res; | ||||
|         match current_memory_size > resulting_size { | ||||
|             true => BasicRegister::new( | ||||
|                 (difference as usize..current_memory_size) | ||||
|                     .map(|i| self.memory[i]) | ||||
|                     .collect::<VecDeque<bool>>(), | ||||
|             ), | ||||
|             false => { | ||||
|                 let mut resulting_memory: VecDeque<bool> = vec![false; -difference as usize].into(); | ||||
|                 resulting_memory.append(&mut self.memory); | ||||
|                 BasicRegister::new(resulting_memory) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn r_shift(&mut self) { | ||||
|         let mut res: Vec<bool> = vec![false; self.memory.len()]; | ||||
|     /// Returns a register which was logically negated.
 | ||||
|     pub fn negated(&self) -> Self { | ||||
|         BasicRegister::new(self.memory.iter().map(|val| !val).collect()) | ||||
|     } | ||||
| 
 | ||||
|         for i in (1..self.memory.len()).rev() { | ||||
|             res[i] = self.memory[i - 1]; | ||||
|     /// Shifts the register to the left by a specified number of steps, shifting in the provided values.
 | ||||
|     pub fn left_shifted(&self, shift_in_value: bool, bits_shifted: usize) -> Self { | ||||
|         let mut shifted_memory = self.memory.clone(); | ||||
| 
 | ||||
|         for _ in 0..bits_shifted { | ||||
|             shifted_memory.pop_front(); | ||||
|             shifted_memory.push_back(shift_in_value) | ||||
|         } | ||||
| 
 | ||||
|         self.memory = res; | ||||
|         BasicRegister::new(shifted_memory) | ||||
|     } | ||||
| 
 | ||||
|     pub fn reverse(&mut self) { | ||||
|         self.memory = self.memory.iter().map(|val| !val).collect(); | ||||
|     /// Shifts the register to the left by a specified number of steps, shifting in the provided values.
 | ||||
|     pub fn right_shifted(&self, shift_in_value: bool, bits_shifted: i32) -> Self { | ||||
|         let mut shifted_memory = self.memory.clone(); | ||||
| 
 | ||||
|         for _i in 0..bits_shifted { | ||||
|             shifted_memory.pop_back(); | ||||
|             shifted_memory.push_front(shift_in_value) | ||||
|         } | ||||
| 
 | ||||
|         BasicRegister::new(shifted_memory) | ||||
|     } | ||||
| 
 | ||||
|     pub fn new(memory: Vec<bool>) -> Self { | ||||
|     /// Constructs a new BasicRegister from a given VecDeque<bool> as memory.
 | ||||
|     pub fn new(memory: VecDeque<bool>) -> Self { | ||||
|         Self { memory } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the number of bits stored in a register.
 | ||||
|     pub fn len(&self) -> usize { | ||||
|         self.memory.len() | ||||
|     } | ||||
| 
 | ||||
|     pub fn table(&self) -> String { | ||||
|         use tabled::{builder::Builder, settings::Style}; | ||||
|         let mut m_row: Vec<String> = Vec::new(); | ||||
|         self.memory | ||||
|             .iter() | ||||
|             .for_each(|bit| m_row.push((*bit as u8).to_string())); | ||||
|         let mut builder: Builder = Builder::default(); | ||||
|         builder.push_record( | ||||
|             self.memory | ||||
|                 .iter() | ||||
|                 .map(|bit| (*bit as u8).to_string()) | ||||
|                 .collect::<Vec<String>>(), | ||||
|         ); | ||||
| 
 | ||||
|         builder.build().with(Style::modern()).to_string() | ||||
|     } | ||||
| 
 | ||||
|     fn decrement(&mut self) { | ||||
|         let one = BasicRegister::new([true].into()).adjusted_by_size(self.len()); | ||||
|         self.memory = binary_subtraction(self, &one).memory; | ||||
|     } | ||||
| 
 | ||||
|     fn increment(&mut self) { | ||||
|         let one = BasicRegister::new([true].into()).adjusted_by_size(self.len()); | ||||
|         self.memory = binary_sum(self, &one).memory; | ||||
|     } | ||||
| 
 | ||||
|     fn non_zero(&mut self) -> bool { | ||||
|         self.memory.iter().any(|i| *i) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Default for BasicRegister { | ||||
|     fn default() -> Self { | ||||
|         Self { | ||||
|             memory: vec![false], | ||||
|             memory: [false].into(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl fmt::Display for BasicRegister { | ||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||
|         write!(f, "Memory: [")?; | ||||
| 
 | ||||
|         for (count, v) in self.memory.iter().enumerate() { | ||||
| @ -68,6 +130,26 @@ impl fmt::Display for BasicRegister { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl fmt::Binary for BasicRegister { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||
|         for v in self.memory.iter() { | ||||
|             write!(f, "{}", *v as u8)?; | ||||
|         } | ||||
| 
 | ||||
|         write!(f, "") | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Converts a u8 number to a boolean.
 | ||||
| ///
 | ||||
| /// # Returns
 | ||||
| /// * false - if the number is zero or below.
 | ||||
| /// * true - if the number is above zero.
 | ||||
| fn u8_to_bool(number: u8) -> bool { | ||||
|     number > 0 | ||||
| } | ||||
| 
 | ||||
| /// Reads a Vec<char> containing only 1-s and 0-s from user.
 | ||||
| fn read_vec(variable_name: &str) -> Vec<char> { | ||||
|     loop { | ||||
|         print!("Enter {variable_name}: "); | ||||
| @ -82,13 +164,14 @@ fn read_vec(variable_name: &str) -> Vec<char> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn char_to_bool_vector(char_vector: Vec<char>) -> Vec<bool> { | ||||
|     let mut bool_vector: Vec<bool> = Vec::new(); | ||||
| /// Converts a Vec<char> containing only 1-s and 0-s to VecDeque<bool>.
 | ||||
| pub fn char_to_bool_vecdeque(char_vector: Vec<char>) -> VecDeque<bool> { | ||||
|     let mut bool_vector: VecDeque<bool> = VecDeque::new(); | ||||
| 
 | ||||
|     for value in char_vector.iter() { | ||||
|     for value in char_vector.into_iter() { | ||||
|         match value { | ||||
|             '0' => bool_vector.push(false), | ||||
|             '1' => bool_vector.push(true), | ||||
|             '0' => bool_vector.push_back(false), | ||||
|             '1' => bool_vector.push_back(true), | ||||
|             _ => (), | ||||
|         } | ||||
|     } | ||||
| @ -96,6 +179,88 @@ pub fn char_to_bool_vector(char_vector: Vec<char>) -> Vec<bool> { | ||||
|     bool_vector | ||||
| } | ||||
| 
 | ||||
| pub fn get_memory(variable_name: &str) -> Vec<bool> { | ||||
|     char_to_bool_vector(read_vec(variable_name)) | ||||
| /// Handles getting the memory for the register from the user.
 | ||||
| pub fn get_memory(variable_name: &str) -> VecDeque<bool> { | ||||
|     char_to_bool_vecdeque(read_vec(variable_name)) | ||||
| } | ||||
| 
 | ||||
| /// Aligns two registers by the length of the bigger one.
 | ||||
| pub fn align_registers( | ||||
|     mut first_register: BasicRegister, | ||||
|     mut second_register: BasicRegister, | ||||
| ) -> (BasicRegister, BasicRegister) { | ||||
|     let required_size: usize = cmp::max(first_register.len(), second_register.len()); | ||||
| 
 | ||||
|     ( | ||||
|         first_register.adjusted_by_size(required_size), | ||||
|         second_register.adjusted_by_size(required_size), | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| /// Sums two terms containing binary numbers and keeps the carry-out.
 | ||||
| /// Returns a tuple containing the register with result and a carry-out.
 | ||||
| fn binary_sum_with_carry( | ||||
|     first_term: &BasicRegister, | ||||
|     second_term: &BasicRegister, | ||||
| ) -> (BasicRegister, bool) { | ||||
|     let mut sum: BasicRegister = BasicRegister::new(vec![false; first_term.len()].into()); | ||||
| 
 | ||||
|     let mut carry: bool = false; | ||||
|     let mut current_bit_sum: u8; | ||||
|     for i in (0..first_term.len()).rev() { | ||||
|         current_bit_sum = first_term.memory[i] as u8 + second_term.memory[i] as u8 + carry as u8; | ||||
|         carry = u8_to_bool(current_bit_sum & 2); | ||||
|         sum.memory[i] = u8_to_bool(current_bit_sum & 1); | ||||
|     } | ||||
| 
 | ||||
|     (sum, carry) | ||||
| } | ||||
| 
 | ||||
| /// Sums two terms containing binary numbers.
 | ||||
| /// Returns the BasicRegister with the result.
 | ||||
| pub fn binary_sum(first_term: &BasicRegister, second_term: &BasicRegister) -> BasicRegister { | ||||
|     binary_sum_with_carry(first_term, second_term).0 | ||||
| } | ||||
| 
 | ||||
| /// Subtracts the value of the subtrahend from the minuend in binary using ones' complement.
 | ||||
| pub fn binary_subtraction(minuend: &BasicRegister, subtrahend: &BasicRegister) -> BasicRegister { | ||||
|     let (difference, final_carry) = binary_sum_with_carry(minuend, &subtrahend.negated()); | ||||
| 
 | ||||
|     match final_carry { | ||||
|         true => { | ||||
|             let mut complement: Vec<bool> = vec![false; difference.len() - 1]; | ||||
|             complement.extend([true]); | ||||
|             binary_sum(&difference, &BasicRegister::new(complement.into())) | ||||
|         } | ||||
|         false => difference.negated(), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Multiplies the first term by the second term.
 | ||||
| pub fn binary_multiplication_method_1( | ||||
|     first_term: &BasicRegister, | ||||
|     second_term: &BasicRegister, | ||||
| ) -> BasicRegister { | ||||
|     let n = first_term.len(); | ||||
|     let mut rg1: BasicRegister = BasicRegister::new(vec![false; n].into()); | ||||
|     let mut rg2: &BasicRegister = first_term; | ||||
|     let rg3: &BasicRegister = second_term; | ||||
|     let mut counter: BasicRegister = BasicRegister::new(char_to_bool_vecdeque(format!("{n:b}").chars().collect())); | ||||
| 
 | ||||
|     let _i = 0; | ||||
| 
 | ||||
|     while counter.non_zero() { | ||||
|         let value_to_check = rg2.memory[n - 1].clone(); | ||||
|         if value_to_check { | ||||
|             rg1 = binary_sum(&rg1, rg3); | ||||
|         } | ||||
| 
 | ||||
|         let new_rg2 = rg2.right_shifted(rg1.memory[n - 1], 1).clone(); | ||||
|         rg2 = &rg2.right_shifted(rg1.memory[n - 1], 1); | ||||
|         rg1 = rg1.right_shifted(false, 1); | ||||
|         counter.decrement(); | ||||
|     } | ||||
| 
 | ||||
|     rg1.memory.append(&mut rg2.memory.clone()); | ||||
|     rg1 | ||||
| } | ||||
|  | ||||
							
								
								
									
										94
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								src/main.rs
									
									
									
									
									
								
							| @ -1,44 +1,60 @@ | ||||
| #[allow(dead_code)] | ||||
| #![allow(dead_code)] | ||||
| 
 | ||||
| mod bit_utilities; | ||||
| 
 | ||||
| use bit_utilities::*; | ||||
| // use text_io::read;
 | ||||
| use bit_utilities as bu; | ||||
| use text_io::read; | ||||
| 
 | ||||
| fn input_handler() { | ||||
|     let (mut first_register, mut second_register) = bu::align_registers( | ||||
|         bu::BasicRegister::new(bu::get_memory("first number")), | ||||
|         bu::BasicRegister::new(bu::get_memory("second number")), | ||||
|     ); | ||||
| 
 | ||||
|     // println!();
 | ||||
|     // println!("First register:\n{}", first_register.table());
 | ||||
|     // println!("Second register:\n{}", second_register.table());
 | ||||
| 
 | ||||
|     loop { | ||||
|         print!("\nChoose the operation:\n[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit\n>>> "); | ||||
|         let input: String = read!(); | ||||
|         match input.as_str() { | ||||
|             "a" => { | ||||
|                 let sum: bu::BasicRegister = bu::binary_sum(&first_register, &second_register); | ||||
|                 println!("Sum:\n{}\nResult (to copy): {sum:b}", sum.table()) | ||||
|             } | ||||
|             "s" => { | ||||
|                 let difference: bu::BasicRegister = | ||||
|                     bu::binary_subtraction(&first_register, &second_register); | ||||
|                 println!( | ||||
|                     "Difference:\n{}\nResult (to copy): {difference:b}", | ||||
|                     difference.table() | ||||
|                 ) | ||||
|             }, | ||||
|             "m" => loop { | ||||
|                 print!("\nChoose method to use (1-4): "); | ||||
|                 let method_input: String = read!(); | ||||
|                 match method_input.as_str() { | ||||
|                     "1" => { | ||||
|                         println!("{}", bu::binary_multiplication_method_1(&first_register, &second_register)); | ||||
|                         break; | ||||
|                     }, | ||||
|                     _ => println!("Not an available operation, try again."), | ||||
|                 } | ||||
|             }, | ||||
|             "d" => (), | ||||
|             "q" => std::process::exit(0x0100), | ||||
|             _ => println!("Not an available operation, try again."), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn main() { | ||||
|        let mut reg = BasicRegister::new(get_memory("your number")); | ||||
|     // let mut reg: BasicRegister = Default::default();
 | ||||
| 
 | ||||
|     println!("\nRegister:"); | ||||
|     println!("{}", reg); | ||||
| 
 | ||||
|     println!("\nShifted right:"); | ||||
|     reg.r_shift(); | ||||
|     println!("{}", reg); | ||||
| 
 | ||||
|     println!("\nShifted left:"); | ||||
|     reg.l_shift(); | ||||
|     println!("{}", reg); | ||||
| 
 | ||||
|     println!("\nReversed:"); | ||||
|     reg.reverse(); | ||||
|     println!("{}", reg); | ||||
| 
 | ||||
|     // println!("{}", true);
 | ||||
|     // println!("{}", true);
 | ||||
| 
 | ||||
|     // let a: i8 = read!();
 | ||||
|     // println!("{} {0:b}", a);
 | ||||
|     // println!("{} {0:b}", a >> 1);
 | ||||
|     // println!("{} {0:b}", a << 1);
 | ||||
|     // println!("{} {0:b}", !a);
 | ||||
|     // println!("{}", '3'.to_digit(2).unwrap());
 | ||||
|     // let f_text = format!("{a:b}").chars().collect::<Vec<char>>();
 | ||||
|     // println!("{:?}", f_text);
 | ||||
|     // println!("{:?}", char_to_bool_vector(f_text.clone()));
 | ||||
|     // let b: BasicRegister = BasicRegister::new(char_to_bool_vector(f_text));
 | ||||
|     // b.print_register();
 | ||||
|     // println!("{:?}", get_memory(format!("{a:b}")));
 | ||||
|     // println!("{:?}", a.split(" ").collect::<Vec<&str>>());
 | ||||
|     // a = text_io::read!("{}\n");
 | ||||
|     // println!("{a}")
 | ||||
|     // let mut reg = bu::BasicRegister::new(bu::get_memory("your number"));
 | ||||
|     // let mut reg2 = bu::BasicRegister::new(bu::get_memory("your number"));
 | ||||
|     //
 | ||||
|     // println!("{reg}");
 | ||||
|     // println!("{reg2}");
 | ||||
|     // println!("{}", bu::binary_multiplication_method_1(reg, reg2))
 | ||||
|     input_handler(); | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user