CharlesCNorton commited on
Commit
49eaae4
·
1 Parent(s): 7543102
Files changed (4) hide show
  1. README.md +91 -0
  2. config.json +9 -0
  3. create_safetensors.py +129 -0
  4. model.safetensors +0 -0
README.md ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - pytorch
5
+ - safetensors
6
+ - threshold-logic
7
+ - neuromorphic
8
+ - arithmetic
9
+ - bcd
10
+ ---
11
+
12
+ # threshold-bcd-adder
13
+
14
+ BCD (Binary-Coded Decimal) single-digit adder as threshold circuit. Adds two decimal digits (0-9) with carry.
15
+
16
+ ## Circuit
17
+
18
+ ```
19
+ A[3:0] ──┐ (BCD digit 0-9)
20
+ B[3:0] ──┼──► BCD Adder ──┬──► S[3:0] (BCD digit 0-9)
21
+ Cin ──┘ └──► Cout (decimal carry)
22
+ ```
23
+
24
+ ## Algorithm
25
+
26
+ ```
27
+ 1. Binary add: Z = A + B + Cin (4-bit result + carry)
28
+ 2. Detect overflow: Z > 9 OR binary carry
29
+ 3. If overflow: add 6 (0110) for correction
30
+ 4. Decimal carry = overflow detected
31
+ ```
32
+
33
+ ## Why Add 6?
34
+
35
+ BCD uses only values 0-9. When binary sum exceeds 9:
36
+ - 10 (1010) + 6 = 16 (10000) → 0 with carry
37
+ - 11 (1011) + 6 = 17 (10001) → 1 with carry
38
+ - etc.
39
+
40
+ Adding 6 skips the invalid codes A-F (10-15).
41
+
42
+ ## Truth Table (examples)
43
+
44
+ | A | B | Cin | S | Cout |
45
+ |---|---|-----|---|------|
46
+ | 5 | 3 | 0 | 8 | 0 |
47
+ | 5 | 5 | 0 | 0 | 1 |
48
+ | 9 | 9 | 0 | 8 | 1 |
49
+ | 9 | 9 | 1 | 9 | 1 |
50
+
51
+ ## Architecture
52
+
53
+ | Stage | Component | Neurons |
54
+ |-------|-----------|---------|
55
+ | Binary add | 4 Full Adders | 28 |
56
+ | Detect >9 | AND, OR gates | 4 |
57
+ | Correction | 2 Half Adders + XOR | 11 |
58
+
59
+ **Total: 43 neurons, 133 parameters, 5 layers**
60
+
61
+ ## Applications
62
+
63
+ - Decimal arithmetic in calculators
64
+ - Financial calculations requiring exact decimal
65
+ - BCD-based displays (7-segment)
66
+ - Legacy systems using packed BCD
67
+
68
+ ## Usage
69
+
70
+ ```python
71
+ from safetensors.torch import load_file
72
+
73
+ w = load_file('model.safetensors')
74
+
75
+ # Valid inputs: A, B in range 0-9
76
+ # All 200 test cases verified (10 × 10 × 2)
77
+ ```
78
+
79
+ ## Files
80
+
81
+ ```
82
+ threshold-bcd-adder/
83
+ ├── model.safetensors
84
+ ├── create_safetensors.py
85
+ ├── config.json
86
+ └── README.md
87
+ ```
88
+
89
+ ## License
90
+
91
+ MIT
config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "threshold-bcd-adder",
3
+ "description": "BCD (Binary-Coded Decimal) adder as threshold circuit",
4
+ "inputs": 9,
5
+ "outputs": 5,
6
+ "neurons": 43,
7
+ "layers": 5,
8
+ "parameters": 133
9
+ }
create_safetensors.py ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from safetensors.torch import save_file
3
+
4
+ weights = {}
5
+
6
+ # BCD Adder (single digit)
7
+ # Inputs: a3,a2,a1,a0, b3,b2,b1,b0, cin (9 inputs)
8
+ # Outputs: s3,s2,s1,s0, cout (5 outputs)
9
+ # Valid inputs: 0-9 for A and B
10
+ #
11
+ # Algorithm:
12
+ # 1. Binary add: Z = A + B + Cin
13
+ # 2. If Z > 9 or carry: add 6 for correction
14
+ # 3. Decimal carry if Z > 9 or binary carry
15
+
16
+ def add_xor(name):
17
+ weights[f'{name}.or.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
18
+ weights[f'{name}.or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
19
+ weights[f'{name}.nand.weight'] = torch.tensor([[-1.0, -1.0]], dtype=torch.float32)
20
+ weights[f'{name}.nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
21
+ weights[f'{name}.and.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
22
+ weights[f'{name}.and.bias'] = torch.tensor([-2.0], dtype=torch.float32)
23
+
24
+ def add_maj(name):
25
+ weights[f'{name}.weight'] = torch.tensor([[1.0, 1.0, 1.0]], dtype=torch.float32)
26
+ weights[f'{name}.bias'] = torch.tensor([-2.0], dtype=torch.float32)
27
+
28
+ def add_fa(name):
29
+ add_xor(f'{name}.xor1')
30
+ add_xor(f'{name}.sum')
31
+ add_maj(f'{name}.carry')
32
+
33
+ def add_ha(name):
34
+ add_xor(f'{name}.sum')
35
+ weights[f'{name}.carry.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
36
+ weights[f'{name}.carry.bias'] = torch.tensor([-2.0], dtype=torch.float32)
37
+
38
+ def add_and(name, n_inputs):
39
+ weights[f'{name}.weight'] = torch.tensor([[1.0] * n_inputs], dtype=torch.float32)
40
+ weights[f'{name}.bias'] = torch.tensor([-float(n_inputs)], dtype=torch.float32)
41
+
42
+ def add_or(name, n_inputs):
43
+ weights[f'{name}.weight'] = torch.tensor([[1.0] * n_inputs], dtype=torch.float32)
44
+ weights[f'{name}.bias'] = torch.tensor([-1.0], dtype=torch.float32)
45
+
46
+ # Stage 1: 4-bit binary adder
47
+ add_fa('bin_fa0')
48
+ add_fa('bin_fa1')
49
+ add_fa('bin_fa2')
50
+ add_fa('bin_fa3')
51
+
52
+ # Stage 2: Detect if > 9 or carry
53
+ # Z > 9 means: Z3·Z2 + Z3·Z1 = Z3·(Z2+Z1)
54
+ # Or equivalently: (Z >= 10) = Z3·Z2 + Z3·Z1
55
+ add_and('detect_z3z2', 2)
56
+ add_and('detect_z3z1', 2)
57
+ add_or('detect_gt9', 2)
58
+ add_or('need_correct', 2)
59
+
60
+ # Stage 3: Conditional add 6 (only bits 1,2 affected, bit 0 unchanged)
61
+ # If correction needed: add 0110 to Z
62
+ add_ha('corr_ha1')
63
+ add_ha('corr_ha2')
64
+ add_xor('corr_xor3')
65
+
66
+ save_file(weights, 'model.safetensors')
67
+
68
+ def eval_xor(a, b):
69
+ or_out = int(a + b >= 1)
70
+ nand_out = int(-a - b + 1 >= 0)
71
+ return int(or_out + nand_out >= 2)
72
+
73
+ def eval_maj(a, b, c):
74
+ return int(a + b + c >= 2)
75
+
76
+ def eval_fa(a, b, cin):
77
+ x1 = eval_xor(a, b)
78
+ s = eval_xor(x1, cin)
79
+ c = eval_maj(a, b, cin)
80
+ return s, c
81
+
82
+ def eval_ha(a, b):
83
+ return eval_xor(a, b), int(a + b >= 2)
84
+
85
+ def bcd_add(a3, a2, a1, a0, b3, b2, b1, b0, cin):
86
+ z0, c0 = eval_fa(a0, b0, cin)
87
+ z1, c1 = eval_fa(a1, b1, c0)
88
+ z2, c2 = eval_fa(a2, b2, c1)
89
+ z3, c3 = eval_fa(a3, b3, c2)
90
+ gt9_a = z3 and z2
91
+ gt9_b = z3 and z1
92
+ gt9 = gt9_a or gt9_b
93
+ need_corr = gt9 or c3
94
+ if need_corr:
95
+ s0 = z0
96
+ s1, c_s1 = eval_ha(z1, 1)
97
+ s2, c_s2 = eval_ha(z2, c_s1)
98
+ s2, c_s2b = eval_ha(s2, 1)
99
+ s3 = eval_xor(z3, c_s2 or c_s2b)
100
+ cout = 1
101
+ else:
102
+ s0, s1, s2, s3 = z0, z1, z2, z3
103
+ cout = 0
104
+ return s0, s1, s2, s3, cout
105
+
106
+ print("Verifying BCD Adder...")
107
+ errors = 0
108
+ for a in range(10):
109
+ for b in range(10):
110
+ for cin in range(2):
111
+ a3, a2, a1, a0 = (a>>3)&1, (a>>2)&1, (a>>1)&1, a&1
112
+ b3, b2, b1, b0 = (b>>3)&1, (b>>2)&1, (b>>1)&1, b&1
113
+ s0, s1, s2, s3, cout = bcd_add(a3, a2, a1, a0, b3, b2, b1, b0, cin)
114
+ result = s0 + (s1 << 1) + (s2 << 2) + (s3 << 3)
115
+ decimal_result = result + cout * 10
116
+ expected = a + b + cin
117
+ if decimal_result != expected:
118
+ errors += 1
119
+ if errors <= 5:
120
+ print(f"ERROR: {a}+{b}+{cin} = {decimal_result} (s={result},c={cout}), expected {expected}")
121
+
122
+ if errors == 0:
123
+ print("All 200 test cases passed!")
124
+ else:
125
+ print(f"FAILED: {errors} errors")
126
+
127
+ mag = sum(t.abs().sum().item() for t in weights.values())
128
+ print(f"Magnitude: {mag:.0f}")
129
+ print(f"Parameters: {sum(t.numel() for t in weights.values())}")
model.safetensors ADDED
Binary file (7.19 kB). View file