Compare commits
12 Commits
Author | SHA1 | Date |
---|---|---|
Rhinemann | 4c994a8fef | |
Rhinemann | aef2dc3760 | |
Rhinemann | 52065cbc37 | |
Rhinemann | ed4a9f08cd | |
Rhinemann | f522eab9bf | |
Rhinemann | ca91c2ea56 | |
Rhinemann | 7ab69ecbe8 | |
Rhinemann | 1e505683cb | |
Rhinemann | 289b87a556 | |
Rhinemann | 81f190dc60 | |
Rhinemann | 75670b9de9 | |
Rhinemann | 31143cac1d |
|
@ -0,0 +1,21 @@
|
|||
[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.dev.package."*"] # +
|
||||
opt-level = "z" # Optimize library for size
|
||||
|
||||
[profile.release]
|
||||
#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"
|
||||
tabled = "0.14.0"
|
520
README.md
520
README.md
|
@ -1,520 +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.
|
||||
|
||||
# English
|
||||
|
||||
## Requirements
|
||||
The user must have installed:
|
||||
|
||||
- python 3 (for the calculator itself);
|
||||
|
||||
## Installation
|
||||
|
||||
### Cloning the repository
|
||||
To install the experimental version of the calculator just clone the repository locally:
|
||||
```
|
||||
git clone -b master http://139.162.162.130:3000/Rhinemann/binaryCalculatorPrototype.git
|
||||
```
|
||||
|
||||
### Stable packages
|
||||
To install a stable release of the calculator download the archive from [releases](http://139.162.162.130:3000/Rhinemann/binaryCalculatorPrototype/releases) page and decompress it in a directory of your choice.
|
||||
|
||||
## User instructions
|
||||
Start the calculator using the following command:
|
||||
```
|
||||
python3 main.py
|
||||
```
|
||||
|
||||
After that you must input the binary number as your first and second operands, as such:
|
||||
```
|
||||
Enter first operand: 110101
|
||||
Enter second operand: 110
|
||||
```
|
||||
|
||||
Note that you can't input any digit other than 0 or 1 into the operands:
|
||||
```
|
||||
Enter first operand: 234123
|
||||
[ERROR] The first operand may contain only 1-s and 0-s!
|
||||
Enter first operand: 12314
|
||||
[ERROR] The first operand may contain only 1-s and 0-s!
|
||||
Enter first operand: 1234123
|
||||
[ERROR] The first operand may contain only 1-s and 0-s!
|
||||
```
|
||||
|
||||
After inputting the operands properly, you will be presented with such prompt:
|
||||
```
|
||||
Choose the operation:
|
||||
[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit
|
||||
(110101 000110) >
|
||||
```
|
||||
|
||||
`(110101 000110)` are the operands you have input.
|
||||
|
||||
You may now choose the operations performed on the operands as such:
|
||||
```
|
||||
Choose the operation:
|
||||
[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit
|
||||
(110101 000110) > a
|
||||
|
||||
Sum: 111011
|
||||
Carry: 0
|
||||
|
||||
Choose the operation:
|
||||
[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit
|
||||
(110101 000110) > s
|
||||
|
||||
Subtraction: 101111
|
||||
Carry: 1
|
||||
|
||||
Choose the operation:
|
||||
[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit
|
||||
(110101 000110) > m
|
||||
|
||||
Choose method to use (1-4):
|
||||
(110101 000110) m > 1
|
||||
|
||||
Multiplication (method 1):
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| iter | RG1 | RG2 | RG3 | CT | MicroOperations |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 0 | 000000 | 110101 | 000110 | 110 | - |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 1 | 000110 | 110101 | 000110 | 110 | RG1 := RG1 + RG3 |
|
||||
| 1 | 000011 | 011010 | 000110 | 101 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 2 | 000001 | 101101 | 000110 | 100 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 3 | 000111 | 101101 | 000110 | 100 | RG1 := RG1 + RG3 |
|
||||
| 3 | 000011 | 110110 | 000110 | 011 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 4 | 000001 | 111011 | 000110 | 010 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 5 | 000111 | 111011 | 000110 | 010 | RG1 := RG1 + RG3 |
|
||||
| 5 | 000011 | 111101 | 000110 | 001 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 6 | 001001 | 111101 | 000110 | 001 | RG1 := RG1 + RG3 |
|
||||
| 6 | 000100 | 111110 | 000110 | 000 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
Result: 000100111110
|
||||
|
||||
Choose the operation:
|
||||
[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit
|
||||
(110101 000110) > d
|
||||
|
||||
Choose method to use (1-2):
|
||||
(110101 000110) d > 1
|
||||
|
||||
Division (method 1):
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| iter | RG3 | RG2 | RG1 | MicroOperations |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 0 | 1111111 | 00110101 | 00000110 | - |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 1 | 1111111 | 00101111 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 1 | 1111111 | 01011110 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 2 | 1111111 | 01011000 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 2 | 1111111 | 10110000 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 3 | 1111111 | 10110110 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 3 | 1111110 | 01101100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 4 | 1111110 | 01100110 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 4 | 1111101 | 11001100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 5 | 1111101 | 11010010 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 5 | 1111010 | 10100100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 6 | 1111010 | 10101010 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 6 | 1110100 | 01010100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 7 | 1110100 | 01001110 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 7 | 1101001 | 10011100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 8 | 1101001 | 10100010 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 8 | 1010010 | 01000100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 9 | 1010010 | 00111110 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 9 | 0100101 | 01111100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
Result: 100101
|
||||
```
|
||||
|
||||
The results of the operations will be displayed, and you will get prompted for the next operation to perform.
|
||||
|
||||
**Note** the results of previous operations don't impact the operands, therefore you can't plug your previous results into the calculator without restarting the program!
|
||||
|
||||
Also, as a quality of life feature, you can chain multiple operations in one prompt as such:
|
||||
```
|
||||
Choose the operation:
|
||||
[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit
|
||||
(110101 000110) > asm1d1
|
||||
|
||||
Sum: 111011
|
||||
Carry: 0
|
||||
|
||||
Subtraction: 101111
|
||||
Carry: 1
|
||||
|
||||
Multiplication (method 1):
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| iter | RG1 | RG2 | RG3 | CT | MicroOperations |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 0 | 000000 | 110101 | 000110 | 110 | - |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 1 | 000110 | 110101 | 000110 | 110 | RG1 := RG1 + RG3 |
|
||||
| 1 | 000011 | 011010 | 000110 | 101 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 2 | 000001 | 101101 | 000110 | 100 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 3 | 000111 | 101101 | 000110 | 100 | RG1 := RG1 + RG3 |
|
||||
| 3 | 000011 | 110110 | 000110 | 011 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 4 | 000001 | 111011 | 000110 | 010 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 5 | 000111 | 111011 | 000110 | 010 | RG1 := RG1 + RG3 |
|
||||
| 5 | 000011 | 111101 | 000110 | 001 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 6 | 001001 | 111101 | 000110 | 001 | RG1 := RG1 + RG3 |
|
||||
| 6 | 000100 | 111110 | 000110 | 000 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
Result: 000100111110
|
||||
|
||||
Division (method 1):
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| iter | RG3 | RG2 | RG1 | MicroOperations |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 0 | 1111111 | 00110101 | 00000110 | - |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 1 | 1111111 | 00101111 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 1 | 1111111 | 01011110 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 2 | 1111111 | 01011000 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 2 | 1111111 | 10110000 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 3 | 1111111 | 10110110 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 3 | 1111110 | 01101100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 4 | 1111110 | 01100110 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 4 | 1111101 | 11001100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 5 | 1111101 | 11010010 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 5 | 1111010 | 10100100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 6 | 1111010 | 10101010 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 6 | 1110100 | 01010100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 7 | 1110100 | 01001110 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 7 | 1101001 | 10011100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 8 | 1101001 | 10100010 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 8 | 1010010 | 01000100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 9 | 1010010 | 00111110 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 9 | 0100101 | 01111100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
Result: 100101
|
||||
```
|
||||
|
||||
So that multiple operations are performed on the same operands without the need for multiple prompts.
|
||||
|
||||
# Українська
|
||||
|
||||
## Вимоги
|
||||
Користувач мусить мати:
|
||||
|
||||
- python 3 (для роботи калькулятора);
|
||||
|
||||
## Завантаження
|
||||
|
||||
### Клонування репозиторію
|
||||
Щоб встановити експериментальну версію калькулятора пропишіть цю команду, щоб клонувати репозиторій:
|
||||
```
|
||||
git clone -b master http://139.162.162.130:3000/Rhinemann/binaryCalculatorPrototype.git
|
||||
```
|
||||
|
||||
### Стабільні версії
|
||||
Щоб встановити стабільний реліз калькулятора завантажте архів зі сторінки [релізів](http://139.162.162.130:3000/Rhinemann/binaryCalculatorPrototype/releases) та розархівуйте в обраній директорії.
|
||||
|
||||
## Інструкція користувачам
|
||||
Калькулятор запускається цією командою:
|
||||
```
|
||||
python3 main.py
|
||||
```
|
||||
|
||||
Після цього користувач має ввести два операнди у двійковій системі, наприклад:
|
||||
```
|
||||
Enter first operand: 110101
|
||||
Enter second operand: 110
|
||||
```
|
||||
|
||||
Варто зауважити, що не можна ввести жодну цифру крім 0 чи 1 у значення операндів:
|
||||
```
|
||||
Enter first operand: 234123
|
||||
[ERROR] The first operand may contain only 1-s and 0-s!
|
||||
Enter first operand: 12314
|
||||
[ERROR] The first operand may contain only 1-s and 0-s!
|
||||
Enter first operand: 1234123
|
||||
[ERROR] The first operand may contain only 1-s and 0-s!
|
||||
```
|
||||
|
||||
Після коректного введення операндів користувач побачить такий запит:
|
||||
```
|
||||
Choose the operation:
|
||||
[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit
|
||||
(110101 000110) >
|
||||
```
|
||||
|
||||
`(110101 000110)` - це операнди введені користувачем.
|
||||
|
||||
Користувач тепер може обрати операції що виконуватимуться:
|
||||
```
|
||||
Choose the operation:
|
||||
[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit
|
||||
(110101 000110) > a
|
||||
|
||||
Sum: 111011
|
||||
Carry: 0
|
||||
|
||||
Choose the operation:
|
||||
[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit
|
||||
(110101 000110) > s
|
||||
|
||||
Subtraction: 101111
|
||||
Carry: 1
|
||||
|
||||
Choose the operation:
|
||||
[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit
|
||||
(110101 000110) > m
|
||||
|
||||
Choose method to use (1-4):
|
||||
(110101 000110) m > 1
|
||||
|
||||
Multiplication (method 1):
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| iter | RG1 | RG2 | RG3 | CT | MicroOperations |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 0 | 000000 | 110101 | 000110 | 110 | - |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 1 | 000110 | 110101 | 000110 | 110 | RG1 := RG1 + RG3 |
|
||||
| 1 | 000011 | 011010 | 000110 | 101 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 2 | 000001 | 101101 | 000110 | 100 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 3 | 000111 | 101101 | 000110 | 100 | RG1 := RG1 + RG3 |
|
||||
| 3 | 000011 | 110110 | 000110 | 011 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 4 | 000001 | 111011 | 000110 | 010 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 5 | 000111 | 111011 | 000110 | 010 | RG1 := RG1 + RG3 |
|
||||
| 5 | 000011 | 111101 | 000110 | 001 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 6 | 001001 | 111101 | 000110 | 001 | RG1 := RG1 + RG3 |
|
||||
| 6 | 000100 | 111110 | 000110 | 000 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
Result: 000100111110
|
||||
|
||||
Choose the operation:
|
||||
[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit
|
||||
(110101 000110) > d
|
||||
|
||||
Choose method to use (1-2):
|
||||
(110101 000110) d > 1
|
||||
|
||||
Division (method 1):
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| iter | RG3 | RG2 | RG1 | MicroOperations |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 0 | 1111111 | 00110101 | 00000110 | - |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 1 | 1111111 | 00101111 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 1 | 1111111 | 01011110 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 2 | 1111111 | 01011000 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 2 | 1111111 | 10110000 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 3 | 1111111 | 10110110 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 3 | 1111110 | 01101100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 4 | 1111110 | 01100110 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 4 | 1111101 | 11001100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 5 | 1111101 | 11010010 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 5 | 1111010 | 10100100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 6 | 1111010 | 10101010 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 6 | 1110100 | 01010100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 7 | 1110100 | 01001110 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 7 | 1101001 | 10011100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 8 | 1101001 | 10100010 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 8 | 1010010 | 01000100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 9 | 1010010 | 00111110 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 9 | 0100101 | 01111100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
Result: 100101
|
||||
```
|
||||
|
||||
Результати обчислень будуть виведені, а користувач отримає повторний запит операції.
|
||||
|
||||
**Увага** результати обчислень не змінюють операнди, тому їх неможливо використовувати у майбутніх обчисленнях без перезапуску програми!
|
||||
|
||||
Також, для зручності користувач може об'єднати декілька операцій у один запис:
|
||||
```
|
||||
Choose the operation:
|
||||
[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [q]uit
|
||||
(110101 000110) > asm1d1
|
||||
|
||||
Sum: 111011
|
||||
Carry: 0
|
||||
|
||||
Subtraction: 101111
|
||||
Carry: 1
|
||||
|
||||
Multiplication (method 1):
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| iter | RG1 | RG2 | RG3 | CT | MicroOperations |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 0 | 000000 | 110101 | 000110 | 110 | - |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 1 | 000110 | 110101 | 000110 | 110 | RG1 := RG1 + RG3 |
|
||||
| 1 | 000011 | 011010 | 000110 | 101 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 2 | 000001 | 101101 | 000110 | 100 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 3 | 000111 | 101101 | 000110 | 100 | RG1 := RG1 + RG3 |
|
||||
| 3 | 000011 | 110110 | 000110 | 011 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 4 | 000001 | 111011 | 000110 | 010 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 5 | 000111 | 111011 | 000110 | 010 | RG1 := RG1 + RG3 |
|
||||
| 5 | 000011 | 111101 | 000110 | 001 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
| 6 | 001001 | 111101 | 000110 | 001 | RG1 := RG1 + RG3 |
|
||||
| 6 | 000100 | 111110 | 000110 | 000 | RG2 := RG1[1].r(RG2) |
|
||||
| | | | | | RG1 := 0.r(RG1) |
|
||||
| | | | | | CT := CT - 1 |
|
||||
+------+--------+--------+--------+-----+----------------------+
|
||||
Result: 000100111110
|
||||
|
||||
Division (method 1):
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| iter | RG3 | RG2 | RG1 | MicroOperations |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 0 | 1111111 | 00110101 | 00000110 | - |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 1 | 1111111 | 00101111 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 1 | 1111111 | 01011110 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 2 | 1111111 | 01011000 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 2 | 1111111 | 10110000 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 3 | 1111111 | 10110110 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 3 | 1111110 | 01101100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 4 | 1111110 | 01100110 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 4 | 1111101 | 11001100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 5 | 1111101 | 11010010 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 5 | 1111010 | 10100100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 6 | 1111010 | 10101010 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 6 | 1110100 | 01010100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 7 | 1110100 | 01001110 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 7 | 1101001 | 10011100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 8 | 1101001 | 10100010 | 00000110 | RG2 := RG2 + RG1 |
|
||||
| 8 | 1010010 | 01000100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
| 9 | 1010010 | 00111110 | 00000110 | RG2 := RG2 - RG1 |
|
||||
| 9 | 0100101 | 01111100 | 00000110 | RG3 := l(RG3).!RG2[8] |
|
||||
| | | | | RG2 := l(RG2).0 |
|
||||
+------+---------+----------+----------+-----------------------+
|
||||
Result: 100101
|
||||
```
|
||||
|
||||
Таким чином обчислення послідовно над операндами без потреби у декількох запитах.
|
551
bitutilities.py
551
bitutilities.py
|
@ -1,551 +0,0 @@
|
|||
from collections import deque
|
||||
|
||||
from typing_extensions import Self
|
||||
from lib.prettytable import PrettyTable
|
||||
|
||||
|
||||
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: deque[bool]):
|
||||
self.memory: deque[bool] = memory
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "".join([str(int(value)) for value in self.memory])
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "".join([str(int(value)) for value in self.memory])
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.memory)
|
||||
|
||||
def adjusted_by_size(self, resulting_size: int) -> Self:
|
||||
"""
|
||||
Adjusts a register to a given size.
|
||||
|
||||
:param int resulting_size: The size of the resulting register.
|
||||
|
||||
:return: A register of a specified size.
|
||||
:rtype: BasicRegister
|
||||
"""
|
||||
current_memory_size: int = len(self.memory)
|
||||
return BasicRegister(
|
||||
deque([False] * max(resulting_size - current_memory_size, 0) + list(self.memory)[-resulting_size:])
|
||||
)
|
||||
|
||||
def negate(self):
|
||||
"""
|
||||
Performs logical negation on the register.
|
||||
"""
|
||||
self.memory = deque([not value for value in self.memory])
|
||||
|
||||
def left_shift(self, shift_in_value: bool = False, bits_shifted: int = 1) -> deque[bool]:
|
||||
"""
|
||||
Shifts the register to the left by a specified number of steps.
|
||||
|
||||
:param bool shift_in_value: The value that shifts inside the freed space.
|
||||
:param int bits_shifted: The number of bits by which the register is shifted.
|
||||
|
||||
:return: The bits shifted outside the register.
|
||||
:rtype: deque[bool]
|
||||
"""
|
||||
self.memory.extend([shift_in_value] * bits_shifted)
|
||||
shifted_bits: deque[bool] = deque([self.memory.popleft() for _i in range(bits_shifted)])
|
||||
return shifted_bits
|
||||
|
||||
def right_shift(self, shift_in_value: bool = False, bits_shifted: int = 1) -> deque[bool]:
|
||||
"""
|
||||
Shifts the register to the right by a specified number of steps
|
||||
|
||||
:param bool shift_in_value: The value that shifts inside the freed space.
|
||||
:param int bits_shifted: The number of bits by which the register is shifted.
|
||||
|
||||
:return: The bits shifted outside the register.
|
||||
:rtype: deque[bool]
|
||||
"""
|
||||
self.memory.extendleft([shift_in_value] * bits_shifted)
|
||||
shifted_bits: deque[bool] = deque([self.memory.pop() for _i in range(bits_shifted)])
|
||||
return shifted_bits
|
||||
|
||||
|
||||
class Counter(BasicRegister):
|
||||
"""
|
||||
The Counter represents a hardware register specifically designed for countdowns.
|
||||
|
||||
:param int value: Initial numeric value this Counter holds.
|
||||
"""
|
||||
|
||||
def __init__(self, value: int):
|
||||
# memory: deque[bool] = deque([i == "1" for i in bin(value)[2:]])
|
||||
super().__init__(deque([i == "1" for i in bin(value)[2:]]))
|
||||
# self.memory: deque[bool] = deque([i == "1" for i in bin(value)[2:]])
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "".join([str(int(value)) for value in self.memory])
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "".join([str(int(value)) for value in self.memory])
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.memory)
|
||||
|
||||
def decrement(self):
|
||||
self.memory = binary_subtraction(self, BasicRegister(deque([False] * (len(self.memory) - 1) + [True]))).memory
|
||||
|
||||
def non_zero(self) -> bool:
|
||||
return any(self.memory)
|
||||
|
||||
|
||||
def negated(memory: deque[bool]) -> deque[bool]:
|
||||
"""
|
||||
Returns negated memory chunk.
|
||||
|
||||
:param deque[bool] memory: Memory chunk to be negated.
|
||||
|
||||
:return: Negated memory chunk.
|
||||
:rtype: deque[bool]
|
||||
"""
|
||||
return deque([not value for value in memory])
|
||||
|
||||
|
||||
def get_memory(variable_name: str) -> deque[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 deque([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 binary_sum_with_carry(first_term: BasicRegister, second_term: BasicRegister) -> tuple[BasicRegister, int]:
|
||||
"""
|
||||
Sums two registers' values and keeps the carry-out.
|
||||
|
||||
:param BasicRegister first_term: First register.
|
||||
:param BasicRegister second_term: Second register.
|
||||
|
||||
:return: Register containing the sum and the carry-out bit.
|
||||
:rtype: tuple[BasicRegister, int]
|
||||
"""
|
||||
result_term = BasicRegister(deque([False] * len(first_term)))
|
||||
|
||||
carry = False
|
||||
for i in range(len(first_term) - 1, -1, -1):
|
||||
current_bit_sum = first_term.memory[i] + second_term.memory[i] + carry
|
||||
carry = bool(current_bit_sum & 2)
|
||||
result_term.memory[i] = bool(current_bit_sum & 1)
|
||||
|
||||
return result_term, carry
|
||||
|
||||
|
||||
def binary_sum(first_term: BasicRegister, second_term: BasicRegister) -> BasicRegister:
|
||||
"""
|
||||
Sums two terms containing binary numbers.
|
||||
|
||||
:param BasicRegister first_term: First register to add.
|
||||
:param BasicRegister second_term: Second register to add.
|
||||
|
||||
:return: Register containing the sum.
|
||||
:rtype: BasicRegister
|
||||
"""
|
||||
return binary_sum_with_carry(first_term, second_term)[0]
|
||||
|
||||
|
||||
def binary_subtraction(minuend: BasicRegister, subtrahend: BasicRegister) -> BasicRegister:
|
||||
"""
|
||||
Subtracts the second term from the first in binary using ones' complement.
|
||||
|
||||
:param BasicRegister minuend: Register to subtract from.
|
||||
:param BasicRegister subtrahend: Register to subtract by.
|
||||
|
||||
:return: Register containing the difference.
|
||||
:rtype: BasicRegister
|
||||
"""
|
||||
subtrahend = BasicRegister(subtrahend.memory)
|
||||
subtrahend.negate()
|
||||
|
||||
difference: BasicRegister
|
||||
final_carry: bool
|
||||
difference, final_carry = binary_sum_with_carry(minuend, subtrahend)
|
||||
|
||||
if final_carry:
|
||||
return binary_sum(difference, BasicRegister(deque([False] * (len(difference) - 1) + [True])))
|
||||
else:
|
||||
difference.negate()
|
||||
return difference
|
||||
|
||||
|
||||
def binary_subtraction_second_complement(minuend: BasicRegister, subtrahend: BasicRegister) \
|
||||
-> tuple[BasicRegister, bool]:
|
||||
"""
|
||||
Subtracts the second term from the first in binary using seconds' complement.
|
||||
|
||||
:param BasicRegister minuend: Register to subtract from.
|
||||
:param BasicRegister subtrahend: Register to subtract by.
|
||||
|
||||
:return: Register containing the difference.
|
||||
:rtype: BasicRegister
|
||||
"""
|
||||
subtrahend = BasicRegister(subtrahend.memory)
|
||||
subtrahend.negate()
|
||||
|
||||
subtrahend = binary_sum(*align_registers(subtrahend, BasicRegister([True])))
|
||||
|
||||
difference: BasicRegister
|
||||
final_carry: bool
|
||||
difference, final_carry = binary_sum_with_carry(minuend, subtrahend)
|
||||
|
||||
return difference, final_carry
|
||||
|
||||
|
||||
def align_registers(*registers: BasicRegister) -> tuple[BasicRegister, ...]:
|
||||
"""
|
||||
Aligns registers by the length of the bigger one.
|
||||
|
||||
:param BasicRegister registers: Registers to align.
|
||||
|
||||
:return: Aligned registers.
|
||||
:rtype: tuple[BasicRegister, ...]
|
||||
"""
|
||||
required_size: int = max(map(len, registers))
|
||||
return tuple(reg.adjusted_by_size(required_size) for reg in registers)
|
||||
|
||||
|
||||
def format_device_state_table(table) -> str:
|
||||
pt = PrettyTable()
|
||||
pt.field_names = table[0]
|
||||
|
||||
for block in table[1:]:
|
||||
for line in block[:-1]:
|
||||
pt.add_row(line)
|
||||
pt.add_row(block[-1], divider=True)
|
||||
|
||||
return pt.get_string()
|
||||
|
||||
|
||||
def binary_multiplication_method_1(first_term: BasicRegister, second_term: BasicRegister) \
|
||||
-> tuple[BasicRegister, list[list[str]]]:
|
||||
"""
|
||||
Multiplies two terms containing binary numbers using first method.
|
||||
|
||||
:param BasicRegister first_term: First register to multiply.
|
||||
:param BasicRegister second_term: Second register to multiply.
|
||||
|
||||
:return: Register containing the product.
|
||||
:rtype: BasicRegister
|
||||
"""
|
||||
first_term, second_term = align_registers(first_term, second_term)
|
||||
n: int = len(first_term)
|
||||
|
||||
rg1 = BasicRegister(deque([False] * n))
|
||||
rg2 = BasicRegister(first_term.memory)
|
||||
rg3 = BasicRegister(second_term.memory)
|
||||
ct = Counter(n)
|
||||
|
||||
data_table = [["iter", "RG1", "RG2", "RG3", "CT", "MicroOperations"]]
|
||||
|
||||
i = 0
|
||||
data_table.append([])
|
||||
data_table[-1].append(list(map(str, [i, rg1, rg2, rg3, ct, "-"])))
|
||||
|
||||
while ct.non_zero():
|
||||
i += 1
|
||||
data_table.append([])
|
||||
|
||||
if rg2.memory[n-1]:
|
||||
rg1 = binary_sum(rg1, rg3)
|
||||
data_table[-1].append(list(map(str, [i, rg1, rg2, rg3, ct, "RG1 := RG1 + RG3"])))
|
||||
|
||||
rg2.right_shift(rg1.memory[n-1])
|
||||
rg1.right_shift()
|
||||
ct.decrement()
|
||||
|
||||
data_table[-1].append(list(map(str, [i, rg1, rg2, rg3, ct, "RG2 := RG1[1].r(RG2)\nRG1 := 0.r(RG1)\nCT := CT - 1"])))
|
||||
|
||||
return BasicRegister(rg1.memory + rg2.memory), data_table
|
||||
|
||||
|
||||
def binary_multiplication_method_2(first_term: BasicRegister, second_term: BasicRegister) \
|
||||
-> tuple[BasicRegister, list[list[str]]]:
|
||||
"""
|
||||
Multiplies two terms containing binary numbers using second method.
|
||||
|
||||
:param BasicRegister first_term: First register to multiply.
|
||||
:param BasicRegister second_term: Second register to multiply.
|
||||
|
||||
:return: Register containing the product.
|
||||
:rtype: BasicRegister
|
||||
"""
|
||||
first_term, second_term = align_registers(first_term, second_term)
|
||||
n: int = len(first_term)
|
||||
|
||||
rg1 = BasicRegister(deque([False] * (2*n)))
|
||||
rg2 = BasicRegister(first_term.memory)
|
||||
rg3 = BasicRegister(deque([False] * n + list(second_term.memory)))
|
||||
|
||||
i = 0
|
||||
data_table = [["iter", "RG1", "RG2", "RG3", "MicroOperations"], []]
|
||||
|
||||
data_table[-1].append(list(map(str, [i, rg1, rg2, rg3, "-"])))
|
||||
|
||||
while any(rg2.memory):
|
||||
i += 1
|
||||
data_table.append([])
|
||||
|
||||
if rg2.memory[n-1]:
|
||||
rg1 = binary_sum(rg1, rg3)
|
||||
data_table[-1].append(list(map(str, [i, rg1, rg2, rg3, "RG1 := RG1 + RG3"])))
|
||||
|
||||
rg2.right_shift()
|
||||
rg3.left_shift()
|
||||
|
||||
data_table[-1].append(list(map(str, [i, rg1, rg2, rg3, "RG2 := 0.r(RG2)\nRG3 := l(RG3).0"])))
|
||||
|
||||
return rg1, data_table
|
||||
|
||||
|
||||
def binary_multiplication_method_3(first_term: BasicRegister, second_term: BasicRegister) \
|
||||
-> tuple[BasicRegister, list[list[str]]]:
|
||||
"""
|
||||
Multiplies two terms containing binary numbers using third method.
|
||||
|
||||
:param BasicRegister first_term: First register to multiply.
|
||||
:param BasicRegister second_term: Second register to multiply.
|
||||
|
||||
:return: Register containing the product.
|
||||
:rtype: BasicRegister
|
||||
"""
|
||||
first_term, second_term = align_registers(first_term, second_term)
|
||||
n: int = len(first_term)
|
||||
|
||||
data_table = [["iter", "RG2", "RG1", "RG3", "CT", "MicroOperations"]]
|
||||
|
||||
rg1 = BasicRegister(deque([False] * n))
|
||||
rg2 = BasicRegister(first_term.memory + deque([False]))
|
||||
rg3 = BasicRegister(deque([False] * (n+1)) + second_term.memory)
|
||||
ct = Counter(n)
|
||||
|
||||
i = 0
|
||||
data_table.append([])
|
||||
data_table[-1].append(list(map(str, [i, rg2, rg1, rg3, ct, "-"])))
|
||||
|
||||
while ct.non_zero():
|
||||
i += 1
|
||||
data_table.append([])
|
||||
|
||||
if rg2.memory[0]:
|
||||
result: list[bool] = list(binary_sum(BasicRegister(rg2.memory + rg1.memory), rg3).memory)
|
||||
rg2 = BasicRegister(deque(result[:n+1]))
|
||||
rg1 = BasicRegister(deque(result[n+1:]))
|
||||
data_table[-1].append(list(map(str, [i, rg2, rg1, rg3, ct, "RG2.RG1 := RG2.RG1 + RG3"])))
|
||||
|
||||
rg2.left_shift(rg1.memory[0])
|
||||
rg1.left_shift()
|
||||
ct.decrement()
|
||||
|
||||
data_table[-1].append(list(map(str, [i, rg2, rg1, rg3, ct, "RG2.RG1 := l(RG2.RG1).0\nCT := CT - 1"])))
|
||||
|
||||
return BasicRegister(deque(list(rg2.memory + rg1.memory)[:-1])), data_table
|
||||
|
||||
|
||||
def binary_multiplication_method_4(first_term: BasicRegister, second_term: BasicRegister) \
|
||||
-> tuple[BasicRegister, list[list[str]]]:
|
||||
"""
|
||||
Multiplies two terms containing binary numbers using fourth method.
|
||||
|
||||
:param BasicRegister first_term: First register to multiply.
|
||||
:param BasicRegister second_term: Second register to multiply.
|
||||
|
||||
:return: Register containing the product.
|
||||
:rtype: BasicRegister
|
||||
"""
|
||||
first_term, second_term = align_registers(first_term, second_term)
|
||||
n: int = len(first_term)
|
||||
|
||||
rg1 = BasicRegister(deque([False] * (2*n+1)))
|
||||
rg2 = BasicRegister(first_term.memory)
|
||||
rg3 = BasicRegister(deque([False]) + second_term.memory + deque([False] * n))
|
||||
|
||||
data_table = [["iter", "RG1", "RG2", "RG3", "MicroOperations"]]
|
||||
|
||||
i = 0
|
||||
data_table.append([])
|
||||
data_table[-1].append(list(map(str, [i, rg1, rg2, rg3, "-"])))
|
||||
|
||||
while any(rg2.memory):
|
||||
i += 1
|
||||
data_table.append([])
|
||||
|
||||
if rg2.memory[0]:
|
||||
rg1 = binary_sum(rg1, rg3)
|
||||
data_table[-1].append(list(map(str, [i, rg1, rg2, rg3, "RG1 := RG1 + RG3"])))
|
||||
|
||||
rg2.left_shift()
|
||||
rg3.right_shift()
|
||||
|
||||
data_table[-1].append(list(map(str, [i, rg1, rg2, rg3, "RG2 := l(RG2).0\nRG3 := 0.r(RG3)"])))
|
||||
|
||||
return BasicRegister(deque(list(rg1.memory)[:-1])), data_table
|
||||
|
||||
def binary_division_method_1(first_term: BasicRegister, second_term: BasicRegister) \
|
||||
-> tuple[BasicRegister, list[list[str]]]:
|
||||
"""
|
||||
Divides first term by the second term containing binary numbers using first method.
|
||||
|
||||
:param: BasicRegister first_term: Register being divided.
|
||||
:param: BasicRegister second_term: Register being divided by.
|
||||
|
||||
:return: Register containing the division result.
|
||||
:rtype: BasicRegister
|
||||
"""
|
||||
|
||||
first_term, second_term = align_registers(first_term, second_term)
|
||||
n: int = len(first_term)
|
||||
|
||||
rg1 = BasicRegister(deque([False, False]) + second_term.memory)
|
||||
rg2 = BasicRegister(deque([False, False]) + first_term.memory)
|
||||
rg3 = BasicRegister(deque([True] * (n+1)))
|
||||
|
||||
data_table = [["iter", "RG3", "RG2", "RG1", "MicroOperations"]]
|
||||
i = 0
|
||||
|
||||
data_table.append([])
|
||||
data_table[-1].append(list(map(str, [i, rg3, rg2, rg1, "-"])))
|
||||
|
||||
while rg3.memory[0]:
|
||||
i += 1
|
||||
data_table.append([])
|
||||
|
||||
if rg2.memory[0]:
|
||||
rg2 = binary_sum(rg2, rg1)
|
||||
data_table[-1].append(list(map(str, [i, rg3, rg2, rg1, "RG2 := RG2 + RG1"])))
|
||||
else:
|
||||
rg2, _ = binary_subtraction_second_complement(rg2, rg1)
|
||||
data_table[-1].append(list(map(str, [i, rg3, rg2, rg1, "RG2 := RG2 - RG1"])))
|
||||
|
||||
rg3.left_shift(not rg2.memory[0])
|
||||
rg2.left_shift()
|
||||
data_table[-1].append(list(map(str, [i, rg3, rg2, rg1, f"RG3 := l(RG3).!RG2[{n+2}]\nRG2 := l(RG2).0"])))
|
||||
|
||||
return BasicRegister(deque(list(rg3.memory)[1:])), data_table
|
||||
|
||||
def binary_division_method_2(first_term: BasicRegister, second_term: BasicRegister) \
|
||||
-> tuple[BasicRegister, list[list[str]]]:
|
||||
"""
|
||||
Divides first term by the second term containing binary numbers using second method.
|
||||
|
||||
:param: BasicRegister first_term: Register being divided.
|
||||
:param: BasicRegister second_term: Register being divided by.
|
||||
|
||||
:return: Register containing the division result.
|
||||
:rtype: BasicRegister
|
||||
"""
|
||||
|
||||
first_term, second_term = align_registers(first_term, second_term)
|
||||
n: int = len(first_term)
|
||||
|
||||
rg1 = BasicRegister(deque([False]) + second_term.memory + deque([False]*n))
|
||||
rg2 = BasicRegister(deque([False]) + first_term.memory + deque([False]*n))
|
||||
rg3 = BasicRegister(deque([True] * (n+1)))
|
||||
|
||||
data_table = [["iter", "RG3", "RG2", "RG1", "MicroOperations"]]
|
||||
i = 0
|
||||
carry = False
|
||||
|
||||
data_table.append([])
|
||||
data_table[-1].append(list(map(str, [i, rg3, rg2, rg1, "-"])))
|
||||
|
||||
while rg3.memory[0]:
|
||||
i += 1
|
||||
data_table.append([])
|
||||
|
||||
if rg2.memory[0]:
|
||||
rg2, carry = binary_sum_with_carry(rg2, rg1)
|
||||
data_table[-1].append(list(map(str, [i, rg3, rg2, rg1, "RG2 := RG2 + RG1"])))
|
||||
else:
|
||||
rg2, carry = binary_subtraction_second_complement(rg2, rg1)
|
||||
data_table[-1].append(list(map(str, [i, rg3, rg2, rg1, "RG2 := RG2 - RG1"])))
|
||||
|
||||
rg3.left_shift(carry)
|
||||
rg1.right_shift()
|
||||
data_table[-1].append(list(map(str, [i, rg3, rg2, rg1, f"RG3 := l(RG3).SM[p]\nRG1 := 0.r(RG1)"])))
|
||||
|
||||
return BasicRegister(deque(list(rg3.memory)[1:])), data_table
|
||||
|
||||
def binary_square_root(first_term: BasicRegister) \
|
||||
-> tuple[BasicRegister, list[list[str]]]:
|
||||
"""
|
||||
Extracts the square root of first term.
|
||||
|
||||
:param: BasicRegister first_term: Register for square root extraction.
|
||||
|
||||
:return: Register containing the division result and the state table of a virtual
|
||||
device that extracted the square root of the given term.
|
||||
:rtype: tuple[BasicRegister, list[list[str]]]
|
||||
"""
|
||||
|
||||
n: int = len(first_term)
|
||||
i = 0
|
||||
|
||||
rga = BasicRegister(deque([False]*n))
|
||||
rgb = BasicRegister(deque([False]*(n+2)))
|
||||
rgc = BasicRegister(first_term.memory)
|
||||
ct = Counter(n)
|
||||
|
||||
data_table = [["iter", "RGA", "RGB", "RGC", "CT", "MicroOperations"]]
|
||||
|
||||
data_table.append([])
|
||||
data_table[-1].append(list(map(str, [i, rga, rgb, rgc, ct, "-"])))
|
||||
|
||||
# two initial shifts
|
||||
rgb.left_shift(rgc.memory[0])
|
||||
rgc.left_shift()
|
||||
data_table[-1].append(list(map(str, [i, rga, rgb, rgc, ct, "RGB := l(RGB).RGC[0]\nRGC := l(RGC).0"])))
|
||||
|
||||
rgb.left_shift(rgc.memory[0])
|
||||
rgc.left_shift()
|
||||
data_table[-1].append(list(map(str, [i, rga, rgb, rgc, ct, "RGB := l(RGB).RGC[0]\nRGC := l(RGC).0"])))
|
||||
|
||||
# initial inverted addition
|
||||
rgb = binary_sum(rgb, BasicRegister(negated(rga.memory) + deque([True, True])))
|
||||
data_table[-1].append(list(map(str, [i, rga, rgb, rgc, ct, "RGB := RGB + !(RGA).11"])))
|
||||
|
||||
while ct.non_zero():
|
||||
data_table.append([])
|
||||
i += 1
|
||||
|
||||
rga.left_shift(not rgb.memory[0])
|
||||
rgb.left_shift(rgc.memory[0])
|
||||
rgc.left_shift()
|
||||
|
||||
data_table[-1].append(list(map(str, [i, rga, rgb, rgc, ct, "RGA := l(RGA).!(RGB[0])\nRGB := l(RGB).RGC[0]\nRGC := l(RGC).0"])))
|
||||
|
||||
rgb.left_shift(rgc.memory[0])
|
||||
rgc.left_shift()
|
||||
|
||||
data_table[-1].append(list(map(str, [i, rga, rgb, rgc, ct, "RGB := l(RGB).RGC[0]\nRGC := l(RGC).0"])))
|
||||
|
||||
if rgb.memory[0]:
|
||||
rgb = binary_sum(rgb, BasicRegister(rga.memory + deque([True, True])))
|
||||
data_table[-1].append(list(map(str, [i, rga, rgb, rgc, ct, "RGB := RGB + RGA.11"])))
|
||||
else:
|
||||
rgb = binary_sum(rgb, BasicRegister(negated(rga.memory) + deque([True, True])))
|
||||
data_table[-1].append(list(map(str, [i, rga, rgb, rgc, ct, "RGB := RGB + !(RGA).11"])))
|
||||
|
||||
ct.decrement()
|
||||
data_table[-1].append(list(map(str, [i, rga, rgb, rgc, ct, "CT := CT - 1"])))
|
||||
|
||||
return rga, data_table
|
2560
lib/prettytable.py
2560
lib/prettytable.py
File diff suppressed because it is too large
Load Diff
|
@ -1 +0,0 @@
|
|||
pip
|
|
@ -1,27 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Jeff Quast <contact@jeffquast.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
Markus Kuhn -- 2007-05-26 (Unicode 5.0)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
for any purpose and without fee is hereby granted. The author
|
||||
disclaims all warranties with regard to this software.
|
|
@ -1,410 +0,0 @@
|
|||
Metadata-Version: 2.1
|
||||
Name: wcwidth
|
||||
Version: 0.2.13
|
||||
Summary: Measures the displayed width of unicode strings in a terminal
|
||||
Home-page: https://github.com/jquast/wcwidth
|
||||
Author: Jeff Quast
|
||||
Author-email: contact@jeffquast.com
|
||||
License: MIT
|
||||
Keywords: cjk,combining,console,eastasian,emoji,emulator,terminal,unicode,wcswidth,wcwidth,xterm
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Natural Language :: English
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Operating System :: POSIX
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Topic :: Software Development :: Libraries
|
||||
Classifier: Topic :: Software Development :: Localization
|
||||
Classifier: Topic :: Software Development :: Internationalization
|
||||
Classifier: Topic :: Terminals
|
||||
License-File: LICENSE
|
||||
Requires-Dist: backports.functools-lru-cache >=1.2.1 ; python_version < "3.2"
|
||||
|
||||
|pypi_downloads| |codecov| |license|
|
||||
|
||||
============
|
||||
Introduction
|
||||
============
|
||||
|
||||
This library is mainly for CLI programs that carefully produce output for
|
||||
Terminals, or make pretend to be an emulator.
|
||||
|
||||
**Problem Statement**: The printable length of *most* strings are equal to the
|
||||
number of cells they occupy on the screen ``1 character : 1 cell``. However,
|
||||
there are categories of characters that *occupy 2 cells* (full-wide), and
|
||||
others that *occupy 0* cells (zero-width).
|
||||
|
||||
**Solution**: POSIX.1-2001 and POSIX.1-2008 conforming systems provide
|
||||
`wcwidth(3)`_ and `wcswidth(3)`_ C functions of which this python module's
|
||||
functions precisely copy. *These functions return the number of cells a
|
||||
unicode string is expected to occupy.*
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
The stable version of this package is maintained on pypi, install using pip::
|
||||
|
||||
pip install wcwidth
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
**Problem**: given the following phrase (Japanese),
|
||||
|
||||
>>> text = u'コンニチハ'
|
||||
|
||||
Python **incorrectly** uses the *string length* of 5 codepoints rather than the
|
||||
*printable length* of 10 cells, so that when using the `rjust` function, the
|
||||
output length is wrong::
|
||||
|
||||
>>> print(len('コンニチハ'))
|
||||
5
|
||||
|
||||
>>> print('コンニチハ'.rjust(20, '_'))
|
||||
_______________コンニチハ
|
||||
|
||||
By defining our own "rjust" function that uses wcwidth, we can correct this::
|
||||
|
||||
>>> def wc_rjust(text, length, padding=' '):
|
||||
... from wcwidth import wcswidth
|
||||
... return padding * max(0, (length - wcswidth(text))) + text
|
||||
...
|
||||
|
||||
Our **Solution** uses wcswidth to determine the string length correctly::
|
||||
|
||||
>>> from wcwidth import wcswidth
|
||||
>>> print(wcswidth('コンニチハ'))
|
||||
10
|
||||
|
||||
>>> print(wc_rjust('コンニチハ', 20, '_'))
|
||||
__________コンニチハ
|
||||
|
||||
|
||||
Choosing a Version
|
||||
------------------
|
||||
|
||||
Export an environment variable, ``UNICODE_VERSION``. This should be done by
|
||||
*terminal emulators* or those developers experimenting with authoring one of
|
||||
their own, from shell::
|
||||
|
||||
$ export UNICODE_VERSION=13.0
|
||||
|
||||
If unspecified, the latest version is used. If your Terminal Emulator does not
|
||||
export this variable, you can use the `jquast/ucs-detect`_ utility to
|
||||
automatically detect and export it to your shell.
|
||||
|
||||
wcwidth, wcswidth
|
||||
-----------------
|
||||
Use function ``wcwidth()`` to determine the length of a *single unicode
|
||||
character*, and ``wcswidth()`` to determine the length of many, a *string
|
||||
of unicode characters*.
|
||||
|
||||
Briefly, return values of function ``wcwidth()`` are:
|
||||
|
||||
``-1``
|
||||
Indeterminate (not printable).
|
||||
|
||||
``0``
|
||||
Does not advance the cursor, such as NULL or Combining.
|
||||
|
||||
``2``
|
||||
Characters of category East Asian Wide (W) or East Asian
|
||||
Full-width (F) which are displayed using two terminal cells.
|
||||
|
||||
``1``
|
||||
All others.
|
||||
|
||||
Function ``wcswidth()`` simply returns the sum of all values for each character
|
||||
along a string, or ``-1`` when it occurs anywhere along a string.
|
||||
|
||||
Full API Documentation at https://wcwidth.readthedocs.org
|
||||
|
||||
==========
|
||||
Developing
|
||||
==========
|
||||
|
||||
Install wcwidth in editable mode::
|
||||
|
||||
pip install -e .
|
||||
|
||||
Execute unit tests using tox_::
|
||||
|
||||
tox -e py27,py35,py36,py37,py38,py39,py310,py311,py312
|
||||
|
||||
Updating Unicode Version
|
||||
------------------------
|
||||
|
||||
Regenerate python code tables from latest Unicode Specification data files::
|
||||
|
||||
tox -e update
|
||||
|
||||
The script is located at ``bin/update-tables.py``, requires Python 3.9 or
|
||||
later. It is recommended but not necessary to run this script with the newest
|
||||
Python, because the newest Python has the latest ``unicodedata`` for generating
|
||||
comments.
|
||||
|
||||
Building Documentation
|
||||
----------------------
|
||||
|
||||
This project is using `sphinx`_ 4.5 to build documentation::
|
||||
|
||||
tox -e sphinx
|
||||
|
||||
The output will be in ``docs/_build/html/``.
|
||||
|
||||
Updating Requirements
|
||||
---------------------
|
||||
|
||||
This project is using `pip-tools`_ to manage requirements.
|
||||
|
||||
To upgrade requirements for updating unicode version, run::
|
||||
|
||||
tox -e update_requirements_update
|
||||
|
||||
To upgrade requirements for testing, run::
|
||||
|
||||
tox -e update_requirements37,update_requirements39
|
||||
|
||||
To upgrade requirements for building documentation, run::
|
||||
|
||||
tox -e update_requirements_docs
|
||||
|
||||
Utilities
|
||||
---------
|
||||
|
||||
Supplementary tools for browsing and testing terminals for wide unicode
|
||||
characters are found in the `bin/`_ of this project's source code. Just ensure
|
||||
to first ``pip install -r requirements-develop.txt`` from this projects main
|
||||
folder. For example, an interactive browser for testing::
|
||||
|
||||
python ./bin/wcwidth-browser.py
|
||||
|
||||
====
|
||||
Uses
|
||||
====
|
||||
|
||||
This library is used in:
|
||||
|
||||
- `jquast/blessed`_: a thin, practical wrapper around terminal capabilities in
|
||||
Python.
|
||||
|
||||
- `prompt-toolkit/python-prompt-toolkit`_: a Library for building powerful
|
||||
interactive command lines in Python.
|
||||
|
||||
- `dbcli/pgcli`_: Postgres CLI with autocompletion and syntax highlighting.
|
||||
|
||||
- `thomasballinger/curtsies`_: a Curses-like terminal wrapper with a display
|
||||
based on compositing 2d arrays of text.
|
||||
|
||||
- `selectel/pyte`_: Simple VTXXX-compatible linux terminal emulator.
|
||||
|
||||
- `astanin/python-tabulate`_: Pretty-print tabular data in Python, a library
|
||||
and a command-line utility.
|
||||
|
||||
- `rspeer/python-ftfy`_: Fixes mojibake and other glitches in Unicode
|
||||
text.
|
||||
|
||||
- `nbedos/termtosvg`_: Terminal recorder that renders sessions as SVG
|
||||
animations.
|
||||
|
||||
- `peterbrittain/asciimatics`_: Package to help people create full-screen text
|
||||
UIs.
|
||||
|
||||
- `python-cmd2/cmd2`_: A tool for building interactive command line apps
|
||||
|
||||
- `stratis-storage/stratis-cli`_: CLI for the Stratis project
|
||||
|
||||
- `ihabunek/toot`_: A Mastodon CLI/TUI client
|
||||
|
||||
- `saulpw/visidata`_: Terminal spreadsheet multitool for discovering and
|
||||
arranging data
|
||||
|
||||
===============
|
||||
Other Languages
|
||||
===============
|
||||
|
||||
- `timoxley/wcwidth`_: JavaScript
|
||||
- `janlelis/unicode-display_width`_: Ruby
|
||||
- `alecrabbit/php-wcwidth`_: PHP
|
||||
- `Text::CharWidth`_: Perl
|
||||
- `bluebear94/Terminal-WCWidth`_: Perl 6
|
||||
- `mattn/go-runewidth`_: Go
|
||||
- `grepsuzette/wcwidth`_: Haxe
|
||||
- `aperezdc/lua-wcwidth`_: Lua
|
||||
- `joachimschmidt557/zig-wcwidth`_: Zig
|
||||
- `fumiyas/wcwidth-cjk`_: `LD_PRELOAD` override
|
||||
- `joshuarubin/wcwidth9`_: Unicode version 9 in C
|
||||
|
||||
=======
|
||||
History
|
||||
=======
|
||||
|
||||
0.2.13 *2024-01-06*
|
||||
* **Bugfix** zero-width support for Hangul Jamo (Korean)
|
||||
|
||||
0.2.12 *2023-11-21*
|
||||
* re-release to remove .pyi file misplaced in wheel files `Issue #101`_.
|
||||
|
||||
0.2.11 *2023-11-20*
|
||||
* Include tests files in the source distribution (`PR #98`_, `PR #100`_).
|
||||
|
||||
0.2.10 *2023-11-13*
|
||||
* **Bugfix** accounting of some kinds of emoji sequences using U+FE0F
|
||||
Variation Selector 16 (`PR #97`_).
|
||||
* **Updated** `Specification <Specification_from_pypi_>`_.
|
||||
|
||||
0.2.9 *2023-10-30*
|
||||
* **Bugfix** zero-width characters used in Emoji ZWJ sequences, Balinese,
|
||||
Jamo, Devanagari, Tamil, Kannada and others (`PR #91`_).
|
||||
* **Updated** to include `Specification <Specification_from_pypi_>`_ of
|
||||
character measurements.
|
||||
|
||||
0.2.8 *2023-09-30*
|
||||
* Include requirements files in the source distribution (`PR #82`_).
|
||||
|
||||
0.2.7 *2023-09-28*
|
||||
* **Updated** tables to include Unicode Specification 15.1.0.
|
||||
* Include ``bin``, ``docs``, and ``tox.ini`` in the source distribution
|
||||
|
||||
0.2.6 *2023-01-14*
|
||||
* **Updated** tables to include Unicode Specification 14.0.0 and 15.0.0.
|
||||
* **Changed** developer tools to use pip-compile, and to use jinja2 templates
|
||||
for code generation in `bin/update-tables.py` to prepare for possible
|
||||
compiler optimization release.
|
||||
|
||||
0.2.1 .. 0.2.5 *2020-06-23*
|
||||
* **Repository** changes to update tests and packaging issues, and
|
||||
begin tagging repository with matching release versions.
|
||||
|
||||
0.2.0 *2020-06-01*
|
||||
* **Enhancement**: Unicode version may be selected by exporting the
|
||||
Environment variable ``UNICODE_VERSION``, such as ``13.0``, or ``6.3.0``.
|
||||
See the `jquast/ucs-detect`_ CLI utility for automatic detection.
|
||||
* **Enhancement**:
|
||||
API Documentation is published to readthedocs.org.
|
||||
* **Updated** tables for *all* Unicode Specifications with files
|
||||
published in a programmatically consumable format, versions 4.1.0
|
||||
through 13.0
|
||||
|
||||
0.1.9 *2020-03-22*
|
||||
* **Performance** optimization by `Avram Lubkin`_, `PR #35`_.
|
||||
* **Updated** tables to Unicode Specification 13.0.0.
|
||||
|
||||
0.1.8 *2020-01-01*
|
||||
* **Updated** tables to Unicode Specification 12.0.0. (`PR #30`_).
|
||||
|
||||
0.1.7 *2016-07-01*
|
||||
* **Updated** tables to Unicode Specification 9.0.0. (`PR #18`_).
|
||||
|
||||
0.1.6 *2016-01-08 Production/Stable*
|
||||
* ``LICENSE`` file now included with distribution.
|
||||
|
||||
0.1.5 *2015-09-13 Alpha*
|
||||
* **Bugfix**:
|
||||
Resolution of "combining_ character width" issue, most especially
|
||||
those that previously returned -1 now often (correctly) return 0.
|
||||
resolved by `Philip Craig`_ via `PR #11`_.
|
||||
* **Deprecated**:
|
||||
The module path ``wcwidth.table_comb`` is no longer available,
|
||||
it has been superseded by module path ``wcwidth.table_zero``.
|
||||
|
||||
0.1.4 *2014-11-20 Pre-Alpha*
|
||||
* **Feature**: ``wcswidth()`` now determines printable length
|
||||
for (most) combining_ characters. The developer's tool
|
||||
`bin/wcwidth-browser.py`_ is improved to display combining_
|
||||
characters when provided the ``--combining`` option
|
||||
(`Thomas Ballinger`_ and `Leta Montopoli`_ `PR #5`_).
|
||||
* **Feature**: added static analysis (prospector_) to testing
|
||||
framework.
|
||||
|
||||
0.1.3 *2014-10-29 Pre-Alpha*
|
||||
* **Bugfix**: 2nd parameter of wcswidth was not honored.
|
||||
(`Thomas Ballinger`_, `PR #4`_).
|
||||
|
||||
0.1.2 *2014-10-28 Pre-Alpha*
|
||||
* **Updated** tables to Unicode Specification 7.0.0.
|
||||
(`Thomas Ballinger`_, `PR #3`_).
|
||||
|
||||
0.1.1 *2014-05-14 Pre-Alpha*
|
||||
* Initial release to pypi, Based on Unicode Specification 6.3.0
|
||||
|
||||
This code was originally derived directly from C code of the same name,
|
||||
whose latest version is available at
|
||||
https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c::
|
||||
|
||||
* Markus Kuhn -- 2007-05-26 (Unicode 5.0)
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software
|
||||
* for any purpose and without fee is hereby granted. The author
|
||||
* disclaims all warranties with regard to this software.
|
||||
|
||||
.. _`Specification_from_pypi`: https://wcwidth.readthedocs.io/en/latest/specs.html
|
||||
.. _`tox`: https://tox.wiki/en/latest/
|
||||
.. _`prospector`: https://github.com/landscapeio/prospector
|
||||
.. _`combining`: https://en.wikipedia.org/wiki/Combining_character
|
||||
.. _`bin/`: https://github.com/jquast/wcwidth/tree/master/bin
|
||||
.. _`bin/wcwidth-browser.py`: https://github.com/jquast/wcwidth/blob/master/bin/wcwidth-browser.py
|
||||
.. _`Thomas Ballinger`: https://github.com/thomasballinger
|
||||
.. _`Leta Montopoli`: https://github.com/lmontopo
|
||||
.. _`Philip Craig`: https://github.com/philipc
|
||||
.. _`PR #3`: https://github.com/jquast/wcwidth/pull/3
|
||||
.. _`PR #4`: https://github.com/jquast/wcwidth/pull/4
|
||||
.. _`PR #5`: https://github.com/jquast/wcwidth/pull/5
|
||||
.. _`PR #11`: https://github.com/jquast/wcwidth/pull/11
|
||||
.. _`PR #18`: https://github.com/jquast/wcwidth/pull/18
|
||||
.. _`PR #30`: https://github.com/jquast/wcwidth/pull/30
|
||||
.. _`PR #35`: https://github.com/jquast/wcwidth/pull/35
|
||||
.. _`PR #82`: https://github.com/jquast/wcwidth/pull/82
|
||||
.. _`PR #91`: https://github.com/jquast/wcwidth/pull/91
|
||||
.. _`PR #97`: https://github.com/jquast/wcwidth/pull/97
|
||||
.. _`PR #98`: https://github.com/jquast/wcwidth/pull/98
|
||||
.. _`PR #100`: https://github.com/jquast/wcwidth/pull/100
|
||||
.. _`Issue #101`: https://github.com/jquast/wcwidth/issues/101
|
||||
.. _`jquast/blessed`: https://github.com/jquast/blessed
|
||||
.. _`selectel/pyte`: https://github.com/selectel/pyte
|
||||
.. _`thomasballinger/curtsies`: https://github.com/thomasballinger/curtsies
|
||||
.. _`dbcli/pgcli`: https://github.com/dbcli/pgcli
|
||||
.. _`prompt-toolkit/python-prompt-toolkit`: https://github.com/prompt-toolkit/python-prompt-toolkit
|
||||
.. _`timoxley/wcwidth`: https://github.com/timoxley/wcwidth
|
||||
.. _`wcwidth(3)`: https://man7.org/linux/man-pages/man3/wcwidth.3.html
|
||||
.. _`wcswidth(3)`: https://man7.org/linux/man-pages/man3/wcswidth.3.html
|
||||
.. _`astanin/python-tabulate`: https://github.com/astanin/python-tabulate
|
||||
.. _`janlelis/unicode-display_width`: https://github.com/janlelis/unicode-display_width
|
||||
.. _`rspeer/python-ftfy`: https://github.com/rspeer/python-ftfy
|
||||
.. _`alecrabbit/php-wcwidth`: https://github.com/alecrabbit/php-wcwidth
|
||||
.. _`Text::CharWidth`: https://metacpan.org/pod/Text::CharWidth
|
||||
.. _`bluebear94/Terminal-WCWidth`: https://github.com/bluebear94/Terminal-WCWidth
|
||||
.. _`mattn/go-runewidth`: https://github.com/mattn/go-runewidth
|
||||
.. _`grepsuzette/wcwidth`: https://github.com/grepsuzette/wcwidth
|
||||
.. _`jquast/ucs-detect`: https://github.com/jquast/ucs-detect
|
||||
.. _`Avram Lubkin`: https://github.com/avylove
|
||||
.. _`nbedos/termtosvg`: https://github.com/nbedos/termtosvg
|
||||
.. _`peterbrittain/asciimatics`: https://github.com/peterbrittain/asciimatics
|
||||
.. _`aperezdc/lua-wcwidth`: https://github.com/aperezdc/lua-wcwidth
|
||||
.. _`joachimschmidt557/zig-wcwidth`: https://github.com/joachimschmidt557/zig-wcwidth
|
||||
.. _`fumiyas/wcwidth-cjk`: https://github.com/fumiyas/wcwidth-cjk
|
||||
.. _`joshuarubin/wcwidth9`: https://github.com/joshuarubin/wcwidth9
|
||||
.. _`python-cmd2/cmd2`: https://github.com/python-cmd2/cmd2
|
||||
.. _`stratis-storage/stratis-cli`: https://github.com/stratis-storage/stratis-cli
|
||||
.. _`ihabunek/toot`: https://github.com/ihabunek/toot
|
||||
.. _`saulpw/visidata`: https://github.com/saulpw/visidata
|
||||
.. _`pip-tools`: https://pip-tools.readthedocs.io/
|
||||
.. _`sphinx`: https://www.sphinx-doc.org/
|
||||
.. |pypi_downloads| image:: https://img.shields.io/pypi/dm/wcwidth.svg?logo=pypi
|
||||
:alt: Downloads
|
||||
:target: https://pypi.org/project/wcwidth/
|
||||
.. |codecov| image:: https://codecov.io/gh/jquast/wcwidth/branch/master/graph/badge.svg
|
||||
:alt: codecov.io Code Coverage
|
||||
:target: https://app.codecov.io/gh/jquast/wcwidth/
|
||||
.. |license| image:: https://img.shields.io/pypi/l/wcwidth.svg
|
||||
:target: https://pypi.org/project/wcwidth/
|
||||
:alt: MIT License
|
|
@ -1,20 +0,0 @@
|
|||
wcwidth-0.2.13.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
wcwidth-0.2.13.dist-info/LICENSE,sha256=cLmKlaIUTrcK-AF_qMbZXOJH5AhnQ26LxknhN_4T0ho,1322
|
||||
wcwidth-0.2.13.dist-info/METADATA,sha256=wBs2ALubn0kTdhEFDXc1gZBU_zf4rlfNgv1YS02jzLQ,14992
|
||||
wcwidth-0.2.13.dist-info/RECORD,,
|
||||
wcwidth-0.2.13.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
wcwidth-0.2.13.dist-info/WHEEL,sha256=iYlv5fX357PQyRT2o6tw1bN-YcKFFHKqB_LwHO5wP-g,110
|
||||
wcwidth-0.2.13.dist-info/top_level.txt,sha256=LLjS8SFiXXuLEcD2BNdFdGhpKWe5opHtvn7KNj9AIRI,8
|
||||
wcwidth-0.2.13.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
||||
wcwidth/__init__.py,sha256=ecZx3UVoktZuAvatG6NetByVFgENkKl9htmk0ZasTmA,1076
|
||||
wcwidth/__pycache__/__init__.cpython-311.pyc,,
|
||||
wcwidth/__pycache__/table_vs16.cpython-311.pyc,,
|
||||
wcwidth/__pycache__/table_wide.cpython-311.pyc,,
|
||||
wcwidth/__pycache__/table_zero.cpython-311.pyc,,
|
||||
wcwidth/__pycache__/unicode_versions.cpython-311.pyc,,
|
||||
wcwidth/__pycache__/wcwidth.cpython-311.pyc,,
|
||||
wcwidth/table_vs16.py,sha256=hPbuoFxmxrGfuBaeoheMTAGmgB2a4EudhxYsYokLf6o,6857
|
||||
wcwidth/table_wide.py,sha256=vUHjEOuRw1WGyUcIw2L9GymZsYvC2I3dc858mlYyTYM,100896
|
||||
wcwidth/table_zero.py,sha256=4ZeihLZDH8obgrwA6ct-vu2lxc4t_DsfyiB9p9Ovxbo,359450
|
||||
wcwidth/unicode_versions.py,sha256=7nShgeRYrvZFkGpREdr-PkUeXnuM-WxeOmGYj6QNaaE,851
|
||||
wcwidth/wcwidth.py,sha256=TLzyH1ahdEDDPOIMcqVO4U0gyKwSyZdzAsSgEPuVFGY,14512
|
|
@ -1,6 +0,0 @@
|
|||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.41.2)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
|
@ -1 +0,0 @@
|
|||
wcwidth
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
"""
|
||||
Wcwidth module.
|
||||
|
||||
https://github.com/jquast/wcwidth
|
||||
"""
|
||||
# re-export all functions & definitions, even private ones, from top-level
|
||||
# module path, to allow for 'from wcwidth import _private_func'. Of course,
|
||||
# user beware that any _private function may disappear or change signature at
|
||||
# any future version.
|
||||
|
||||
# local
|
||||
from .wcwidth import ZERO_WIDTH # noqa
|
||||
from .wcwidth import (WIDE_EASTASIAN,
|
||||
VS16_NARROW_TO_WIDE,
|
||||
wcwidth,
|
||||
wcswidth,
|
||||
_bisearch,
|
||||
list_versions,
|
||||
_wcmatch_version,
|
||||
_wcversion_value)
|
||||
|
||||
# The __all__ attribute defines the items exported from statement,
|
||||
# 'from wcwidth import *', but also to say, "This is the public API".
|
||||
__all__ = ('wcwidth', 'wcswidth', 'list_versions')
|
||||
|
||||
# We also used pkg_resources to load unicode version tables from version.json,
|
||||
# generated by bin/update-tables.py, but some environments are unable to
|
||||
# import pkg_resources for one reason or another, yikes!
|
||||
__version__ = '0.2.13'
|
|
@ -1,125 +0,0 @@
|
|||
"""
|
||||
Exports VS16_NARROW_TO_WIDE table keyed by supporting unicode version level.
|
||||
|
||||
This code generated by wcwidth/bin/update-tables.py on 2023-11-07 16:43:49 UTC.
|
||||
"""
|
||||
VS16_NARROW_TO_WIDE = {
|
||||
'9.0.0': (
|
||||
# Source: 9.0.0
|
||||
# Date: 2023-02-01, 02:22:54 GMT
|
||||
#
|
||||
(0x00023, 0x00023,), # Number Sign
|
||||
(0x0002a, 0x0002a,), # Asterisk
|
||||
(0x00030, 0x00039,), # Digit Zero ..Digit Nine
|
||||
(0x000a9, 0x000a9,), # Copyright Sign
|
||||
(0x000ae, 0x000ae,), # Registered Sign
|
||||
(0x0203c, 0x0203c,), # Double Exclamation Mark
|
||||
(0x02049, 0x02049,), # Exclamation Question Mark
|
||||
(0x02122, 0x02122,), # Trade Mark Sign
|
||||
(0x02139, 0x02139,), # Information Source
|
||||
(0x02194, 0x02199,), # Left Right Arrow ..South West Arrow
|
||||
(0x021a9, 0x021aa,), # Leftwards Arrow With Hoo..Rightwards Arrow With Ho
|
||||
(0x02328, 0x02328,), # Keyboard
|
||||
(0x023cf, 0x023cf,), # Eject Symbol
|
||||
(0x023ed, 0x023ef,), # Black Right-pointing Dou..Black Right-pointing Tri
|
||||
(0x023f1, 0x023f2,), # Stopwatch ..Timer Clock
|
||||
(0x023f8, 0x023fa,), # Double Vertical Bar ..Black Circle For Record
|
||||
(0x024c2, 0x024c2,), # Circled Latin Capital Letter M
|
||||
(0x025aa, 0x025ab,), # Black Small Square ..White Small Square
|
||||
(0x025b6, 0x025b6,), # Black Right-pointing Triangle
|
||||
(0x025c0, 0x025c0,), # Black Left-pointing Triangle
|
||||
(0x025fb, 0x025fc,), # White Medium Square ..Black Medium Square
|
||||
(0x02600, 0x02604,), # Black Sun With Rays ..Comet
|
||||
(0x0260e, 0x0260e,), # Black Telephone
|
||||
(0x02611, 0x02611,), # Ballot Box With Check
|
||||
(0x02618, 0x02618,), # Shamrock
|
||||
(0x0261d, 0x0261d,), # White Up Pointing Index
|
||||
(0x02620, 0x02620,), # Skull And Crossbones
|
||||
(0x02622, 0x02623,), # Radioactive Sign ..Biohazard Sign
|
||||
(0x02626, 0x02626,), # Orthodox Cross
|
||||
(0x0262a, 0x0262a,), # Star And Crescent
|
||||
(0x0262e, 0x0262f,), # Peace Symbol ..Yin Yang
|
||||
(0x02638, 0x0263a,), # Wheel Of Dharma ..White Smiling Face
|
||||
(0x02640, 0x02640,), # Female Sign
|
||||
(0x02642, 0x02642,), # Male Sign
|
||||
(0x0265f, 0x02660,), # Black Chess Pawn ..Black Spade Suit
|
||||
(0x02663, 0x02663,), # Black Club Suit
|
||||
(0x02665, 0x02666,), # Black Heart Suit ..Black Diamond Suit
|
||||
(0x02668, 0x02668,), # Hot Springs
|
||||
(0x0267b, 0x0267b,), # Black Universal Recycling Symbol
|
||||
(0x0267e, 0x0267e,), # Permanent Paper Sign
|
||||
(0x02692, 0x02692,), # Hammer And Pick
|
||||
(0x02694, 0x02697,), # Crossed Swords ..Alembic
|
||||
(0x02699, 0x02699,), # Gear
|
||||
(0x0269b, 0x0269c,), # Atom Symbol ..Fleur-de-lis
|
||||
(0x026a0, 0x026a0,), # Warning Sign
|
||||
(0x026a7, 0x026a7,), # Male With Stroke And Male And Female Sign
|
||||
(0x026b0, 0x026b1,), # Coffin ..Funeral Urn
|
||||
(0x026c8, 0x026c8,), # Thunder Cloud And Rain
|
||||
(0x026cf, 0x026cf,), # Pick
|
||||
(0x026d1, 0x026d1,), # Helmet With White Cross
|
||||
(0x026d3, 0x026d3,), # Chains
|
||||
(0x026e9, 0x026e9,), # Shinto Shrine
|
||||
(0x026f0, 0x026f1,), # Mountain ..Umbrella On Ground
|
||||
(0x026f4, 0x026f4,), # Ferry
|
||||
(0x026f7, 0x026f9,), # Skier ..Person With Ball
|
||||
(0x02702, 0x02702,), # Black Scissors
|
||||
(0x02708, 0x02709,), # Airplane ..Envelope
|
||||
(0x0270c, 0x0270d,), # Victory Hand ..Writing Hand
|
||||
(0x0270f, 0x0270f,), # Pencil
|
||||
(0x02712, 0x02712,), # Black Nib
|
||||
(0x02714, 0x02714,), # Heavy Check Mark
|
||||
(0x02716, 0x02716,), # Heavy Multiplication X
|
||||
(0x0271d, 0x0271d,), # Latin Cross
|
||||
(0x02721, 0x02721,), # Star Of David
|
||||
(0x02733, 0x02734,), # Eight Spoked Asterisk ..Eight Pointed Black Star
|
||||
(0x02744, 0x02744,), # Snowflake
|
||||
(0x02747, 0x02747,), # Sparkle
|
||||
(0x02763, 0x02764,), # Heavy Heart Exclamation ..Heavy Black Heart
|
||||
(0x027a1, 0x027a1,), # Black Rightwards Arrow
|
||||
(0x02934, 0x02935,), # Arrow Pointing Rightward..Arrow Pointing Rightward
|
||||
(0x02b05, 0x02b07,), # Leftwards Black Arrow ..Downwards Black Arrow
|
||||
(0x1f170, 0x1f171,), # Negative Squared Latin C..Negative Squared Latin C
|
||||
(0x1f17e, 0x1f17f,), # Negative Squared Latin C..Negative Squared Latin C
|
||||
(0x1f321, 0x1f321,), # Thermometer
|
||||
(0x1f324, 0x1f32c,), # White Sun With Small Clo..Wind Blowing Face
|
||||
(0x1f336, 0x1f336,), # Hot Pepper
|
||||
(0x1f37d, 0x1f37d,), # Fork And Knife With Plate
|
||||
(0x1f396, 0x1f397,), # Military Medal ..Reminder Ribbon
|
||||
(0x1f399, 0x1f39b,), # Studio Microphone ..Control Knobs
|
||||
(0x1f39e, 0x1f39f,), # Film Frames ..Admission Tickets
|
||||
(0x1f3cb, 0x1f3ce,), # Weight Lifter ..Racing Car
|
||||
(0x1f3d4, 0x1f3df,), # Snow Capped Mountain ..Stadium
|
||||
(0x1f3f3, 0x1f3f3,), # Waving White Flag
|
||||
(0x1f3f5, 0x1f3f5,), # Rosette
|
||||
(0x1f3f7, 0x1f3f7,), # Label
|
||||
(0x1f43f, 0x1f43f,), # Chipmunk
|
||||
(0x1f441, 0x1f441,), # Eye
|
||||
(0x1f4fd, 0x1f4fd,), # Film Projector
|
||||
(0x1f549, 0x1f54a,), # Om Symbol ..Dove Of Peace
|
||||
(0x1f56f, 0x1f570,), # Candle ..Mantelpiece Clock
|
||||
(0x1f573, 0x1f579,), # Hole ..Joystick
|
||||
(0x1f587, 0x1f587,), # Linked Paperclips
|
||||
(0x1f58a, 0x1f58d,), # Lower Left Ballpoint Pen..Lower Left Crayon
|
||||
(0x1f590, 0x1f590,), # Raised Hand With Fingers Splayed
|
||||
(0x1f5a5, 0x1f5a5,), # Desktop Computer
|
||||
(0x1f5a8, 0x1f5a8,), # Printer
|
||||
(0x1f5b1, 0x1f5b2,), # Three Button Mouse ..Trackball
|
||||
(0x1f5bc, 0x1f5bc,), # Frame With Picture
|
||||
(0x1f5c2, 0x1f5c4,), # Card Index Dividers ..File Cabinet
|
||||
(0x1f5d1, 0x1f5d3,), # Wastebasket ..Spiral Calendar Pad
|
||||
(0x1f5dc, 0x1f5de,), # Compression ..Rolled-up Newspaper
|
||||
(0x1f5e1, 0x1f5e1,), # Dagger Knife
|
||||
(0x1f5e3, 0x1f5e3,), # Speaking Head In Silhouette
|
||||
(0x1f5e8, 0x1f5e8,), # Left Speech Bubble
|
||||
(0x1f5ef, 0x1f5ef,), # Right Anger Bubble
|
||||
(0x1f5f3, 0x1f5f3,), # Ballot Box With Ballot
|
||||
(0x1f5fa, 0x1f5fa,), # World Map
|
||||
(0x1f6cb, 0x1f6cb,), # Couch And Lamp
|
||||
(0x1f6cd, 0x1f6cf,), # Shopping Bags ..Bed
|
||||
(0x1f6e0, 0x1f6e5,), # Hammer And Wrench ..Motor Boat
|
||||
(0x1f6e9, 0x1f6e9,), # Small Airplane
|
||||
(0x1f6f0, 0x1f6f0,), # Satellite
|
||||
(0x1f6f3, 0x1f6f3,), # Passenger Ship
|
||||
),
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,38 +0,0 @@
|
|||
"""
|
||||
Exports function list_versions() for unicode version level support.
|
||||
|
||||
This code generated by wcwidth/bin/update-tables.py on 2023-09-14 15:45:33 UTC.
|
||||
"""
|
||||
|
||||
|
||||
def list_versions():
|
||||
"""
|
||||
Return Unicode version levels supported by this module release.
|
||||
|
||||
Any of the version strings returned may be used as keyword argument
|
||||
``unicode_version`` to the ``wcwidth()`` family of functions.
|
||||
|
||||
:returns: Supported Unicode version numbers in ascending sorted order.
|
||||
:rtype: list[str]
|
||||
"""
|
||||
return (
|
||||
"4.1.0",
|
||||
"5.0.0",
|
||||
"5.1.0",
|
||||
"5.2.0",
|
||||
"6.0.0",
|
||||
"6.1.0",
|
||||
"6.2.0",
|
||||
"6.3.0",
|
||||
"7.0.0",
|
||||
"8.0.0",
|
||||
"9.0.0",
|
||||
"10.0.0",
|
||||
"11.0.0",
|
||||
"12.0.0",
|
||||
"12.1.0",
|
||||
"13.0.0",
|
||||
"14.0.0",
|
||||
"15.0.0",
|
||||
"15.1.0",
|
||||
)
|
|
@ -1,345 +0,0 @@
|
|||
"""
|
||||
This is a python implementation of wcwidth() and wcswidth().
|
||||
|
||||
https://github.com/jquast/wcwidth
|
||||
|
||||
from Markus Kuhn's C code, retrieved from:
|
||||
|
||||
http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
||||
|
||||
This is an implementation of wcwidth() and wcswidth() (defined in
|
||||
IEEE Std 1002.1-2001) for Unicode.
|
||||
|
||||
http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
|
||||
http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
|
||||
|
||||
In fixed-width output devices, Latin characters all occupy a single
|
||||
"cell" position of equal width, whereas ideographic CJK characters
|
||||
occupy two such cells. Interoperability between terminal-line
|
||||
applications and (teletype-style) character terminals using the
|
||||
UTF-8 encoding requires agreement on which character should advance
|
||||
the cursor by how many cell positions. No established formal
|
||||
standards exist at present on which Unicode character shall occupy
|
||||
how many cell positions on character terminals. These routines are
|
||||
a first attempt of defining such behavior based on simple rules
|
||||
applied to data provided by the Unicode Consortium.
|
||||
|
||||
For some graphical characters, the Unicode standard explicitly
|
||||
defines a character-cell width via the definition of the East Asian
|
||||
FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
|
||||
In all these cases, there is no ambiguity about which width a
|
||||
terminal shall use. For characters in the East Asian Ambiguous (A)
|
||||
class, the width choice depends purely on a preference of backward
|
||||
compatibility with either historic CJK or Western practice.
|
||||
Choosing single-width for these characters is easy to justify as
|
||||
the appropriate long-term solution, as the CJK practice of
|
||||
displaying these characters as double-width comes from historic
|
||||
implementation simplicity (8-bit encoded characters were displayed
|
||||
single-width and 16-bit ones double-width, even for Greek,
|
||||
Cyrillic, etc.) and not any typographic considerations.
|
||||
|
||||
Much less clear is the choice of width for the Not East Asian
|
||||
(Neutral) class. Existing practice does not dictate a width for any
|
||||
of these characters. It would nevertheless make sense
|
||||
typographically to allocate two character cells to characters such
|
||||
as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
|
||||
represented adequately with a single-width glyph. The following
|
||||
routines at present merely assign a single-cell width to all
|
||||
neutral characters, in the interest of simplicity. This is not
|
||||
entirely satisfactory and should be reconsidered before
|
||||
establishing a formal standard in this area. At the moment, the
|
||||
decision which Not East Asian (Neutral) characters should be
|
||||
represented by double-width glyphs cannot yet be answered by
|
||||
applying a simple rule from the Unicode database content. Setting
|
||||
up a proper standard for the behavior of UTF-8 character terminals
|
||||
will require a careful analysis not only of each Unicode character,
|
||||
but also of each presentation form, something the author of these
|
||||
routines has avoided to do so far.
|
||||
|
||||
http://www.unicode.org/unicode/reports/tr11/
|
||||
|
||||
Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
||||
"""
|
||||
from __future__ import division
|
||||
|
||||
# std imports
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
# local
|
||||
from .table_vs16 import VS16_NARROW_TO_WIDE
|
||||
from .table_wide import WIDE_EASTASIAN
|
||||
from .table_zero import ZERO_WIDTH
|
||||
from .unicode_versions import list_versions
|
||||
|
||||
try:
|
||||
# std imports
|
||||
from functools import lru_cache
|
||||
except ImportError:
|
||||
# lru_cache was added in Python 3.2
|
||||
# 3rd party
|
||||
from backports.functools_lru_cache import lru_cache
|
||||
|
||||
# global cache
|
||||
_PY3 = sys.version_info[0] >= 3
|
||||
|
||||
|
||||
def _bisearch(ucs, table):
|
||||
"""
|
||||
Auxiliary function for binary search in interval table.
|
||||
|
||||
:arg int ucs: Ordinal value of unicode character.
|
||||
:arg list table: List of starting and ending ranges of ordinal values,
|
||||
in form of ``[(start, end), ...]``.
|
||||
:rtype: int
|
||||
:returns: 1 if ordinal value ucs is found within lookup table, else 0.
|
||||
"""
|
||||
lbound = 0
|
||||
ubound = len(table) - 1
|
||||
|
||||
if ucs < table[0][0] or ucs > table[ubound][1]:
|
||||
return 0
|
||||
while ubound >= lbound:
|
||||
mid = (lbound + ubound) // 2
|
||||
if ucs > table[mid][1]:
|
||||
lbound = mid + 1
|
||||
elif ucs < table[mid][0]:
|
||||
ubound = mid - 1
|
||||
else:
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
@lru_cache(maxsize=1000)
|
||||
def wcwidth(wc, unicode_version='auto'):
|
||||
r"""
|
||||
Given one Unicode character, return its printable length on a terminal.
|
||||
|
||||
:param str wc: A single Unicode character.
|
||||
:param str unicode_version: A Unicode version number, such as
|
||||
``'6.0.0'``. A list of version levels suported by wcwidth
|
||||
is returned by :func:`list_versions`.
|
||||
|
||||
Any version string may be specified without error -- the nearest
|
||||
matching version is selected. When ``latest`` (default), the
|
||||
highest Unicode version level is used.
|
||||
:return: The width, in cells, necessary to display the character of
|
||||
Unicode string character, ``wc``. Returns 0 if the ``wc`` argument has
|
||||
no printable effect on a terminal (such as NUL '\0'), -1 if ``wc`` is
|
||||
not printable, or has an indeterminate effect on the terminal, such as
|
||||
a control character. Otherwise, the number of column positions the
|
||||
character occupies on a graphic terminal (1 or 2) is returned.
|
||||
:rtype: int
|
||||
|
||||
See :ref:`Specification` for details of cell measurement.
|
||||
"""
|
||||
ucs = ord(wc) if wc else 0
|
||||
|
||||
# small optimization: early return of 1 for printable ASCII, this provides
|
||||
# approximately 40% performance improvement for mostly-ascii documents, with
|
||||
# less than 1% impact to others.
|
||||
if 32 <= ucs < 0x7f:
|
||||
return 1
|
||||
|
||||
# C0/C1 control characters are -1 for compatibility with POSIX-like calls
|
||||
if ucs and ucs < 32 or 0x07F <= ucs < 0x0A0:
|
||||
return -1
|
||||
|
||||
_unicode_version = _wcmatch_version(unicode_version)
|
||||
|
||||
# Zero width
|
||||
if _bisearch(ucs, ZERO_WIDTH[_unicode_version]):
|
||||
return 0
|
||||
|
||||
# 1 or 2 width
|
||||
return 1 + _bisearch(ucs, WIDE_EASTASIAN[_unicode_version])
|
||||
|
||||
|
||||
def wcswidth(pwcs, n=None, unicode_version='auto'):
|
||||
"""
|
||||
Given a unicode string, return its printable length on a terminal.
|
||||
|
||||
:param str pwcs: Measure width of given unicode string.
|
||||
:param int n: When ``n`` is None (default), return the length of the entire
|
||||
string, otherwise only the first ``n`` characters are measured. This
|
||||
argument exists only for compatibility with the C POSIX function
|
||||
signature. It is suggested instead to use python's string slicing
|
||||
capability, ``wcswidth(pwcs[:n])``
|
||||
:param str unicode_version: An explicit definition of the unicode version
|
||||
level to use for determination, may be ``auto`` (default), which uses
|
||||
the Environment Variable, ``UNICODE_VERSION`` if defined, or the latest
|
||||
available unicode version, otherwise.
|
||||
:rtype: int
|
||||
:returns: The width, in cells, needed to display the first ``n`` characters
|
||||
of the unicode string ``pwcs``. Returns ``-1`` for C0 and C1 control
|
||||
characters!
|
||||
|
||||
See :ref:`Specification` for details of cell measurement.
|
||||
"""
|
||||
# this 'n' argument is a holdover for POSIX function
|
||||
_unicode_version = None
|
||||
end = len(pwcs) if n is None else n
|
||||
width = 0
|
||||
idx = 0
|
||||
last_measured_char = None
|
||||
while idx < end:
|
||||
char = pwcs[idx]
|
||||
if char == u'\u200D':
|
||||
# Zero Width Joiner, do not measure this or next character
|
||||
idx += 2
|
||||
continue
|
||||
if char == u'\uFE0F' and last_measured_char:
|
||||
# on variation selector 16 (VS16) following another character,
|
||||
# conditionally add '1' to the measured width if that character is
|
||||
# known to be converted from narrow to wide by the VS16 character.
|
||||
if _unicode_version is None:
|
||||
_unicode_version = _wcversion_value(_wcmatch_version(unicode_version))
|
||||
if _unicode_version >= (9, 0, 0):
|
||||
width += _bisearch(ord(last_measured_char), VS16_NARROW_TO_WIDE["9.0.0"])
|
||||
last_measured_char = None
|
||||
idx += 1
|
||||
continue
|
||||
# measure character at current index
|
||||
wcw = wcwidth(char, unicode_version)
|
||||
if wcw < 0:
|
||||
# early return -1 on C0 and C1 control characters
|
||||
return wcw
|
||||
if wcw > 0:
|
||||
# track last character measured to contain a cell, so that
|
||||
# subsequent VS-16 modifiers may be understood
|
||||
last_measured_char = char
|
||||
width += wcw
|
||||
idx += 1
|
||||
return width
|
||||
|
||||
|
||||
@lru_cache(maxsize=128)
|
||||
def _wcversion_value(ver_string):
|
||||
"""
|
||||
Integer-mapped value of given dotted version string.
|
||||
|
||||
:param str ver_string: Unicode version string, of form ``n.n.n``.
|
||||
:rtype: tuple(int)
|
||||
:returns: tuple of digit tuples, ``tuple(int, [...])``.
|
||||
"""
|
||||
retval = tuple(map(int, (ver_string.split('.'))))
|
||||
return retval
|
||||
|
||||
|
||||
@lru_cache(maxsize=8)
|
||||
def _wcmatch_version(given_version):
|
||||
"""
|
||||
Return nearest matching supported Unicode version level.
|
||||
|
||||
If an exact match is not determined, the nearest lowest version level is
|
||||
returned after a warning is emitted. For example, given supported levels
|
||||
``4.1.0`` and ``5.0.0``, and a version string of ``4.9.9``, then ``4.1.0``
|
||||
is selected and returned:
|
||||
|
||||
>>> _wcmatch_version('4.9.9')
|
||||
'4.1.0'
|
||||
>>> _wcmatch_version('8.0')
|
||||
'8.0.0'
|
||||
>>> _wcmatch_version('1')
|
||||
'4.1.0'
|
||||
|
||||
:param str given_version: given version for compare, may be ``auto``
|
||||
(default), to select Unicode Version from Environment Variable,
|
||||
``UNICODE_VERSION``. If the environment variable is not set, then the
|
||||
latest is used.
|
||||
:rtype: str
|
||||
:returns: unicode string, or non-unicode ``str`` type for python 2
|
||||
when given ``version`` is also type ``str``.
|
||||
"""
|
||||
# Design note: the choice to return the same type that is given certainly
|
||||
# complicates it for python 2 str-type, but allows us to define an api that
|
||||
# uses 'string-type' for unicode version level definitions, so all of our
|
||||
# example code works with all versions of python.
|
||||
#
|
||||
# That, along with the string-to-numeric and comparisons of earliest,
|
||||
# latest, matching, or nearest, greatly complicates this function.
|
||||
# Performance is somewhat curbed by memoization.
|
||||
_return_str = not _PY3 and isinstance(given_version, str)
|
||||
|
||||
if _return_str:
|
||||
# avoid list-comprehension to work around a coverage issue:
|
||||
# https://github.com/nedbat/coveragepy/issues/753
|
||||
unicode_versions = list(map(lambda ucs: ucs.encode(), list_versions()))
|
||||
else:
|
||||
unicode_versions = list_versions()
|
||||
latest_version = unicode_versions[-1]
|
||||
|
||||
if given_version in (u'auto', 'auto'):
|
||||
given_version = os.environ.get(
|
||||
'UNICODE_VERSION',
|
||||
'latest' if not _return_str else latest_version.encode())
|
||||
|
||||
if given_version in (u'latest', 'latest'):
|
||||
# default match, when given as 'latest', use the most latest unicode
|
||||
# version specification level supported.
|
||||
return latest_version if not _return_str else latest_version.encode()
|
||||
|
||||
if given_version in unicode_versions:
|
||||
# exact match, downstream has specified an explicit matching version
|
||||
# matching any value of list_versions().
|
||||
return given_version if not _return_str else given_version.encode()
|
||||
|
||||
# The user's version is not supported by ours. We return the newest unicode
|
||||
# version level that we support below their given value.
|
||||
try:
|
||||
cmp_given = _wcversion_value(given_version)
|
||||
|
||||
except ValueError:
|
||||
# submitted value raises ValueError in int(), warn and use latest.
|
||||
warnings.warn("UNICODE_VERSION value, {given_version!r}, is invalid. "
|
||||
"Value should be in form of `integer[.]+', the latest "
|
||||
"supported unicode version {latest_version!r} has been "
|
||||
"inferred.".format(given_version=given_version,
|
||||
latest_version=latest_version))
|
||||
return latest_version if not _return_str else latest_version.encode()
|
||||
|
||||
# given version is less than any available version, return earliest
|
||||
# version.
|
||||
earliest_version = unicode_versions[0]
|
||||
cmp_earliest_version = _wcversion_value(earliest_version)
|
||||
|
||||
if cmp_given <= cmp_earliest_version:
|
||||
# this probably isn't what you wanted, the oldest wcwidth.c you will
|
||||
# find in the wild is likely version 5 or 6, which we both support,
|
||||
# but it's better than not saying anything at all.
|
||||
warnings.warn("UNICODE_VERSION value, {given_version!r}, is lower "
|
||||
"than any available unicode version. Returning lowest "
|
||||
"version level, {earliest_version!r}".format(
|
||||
given_version=given_version,
|
||||
earliest_version=earliest_version))
|
||||
return earliest_version if not _return_str else earliest_version.encode()
|
||||
|
||||
# create list of versions which are less than our equal to given version,
|
||||
# and return the tail value, which is the highest level we may support,
|
||||
# or the latest value we support, when completely unmatched or higher
|
||||
# than any supported version.
|
||||
#
|
||||
# function will never complete, always returns.
|
||||
for idx, unicode_version in enumerate(unicode_versions):
|
||||
# look ahead to next value
|
||||
try:
|
||||
cmp_next_version = _wcversion_value(unicode_versions[idx + 1])
|
||||
except IndexError:
|
||||
# at end of list, return latest version
|
||||
return latest_version if not _return_str else latest_version.encode()
|
||||
|
||||
# Maybe our given version has less parts, as in tuple(8, 0), than the
|
||||
# next compare version tuple(8, 0, 0). Test for an exact match by
|
||||
# comparison of only the leading dotted piece(s): (8, 0) == (8, 0).
|
||||
if cmp_given == cmp_next_version[:len(cmp_given)]:
|
||||
return unicode_versions[idx + 1]
|
||||
|
||||
# Or, if any next value is greater than our given support level
|
||||
# version, return the current value in index. Even though it must
|
||||
# be less than the given value, its our closest possible match. That
|
||||
# is, 4.1 is returned for given 4.9.9, where 4.1 and 5.0 are available.
|
||||
if cmp_next_version > cmp_given:
|
||||
return unicode_version
|
||||
assert False, ("Code path unreachable", given_version, unicode_versions) # pragma: no cover
|
123
main.py
123
main.py
|
@ -1,123 +0,0 @@
|
|||
import bitutilities as bu
|
||||
|
||||
operation = ""
|
||||
method = ""
|
||||
|
||||
user_input = []
|
||||
|
||||
|
||||
def process_command(symbol):
|
||||
global operation, method
|
||||
|
||||
if symbol.lower() in "asmdrq":
|
||||
operation = symbol
|
||||
elif operation == "m" and symbol in "1234":
|
||||
method = symbol
|
||||
elif operation == "d" and symbol in "12":
|
||||
method = symbol
|
||||
elif symbol in " ;:":
|
||||
pass
|
||||
else:
|
||||
print(f"Error: unexpected instruction '{symbol}', skipping")
|
||||
|
||||
|
||||
def perform_operation(first_register: bu.BasicRegister, second_register: bu.BasicRegister):
|
||||
global operation, method
|
||||
|
||||
match operation:
|
||||
case "a":
|
||||
result, carry = bu.binary_sum_with_carry(first_register, second_register)
|
||||
print(f"\nSum: {result}\nCarry: {int(carry)}")
|
||||
operation, method = "", ""
|
||||
case "s":
|
||||
result, carry = bu.binary_subtraction_second_complement(first_register, second_register)
|
||||
print(f"\nSubtraction: {result}\nCarry: {int(carry)}")
|
||||
operation, method = "", ""
|
||||
case "m":
|
||||
match method:
|
||||
case "1":
|
||||
result, data_table = bu.binary_multiplication_method_1(first_register, second_register)
|
||||
print(f"\nMultiplication (method 1):\n{bu.format_device_state_table(data_table)}\nResult: {result}")
|
||||
operation, method = "", ""
|
||||
case "2":
|
||||
result, data_table = bu.binary_multiplication_method_2(first_register, second_register)
|
||||
print(f"\nMultiplication (method 2):\n{bu.format_device_state_table(data_table)}\nResult: {result}")
|
||||
operation, method = "", ""
|
||||
case "3":
|
||||
result, data_table = bu.binary_multiplication_method_3(first_register, second_register)
|
||||
print(f"\nMultiplication (method 3):\n{bu.format_device_state_table(data_table)}\nResult: {result}")
|
||||
operation, method = "", ""
|
||||
case "4":
|
||||
result, data_table = bu.binary_multiplication_method_4(first_register, second_register)
|
||||
print(f"\nMultiplication (method 4):\n{bu.format_device_state_table(data_table)}\nResult: {result}")
|
||||
operation, method = "", ""
|
||||
case _:
|
||||
pass
|
||||
case "d":
|
||||
match method:
|
||||
case "1":
|
||||
result, data_table = bu.binary_division_method_1(first_register, second_register)
|
||||
print(f"\nDivision (method 1):\n{bu.format_device_state_table(data_table)}\nResult: {result}")
|
||||
operation, method = "", ""
|
||||
case "2":
|
||||
result, data_table = bu.binary_division_method_2(first_register, second_register)
|
||||
print(f"\nDivision (method 2):\n{bu.format_device_state_table(data_table)}\nResult: {result}")
|
||||
operation, method = "", ""
|
||||
case _:
|
||||
pass
|
||||
case "r":
|
||||
result, data_table = bu.binary_square_root(first_register)
|
||||
print(f"\nSquare root:\n{bu.format_device_state_table(data_table)}\nResult: {result}")
|
||||
operation, method = "", ""
|
||||
case "q":
|
||||
exit(0)
|
||||
|
||||
case _:
|
||||
pass
|
||||
|
||||
|
||||
def get_prompt_text(operation: any, method: any) -> str:
|
||||
response = "({} {})"
|
||||
|
||||
if operation:
|
||||
response += " {}"
|
||||
if operation and method:
|
||||
response += "/{}"
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def input_handler(first_register: bu.BasicRegister, second_register: bu.BasicRegister):
|
||||
global user_input, operation
|
||||
first_register, second_register = bu.align_registers(first_register, second_register)
|
||||
|
||||
print()
|
||||
print(first_register)
|
||||
print(second_register)
|
||||
|
||||
while True:
|
||||
prompt_text: str = get_prompt_text(operation, method).format(first_register, second_register, operation, method)
|
||||
# print()
|
||||
if operation == "":
|
||||
raw_user_input = input("Choose the operation:\n"
|
||||
"[a]ddition, [s]ubtraction, [m]ultiplication, [d]ivision, [r]oot, [q]uit\n" +
|
||||
prompt_text + " > ")
|
||||
elif operation == "m":
|
||||
raw_user_input = input("Choose method to use (1-4):\n" + prompt_text + " > ")
|
||||
elif operation == "d":
|
||||
raw_user_input = input("Choose method to use (1-2):\n" + prompt_text + " > ")
|
||||
|
||||
user_input = list(raw_user_input)
|
||||
|
||||
for symbol in user_input:
|
||||
process_command(symbol)
|
||||
perform_operation(first_register, second_register)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
reg1: bu.BasicRegister = bu.BasicRegister(bu.get_memory("first operand"))
|
||||
reg2: bu.BasicRegister = bu.BasicRegister(bu.get_memory("second operand"))
|
||||
|
||||
# TODO live-swapping of registers!!!
|
||||
|
||||
input_handler(reg1, reg2)
|
|
@ -0,0 +1,266 @@
|
|||
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, Clone)]
|
||||
pub struct BasicRegister {
|
||||
/// A [VecDeque] 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_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)
|
||||
}
|
||||
|
||||
BasicRegister::new(shifted_memory)
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
||||
/// 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: [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 {
|
||||
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(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
mod bit_utilities;
|
||||
|
||||
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 = 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…
Reference in New Issue