Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ed4a9f08cd | |||
| f522eab9bf | |||
| ca91c2ea56 | |||
| 7ab69ecbe8 | |||
| 1e505683cb | |||
| 289b87a556 | |||
| 81f190dc60 | |||
| 75670b9de9 | |||
| 31143cac1d |
+18
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "rust_tests"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[profile.release]
|
||||
opt-level = 'z' # Optimize for size
|
||||
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"
|
||||
prettytable-rs = "0.10.0"
|
||||
#tabled = "0.12.2"
|
||||
@@ -1,3 +0,0 @@
|
||||
# binaryCalculatorPrototype
|
||||
|
||||
This is a Python language prototype for a binary calculator to be used in Computer Arithmetics lab works for first-year students studying Computer Engineering at KPI.
|
||||
@@ -1,86 +0,0 @@
|
||||
from collections import deque
|
||||
|
||||
|
||||
class BasicRegister:
|
||||
"""The BasicRegister represents a hardware register capable of manipulating multiple bits at a time.
|
||||
|
||||
:param deque[bool] memory: The bits stored inside the register.
|
||||
"""
|
||||
|
||||
def __init__(self, memory: list[bool]):
|
||||
"""Constructor method"""
|
||||
self.memory: deque[bool] = deque(memory)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"Memory: {[int(value) for value in self.memory]}"
|
||||
|
||||
def reverse(self):
|
||||
self.memory = deque([not value for value in self.memory])
|
||||
|
||||
def left_shift(self, digit_to_fill: bool = False, steps_shifted: int = 1) -> deque[bool]:
|
||||
self.memory.extend([digit_to_fill] * steps_shifted)
|
||||
shifted_radices: deque[bool] = deque([self.memory.popleft() for _i in range(steps_shifted)])
|
||||
return shifted_radices
|
||||
|
||||
def right_shift(self, digit_to_fill: bool = False, steps_shifted: int = 1) -> deque[bool]:
|
||||
self.memory.extendleft([digit_to_fill] * steps_shifted)
|
||||
shifted_radices: deque[bool] = deque([self.memory.pop() for _i in range(steps_shifted)])
|
||||
return shifted_radices
|
||||
|
||||
def adjust_size(self, s: int) -> None:
|
||||
current_memory_size: int = len(self.memory)
|
||||
return BasicRegister([False] * max(s - current_memory_size, 0) + list(self.memory)[-current_memory_size:])
|
||||
|
||||
|
||||
def get_memory(variable_name: str) -> list[bool]:
|
||||
"""
|
||||
Reads user input to be used as a memory array.
|
||||
|
||||
:param str variable_name: The name to be displayed in the input line.
|
||||
|
||||
:return: A list of boolean values read from user.
|
||||
:rtype: list[bool]
|
||||
"""
|
||||
while True:
|
||||
input_chars: list[str] = list(input(f"Enter {variable_name}: "))
|
||||
|
||||
if all(character in ["0", "1"] for character in input_chars):
|
||||
return [True if character == "1" else False for character in input_chars]
|
||||
else:
|
||||
print(f"[ERROR] The {variable_name} may contain only 1-s and 0-s!")
|
||||
|
||||
|
||||
def sum(a_original: BasicRegister, b_original: BasicRegister) -> BasicRegister:
|
||||
"""
|
||||
Sums two registers' values.
|
||||
|
||||
:param BasicRegister a: First register.
|
||||
:param BasicRegister b: Second register.
|
||||
|
||||
:return: Register containing the result.
|
||||
:rtype: BasicRegister
|
||||
"""
|
||||
size_a = len(a_original.memory)
|
||||
size_b = len(b_original.memory)
|
||||
|
||||
required_size = max(size_a, size_b)
|
||||
|
||||
if size_a != size_b:
|
||||
a = a_original.adjust_size(required_size)
|
||||
b = b_original.adjust_size(required_size)
|
||||
else:
|
||||
a = a_original
|
||||
b = b_original
|
||||
|
||||
c = BasicRegister([False] * required_size)
|
||||
|
||||
carry = False
|
||||
for i in range(size_a - 1, 0, -1):
|
||||
current_bit_sum = a.memory[i] + b.memory[i] + carry
|
||||
carry = bool(current_bit_sum & 2)
|
||||
c.memory[i] = bool(current_bit_sum & 1)
|
||||
|
||||
final_bit_sum = a.memory[0] + b.memory[0] + carry
|
||||
c.memory[0] = bool(final_bit_sum & 1)
|
||||
|
||||
return c
|
||||
@@ -1,28 +0,0 @@
|
||||
from bitutilities import *
|
||||
import timeit
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
reg: BasicRegister = BasicRegister(get_memory("memory"))
|
||||
# print(type(reg))
|
||||
|
||||
print("\nRegister:")
|
||||
print(reg)
|
||||
|
||||
print("\nReversed:")
|
||||
reg.reverse()
|
||||
print(reg)
|
||||
|
||||
print("\nShifted left:")
|
||||
print([int(value) for value in reg.left_shift()])
|
||||
print(reg)
|
||||
|
||||
print("\nShifted right:")
|
||||
print([int(value) for value in reg.right_shift()])
|
||||
print(reg)
|
||||
|
||||
reg2: BasicRegister = BasicRegister(get_memory("more memory"))
|
||||
|
||||
reg3: BasicRegister = sum(reg, reg2)
|
||||
|
||||
print(reg3)
|
||||
@@ -0,0 +1,233 @@
|
||||
use prettytable::{Cell, Row, Table};
|
||||
use std::collections::VecDeque;
|
||||
use std::{cmp, fmt};
|
||||
|
||||
fn capitalise(s: &str) -> String {
|
||||
let mut c = s.chars();
|
||||
match c.next() {
|
||||
None => String::new(),
|
||||
Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
/// A basic register capable of storing binary data.
|
||||
#[derive(Debug)]
|
||||
pub struct BasicRegister {
|
||||
/// A [Vec] that stores the binary data of the register.
|
||||
memory: VecDeque<bool>,
|
||||
}
|
||||
|
||||
impl BasicRegister {
|
||||
/// 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;
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a register which was logically negated.
|
||||
pub fn negated(&self) -> Self {
|
||||
BasicRegister::new(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 left_shift(
|
||||
&mut self,
|
||||
shift_in_value_default: Option<bool>,
|
||||
bits_shifted_default: Option<i32>,
|
||||
) -> VecDeque<bool> {
|
||||
let shift_in_value: bool = shift_in_value_default.unwrap_or(false);
|
||||
let bits_shifted: usize = bits_shifted_default.unwrap_or(1) as usize;
|
||||
|
||||
let mut shifted_bits: VecDeque<bool> = [].into();
|
||||
for _i in 0..bits_shifted {
|
||||
shifted_bits.push_back(self.memory.pop_front().unwrap());
|
||||
self.memory.push_back(shift_in_value)
|
||||
}
|
||||
|
||||
shifted_bits
|
||||
}
|
||||
|
||||
/// Shifts the register to the left by a specified number of steps, shifting in the provided values.
|
||||
pub fn right_shift(
|
||||
&mut self,
|
||||
shift_in_value_default: Option<bool>,
|
||||
bits_shifted_default: Option<i32>,
|
||||
) -> VecDeque<bool> {
|
||||
let shift_in_value: bool = shift_in_value_default.unwrap_or(false);
|
||||
let bits_shifted: usize = bits_shifted_default.unwrap_or(1) as usize;
|
||||
|
||||
let mut shifted_bits: VecDeque<bool> = [].into();
|
||||
for _i in 0..bits_shifted {
|
||||
shifted_bits.push_back(self.memory.pop_back().unwrap());
|
||||
self.memory.push_front(shift_in_value)
|
||||
}
|
||||
|
||||
shifted_bits
|
||||
}
|
||||
|
||||
/// 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) -> Table {
|
||||
let mut table = Table::new();
|
||||
|
||||
let mut memory_row: Vec<Cell> = vec![Cell::new("Memory")];
|
||||
self.memory
|
||||
.iter()
|
||||
.for_each(|value| memory_row.push(Cell::new((*value as u8).to_string().as_str())));
|
||||
|
||||
table.add_row(Row::new(memory_row));
|
||||
table
|
||||
}*/
|
||||
}
|
||||
|
||||
impl Default for BasicRegister {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
memory: [false].into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for BasicRegister {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Memory: [")?;
|
||||
|
||||
for (count, v) in self.memory.iter().enumerate() {
|
||||
if count != 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
write!(f, "{}", *v as u8)?;
|
||||
}
|
||||
|
||||
write!(f, "]")
|
||||
}
|
||||
}
|
||||
|
||||
/*impl fmt::Binary for BasicRegister {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Memory: ")?;
|
||||
|
||||
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}: ");
|
||||
let input: String = text_io::read!("{}\n");
|
||||
match input.chars().all(|c| c == '1' || c == '0') {
|
||||
true => return input.chars().collect(),
|
||||
false => eprintln!(
|
||||
"[ERROR] {} may contain only 1-s and 0-s with no whitespaces!",
|
||||
capitalise(variable_name)
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.into_iter() {
|
||||
match value {
|
||||
'0' => bool_vector.push_back(false),
|
||||
'1' => bool_vector.push_back(true),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
bool_vector
|
||||
}
|
||||
|
||||
/// 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(),
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
#[allow(dead_code)]
|
||||
mod bit_utilities;
|
||||
|
||||
use bit_utilities as bu;
|
||||
use text_io::read;
|
||||
|
||||
fn input_handler(first_register: bu::BasicRegister, second_register: bu::BasicRegister) {
|
||||
let (first_register, second_register) = bu::align_registers(first_register, second_register);
|
||||
|
||||
println!();
|
||||
println!("{}", first_register);
|
||||
println!("{}", second_register);
|
||||
|
||||
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" => println!(
|
||||
"Sum:\n{}",
|
||||
bu::binary_sum(&first_register, &second_register)
|
||||
),
|
||||
"s" => println!(
|
||||
"Subtraction:\n{}",
|
||||
bu::binary_subtraction(&first_register, &second_register)
|
||||
),
|
||||
"m" => (),
|
||||
"d" => (),
|
||||
"q" => std::process::exit(0x0100),
|
||||
_ => println!("Not an available operation, try again."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let reg = bu::BasicRegister::new(bu::get_memory("your number"));
|
||||
let reg2 = bu::BasicRegister::new(bu::get_memory("your number"));
|
||||
|
||||
input_handler(reg, reg2);
|
||||
}
|
||||
Reference in New Issue
Block a user