Skip to content

Commit 8cc0787

Browse files
Initial Commit
0 parents  commit 8cc0787

File tree

12 files changed

+359
-0
lines changed

12 files changed

+359
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/target

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "booths-algorithm"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Jyotismoy Kalita
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Booth's Algorithm Step Visualization
2+
3+
by [Jyotismoy Kalita](https://github.com/JyotismoyKalita)
4+
5+
## Description
6+
7+
A small program written in Rust to display the Booth's Algorithm for multiplication step by step.
8+
9+
## Cloning the repository
10+
11+
```sh
12+
# Clone the repository
13+
git clone https://github.com/JyotismoyKalita/booths-algorithm.git
14+
cd booths-algo
15+
```
16+
17+
## Running Source file with cargo
18+
19+
You can compile and run your program using cargo:
20+
21+
### Compiling
22+
23+
```sh
24+
#debug version
25+
#for release use --release
26+
cargo build
27+
```
28+
29+
### Running
30+
31+
```sh
32+
#debug version
33+
#for release use --release
34+
#Use "-h" for help.
35+
#Use "-r VALUE" for specifying the Register Size
36+
cargo run
37+
```
38+
39+
## Using the binary - booths-algorithm
40+
41+
Suppose in your current working directory you have saved the binary executable with the name `booths-algorithm`
42+
43+
### Run the program
44+
45+
Running without -r flag would let you enter the register size during runtime.
46+
47+
```sh
48+
./booths-algorithm
49+
```
50+
51+
### Run in Help mode
52+
53+
Display Help and other useful information
54+
55+
```sh
56+
./booths-algorithm -h
57+
```
58+
59+
### Run with -r flag
60+
61+
Run with register size specified at compile time.
62+
63+
```sh
64+
#here the Register size is specified as 4 bits
65+
./booths-algorithm -r 4
66+
```
67+
68+
## Modules
69+
70+
### Under the `booth` module we have 4 submodules
71+
72+
- **io.rs**: Contains functions for taking input and printing the values
73+
- **ops.rs**: Contains Operations of Booth's Algorithm
74+
- **utils.rs**: Contains other utility functions
75+
- **console.rs**: Contains console functions
76+
77+
### Structure
78+
79+
```sh
80+
📦 booths-algotithm
81+
├─ 📦 src
82+
│  ├─ 📦 booth
83+
│  │  ├─ 📄mod.rs
84+
│  │  ├─ 📄io.rs
85+
│  │  ├─ 📄ops.rs
86+
│  │  ├─ 📄util.rs
87+
│  │  └─ 📄console.rs
88+
│  ├─ 📄main.rs
89+
│  └─ 📄lib.rs
90+
│  .gitignore
91+
│  🔒Cargo.lock
92+
├─ Cargo.toml
93+
├─ 📖README.md
94+
└─ 🪪LICENSE 
95+
```
96+
97+
## Help
98+
99+
### FLAGS
100+
101+
`-r X`: Specify the register bit size where X is the specified size. 0 < X <= 16.
102+
If Register flag is not used when executing the program. The option to specify register will
103+
show during runtime.
104+
105+
`-h`: Use help.
106+
107+
### DEFINITION OF STEPS
108+
109+
`Initialization`:&emsp;Initial Value after loading up Multiplier and Multiplicand.
110+
111+
`A <- A + M`:&emsp;&emsp;&emsp;Values of Register A & M are added and put back into A register.
112+
113+
`A <- A - M`:&emsp;&emsp;&emsp;Values of Register M subtracted from A and put into A register.
114+
115+
`ASR`:&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;Arithmetic Shift Right. The MSB is retained while all other bits are shifted right starting from A to Q-1.
116+
117+
### ALGORITHM
118+
119+
Action is determined by the Bits stored in 0th bit of Q and -1th bit of Q a.k.a Q-1. Here's the table for the actions -
120+
121+
<div align="center">
122+
123+
|Q |Q-1 |Action |
124+
|:--:|:--:|:---------------------------:|
125+
|0 |0 |**ASR** |
126+
|0 |1 |**A <- A + M** *then* **ASR**|
127+
|1 |0 |**A <- A - M** *then* **ASR**|
128+
|1 |1 |**ASR** |
129+
130+
</div>
131+
132+
This Algorithm is repeated as many times as there are Bits in the Registers.
133+
134+
E.g. If Register size if 4, the Algorithm is repeated 4 times.

src/booth/console.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use std::process::exit;
2+
3+
pub const R_FLAG: &str = "-r";
4+
pub const H_FLAG: &str = "-h";
5+
pub const HELP: &str = "
6+
*******************Booth's Algorithm Step Visualization***************************
7+
- by Jyotismoy Kalita
8+
9+
------------------------------------ HELP ----------------------------------------
10+
FLAGS:
11+
-r X: Specify the register bit size where X is the specified size. 0 < X <= 16.
12+
If Register flag is not used when executing the program. The option to specify register will
13+
show during runtime.
14+
15+
-h: Use help.
16+
17+
DEFINITION OF STEPS:
18+
Initialization: Initial Value after loading up Multiplier and Multiplicand.
19+
A <- A + M: Values of Register A & M are added and put back into A register.
20+
A <- A - M: Values of Register M subtracted from A and put into A register.
21+
ASR: Arithmetic Shift Right. The MSB is retained while all other bits are shifted right starting from A to Q-1.
22+
23+
ALGORITHM:
24+
Action is determined by the Bits stored in 0th bit of Q and -1th bit of Q a.k.a Q-1. Here's the table for the actions -
25+
26+
Q Q-1 Action
27+
--------------------------------
28+
0 0 ASR
29+
0 1 A <- A + M then ASR
30+
1 0 A <- A - M then ASR
31+
1 1 ASR
32+
--------------------------------
33+
This Algorithm is repeated as many times as there are Bits in the Registers.
34+
E.g. If Register size if 4, the Algorithm is repeated 4 times.
35+
36+
";
37+
38+
pub fn initialize_size(args: Vec<String>) -> usize {
39+
let size: usize;
40+
if args.contains(&H_FLAG.to_string()) {
41+
if args.contains(&R_FLAG.to_string()) {
42+
println!("Note: Cannot run program while in Help mode\n");
43+
}
44+
println!("{}", HELP);
45+
exit(0);
46+
}
47+
if args.contains(&R_FLAG.to_string()) {
48+
let pos = args.iter().position(|x| x == R_FLAG).unwrap() + 1;
49+
let n = args
50+
.get(pos)
51+
.expect("Register Flag used but size not specified\nUse -h for help.");
52+
size = n
53+
.parse::<usize>()
54+
.expect("Invalid Register Size specified. Use -h for help.\n");
55+
} else {
56+
size = crate::booth::get_size();
57+
}
58+
if size == 0 {
59+
println!("Register Size specified cannot be 0. Use -h for help.");
60+
exit(1);
61+
}
62+
if size > 16 {
63+
println!("Register Size specified exceeds maximum limit of 16. Use -h for help.");
64+
exit(2);
65+
}
66+
println!(
67+
"Input Range: {} to {}",
68+
-2_i32.pow(size as u32 - 1),
69+
(2_i32.pow(size as u32 - 1) - 1)
70+
);
71+
println!(
72+
"Output Range: {} to {}\n",
73+
-2_i32.pow(size as u32 * 2 - 1),
74+
(2_i32.pow(size as u32 * 2 - 1) - 1)
75+
);
76+
size
77+
}

src/booth/io.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use std::io;
2+
3+
pub fn int_input<T: std::str::FromStr>() -> T
4+
where
5+
<T as std::str::FromStr>::Err: std::fmt::Debug,
6+
{
7+
let mut buff: String = String::new();
8+
io::stdin().read_line(&mut buff).expect("Input Error");
9+
let num: T = buff.trim().parse::<T>().expect("Invalid Input");
10+
num
11+
}
12+
13+
pub fn print_header() {
14+
println!("A \tQ \tQ-1 \tM");
15+
}
16+
17+
pub fn print_step(size: usize, mut a: i32, mut q: i32, qc: u32, mut m: i32, step: &str, end: bool) {
18+
a = a & (2_i32.pow(size as u32) - 1);
19+
q = q & (2_i32.pow(size as u32) - 1);
20+
m = m & (2_i32.pow(size as u32) - 1);
21+
println!(
22+
"{:0size$b} \t{:0size$b} \t{:01b} \t{:0size$b} \t{}",
23+
a, q, qc, m, step
24+
);
25+
if end {
26+
println!("{}", "-".repeat(size * 6 + 28));
27+
}
28+
}
29+
30+
pub fn print_result(mut res: i32, mut size: usize) {
31+
size *= 2;
32+
println!("\tResult(decimal): \t{}", res);
33+
res = res & (2_i32.pow(size as u32) - 1);
34+
println!("\tResult(binary): \t{:0size$b}", res);
35+
}

src/booth/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pub mod console;
2+
pub mod io;
3+
pub mod ops;
4+
pub mod util;
5+
6+
pub use console::*;
7+
pub use io::*;
8+
pub use ops::*;
9+
pub use util::*;

src/booth/ops.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use crate::booth;
2+
3+
pub fn asr(a: &mut i32, q: &mut i32, qc: &mut u32, size: usize) {
4+
*qc = *q as u32 & 1_u32;
5+
let temp: i32 = *a & 1;
6+
*q = ((*q >> 1) & (2_i32.pow(size as u32 - 1) - 1)) | (temp << (size - 1));
7+
*a = *a >> 1;
8+
}
9+
10+
pub fn booth_algorithm(a: &mut i32, q: &mut i32, qc: &mut u32, m: &mut i32, size: usize) {
11+
booth::print_header();
12+
booth::print_step(size, *a, *q, *qc, *m, "Initialization", true);
13+
14+
for _ in 0..size {
15+
let lsb: i32 = *q & 1;
16+
if lsb == 0 && *qc == 1 {
17+
*a += *m;
18+
booth::print_step(size, *a, *q, *qc, *m, "A <- A + M", false);
19+
} else if lsb == 1 && *qc == 0 {
20+
*a -= *m;
21+
booth::print_step(size, *a, *q, *qc, *m, "A <- A - M", false);
22+
}
23+
asr(a, q, qc, size);
24+
booth::print_step(size, *a, *q, *qc, *m, "ASR", true);
25+
}
26+
}

src/booth/util.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use std::io::{self, Write};
2+
3+
use crate::booth;
4+
5+
pub fn get_size() -> usize {
6+
print!("Enter the size of Registers(MAX 16): ");
7+
io::stdout().flush().unwrap();
8+
let size: usize = booth::int_input::<usize>();
9+
size
10+
}
11+
12+
pub fn initialize_a_q_m() -> (i32, i32, i32, u32) {
13+
let a: i32 = 0;
14+
let q: i32;
15+
let m: i32;
16+
let qc: u32 = 0;
17+
print!("Enter the Multiplicand(M): ");
18+
io::stdout().flush().unwrap();
19+
m = booth::int_input::<i32>();
20+
print!("Enter the Multiplier(Q): ");
21+
io::stdout().flush().unwrap();
22+
q = booth::int_input::<i32>();
23+
(a, q, m, qc)
24+
}
25+
26+
pub fn get_result(a: i32, q: i32, size: usize) -> i32 {
27+
let size: u32 = size as u32;
28+
let res: i32 = (a << size) | (q & (2_i32.pow(size as u32) - 1));
29+
res
30+
}

0 commit comments

Comments
 (0)