ffs8(x7..x0) -> (f3, f2, f1, f0)
position = 8*f3 + 4*f2 + 2*f1 + f0
if input = 0: position = 0
if input != 0: position = CTZ(input) + 1
FFS is 1-indexed: the first bit (x0) is position 1, not 0.
Truth Table (selected)
Input (hex)
Binary
FFS
f3 f2 f1 f0
Meaning
0x00
00000000
0
0 0 0 0
No bits set
0x01
00000001
1
0 0 0 1
Bit 0 is first
0x02
00000010
2
0 0 1 0
Bit 1 is first
0x04
00000100
3
0 0 1 1
Bit 2 is first
0x08
00001000
4
0 1 0 0
Bit 3 is first
0x10
00010000
5
0 1 0 1
Bit 4 is first
0x20
00100000
6
0 1 1 0
Bit 5 is first
0x40
01000000
7
0 1 1 1
Bit 6 is first
0x80
10000000
8
1 0 0 0
Bit 7 is first
0xFF
11111111
1
0 0 0 1
Bit 0 is first
Relationship to CTZ
if (input == 0):
FFS = 0
else:
FFS = CTZ + 1
FFS and CTZ are closely related:
CTZ returns 0-7 for positions, 8 for zero input
FFS returns 1-8 for positions, 0 for zero input
Mechanism
Position detectors: Same as CTZ - detect where first 1 appears from LSB
Signal
Fires when
p0
x0 = 1
p1
x0 = 0, x1 = 1
p2
x0 = x1 = 0, x2 = 1
...
...
p7
x0..x6 = 0, x7 = 1
Output encoding: Direct binary encoding of position + 1
f0 = p0 OR p2 OR p4 OR p6 (positions 0,2,4,6 → FFS 1,3,5,7)
f1 = p1 OR p2 OR p5 OR p6 (positions 1,2,5,6 → FFS 2,3,6,7)
f2 = p3 OR p4 OR p5 OR p6 (positions 3,4,5,6 → FFS 4,5,6,7)
f3 = p7 (position 7 → FFS 8)
Parameters
Inputs
8
Outputs
4
Neurons
12
Layers
2
Parameters
76
Magnitude
48
Usage
python
1from safetensors.torch import load_file
2import torch
34w = load_file('model.safetensors')56defffs8(bits):7# bits = [x0, x1, ..., x7] (LSB first)8 inp = torch.tensor([float(b)for b in bits])9# ... (see model.py for full implementation)1011# Examples12print(ffs8([1,0,0,0,0,0,0,0]))# 1 (first bit set is position 0)13print(ffs8([0,0,1,0,0,0,0,0]))# 3 (first bit set is position 2)14print(ffs8([0,0,0,0,0,0,0,0]))# 0 (no bits set)