Subtracts three 1-bit inputs (a, b, borrow_in), producing difference and borrow_out. The subtraction counterpart to the full adder.
a b
│ │
└───┬───┘
▼
┌─────────┐
│ HS1 │ First half subtractor
└─────────┘
│ │
d1 b1
│ \
│ bin \
└──┬──┘ \
▼ \
┌─────────┐ \
│ HS2 │ │
└─────────┘ │
│ │ │
diff b2 │
│ │
└──┬───┘
▼
┌──────┐
│ OR │
└──────┘
│
▼
bout
x y
│ │
├───┬───┤
│ │ │
▼ │ ▼
┌──────┐│┌──────┐ ┌───────┐
│ OR │││ NAND │ │ ¬x ∧ y│
│w:1,1 │││w:-1,-1│ │w:-1,1 │
│b: -1 │││b: +1 │ │b: -1 │
└──────┘│└──────┘ └───────┘
│ │ │ │
└───┼───┘ │
▼ │
┌──────┐ │
│ AND │ │
└──────┘ │
│ │
▼ ▼
diff borrow
d1, b1 = HalfSubtractor(a, b)
diff, b2 = HalfSubtractor(d1, bin)
bout = OR(b1, b2)
A borrow propagates if either half subtractor produces one.
The only structural difference: the borrow circuit uses NOT(a) AND b instead of AND.
1from safetensors.torch import load_file
2import torch
3
4w = load_file('model.safetensors')
5
6def full_subtractor(a, b, bin_in):
7 inp = torch.tensor([float(a), float(b)])
8
9 # HS1
10 hs1_l1 = (inp @ w['hs1.xor.layer1.weight'].T + w['hs1.xor.layer1.bias'] >= 0).float()
11 d1 = (hs1_l1 @ w['hs1.xor.layer2.weight'].T + w['hs1.xor.layer2.bias'] >= 0).float().item()
12 b1 = (inp @ w['hs1.borrow.weight'].T + w['hs1.borrow.bias'] >= 0).float().item()
13
14 # HS2
15 inp2 = torch.tensor([d1, float(bin_in)])
16 hs2_l1 = (inp2 @ w['hs2.xor.layer1.weight'].T + w['hs2.xor.layer1.bias'] >= 0).float()
17 diff = int((hs2_l1 @ w['hs2.xor.layer2.weight'].T + w['hs2.xor.layer2.bias'] >= 0).item())
18 b2 = (inp2 @ w['hs2.borrow.weight'].T + w['hs2.borrow.bias'] >= 0).float().item()
19
20 # Final borrow
21 bout = int((torch.tensor([b1, b2]) @ w['bout.weight'].T + w['bout.bias'] >= 0).item())
22
23 return diff, bout
threshold-fullsubtractor/
├── model.safetensors
├── model.py
├── config.json
└── README.md