Math (Bits)
bit_not()¶
Return NOT(bit) for a bit expression.
This cell verifies the bit_not function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
Aliases: bnot can also be used equivalently.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import bit_not
def test_bit_not(bit):
import numpy as np
res = bit_not(bit)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_bit_not, {'bit': 'encrypted'})
inputset = [(0,), (1,)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = bit_not(inp[0])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "bit_not: all inputs were skipped — test is broken"
print(f"bit_not tests passed! ({_successes}/{len(inputset)})")
bit_and()¶
Return left AND right for bit expressions.
This cell verifies the bit_and function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
Aliases: band can also be used equivalently.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import bit_and
def test_bit_and(left, right):
import numpy as np
res = bit_and(left, right)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_bit_and, {'left': 'encrypted', 'right': 'encrypted'})
inputset = [(0, 0), (0, 1), (1, 0), (1, 1)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = bit_and(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "bit_and: all inputs were skipped — test is broken"
print(f"bit_and tests passed! ({_successes}/{len(inputset)})")
bit_or()¶
Return left OR right for bit expressions.
This cell verifies the bit_or function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
Aliases: bor can also be used equivalently.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import bit_or
def test_bit_or(left, right):
import numpy as np
res = bit_or(left, right)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_bit_or, {'left': 'encrypted', 'right': 'encrypted'})
inputset = [(0, 0), (0, 1), (1, 0), (1, 1)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = bit_or(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "bit_or: all inputs were skipped — test is broken"
print(f"bit_or tests passed! ({_successes}/{len(inputset)})")
bit_xor()¶
Return left XOR right for bit expressions.
This cell verifies the bit_xor function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
Aliases: bxor can also be used equivalently.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import bit_xor
def test_bit_xor(left, right):
import numpy as np
res = bit_xor(left, right)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_bit_xor, {'left': 'encrypted', 'right': 'encrypted'})
inputset = [(0, 0), (0, 1), (1, 0), (1, 1)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = bit_xor(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "bit_xor: all inputs were skipped — test is broken"
print(f"bit_xor tests passed! ({_successes}/{len(inputset)})")
bit_select()¶
Return when_one if control is 1, otherwise when_zero.
This cell verifies the bit_select function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
Aliases: bsel can also be used equivalently.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import bit_select
def test_bit_select(control, when_one, when_zero):
import numpy as np
res = bit_select(control, when_one, when_zero)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_bit_select, {'control': 'encrypted', 'when_one': 'encrypted', 'when_zero': 'encrypted'})
inputset = [(0, 0, 0), (0, 1, 0), (1, 0, 1), (1, 1, 1), (0, 1, 1)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = bit_select(inp[0], inp[1], inp[2])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "bit_select: all inputs were skipped — test is broken"
print(f"bit_select tests passed! ({_successes}/{len(inputset)})")
full_adder_bit()¶
Return (sum_bit, carry_out) for one full-adder stage.
This cell verifies the full_adder_bit function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
Aliases: fadd_bit can also be used equivalently.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import full_adder_bit
def test_full_adder_bit(left, right, carry_in):
import numpy as np
res = full_adder_bit(left, right, carry_in)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_full_adder_bit, {'left': 'encrypted', 'right': 'encrypted', 'carry_in': 'encrypted'})
inputset = [(0, 0, 0), (0, 1, 0), (1, 0, 1), (1, 1, 1), (0, 1, 1)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = full_adder_bit(inp[0], inp[1], inp[2])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "full_adder_bit: all inputs were skipped — test is broken"
print(f"full_adder_bit tests passed! ({_successes}/{len(inputset)})")
full_subtractor_bit()¶
Return (difference_bit, borrow_out) for one full-subtractor stage.
This cell verifies the full_subtractor_bit function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
Aliases: fsub_bit can also be used equivalently.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import full_subtractor_bit
def test_full_subtractor_bit(left, right, borrow_in):
import numpy as np
res = full_subtractor_bit(left, right, borrow_in)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_full_subtractor_bit, {'left': 'encrypted', 'right': 'encrypted', 'borrow_in': 'encrypted'})
inputset = [(0, 0, 0), (0, 1, 0), (1, 0, 1), (1, 1, 1), (0, 1, 1)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = full_subtractor_bit(inp[0], inp[1], inp[2])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "full_subtractor_bit: all inputs were skipped — test is broken"
print(f"full_subtractor_bit tests passed! ({_successes}/{len(inputset)})")
bit_or_many()¶
Return the OR-reduction of a bit iterable with higher performance.
This cell verifies the bit_or_many function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import bit_or_many
def test_bit_or_many(bits):
import numpy as np
res = bit_or_many(bits)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_bit_or_many, {'bits': 'encrypted'})
inputset = [([0, 1, 0],), ([1, 1, 1],), ([0, 0, 0],)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = bit_or_many(inp[0])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "bit_or_many: all inputs were skipped — test is broken"
print(f"bit_or_many tests passed! ({_successes}/{len(inputset)})")
bit_and_many()¶
Return the AND-reduction of a bit iterable with higher performance.
This cell verifies the bit_and_many function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import bit_and_many
def test_bit_and_many(bits):
import numpy as np
res = bit_and_many(bits)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_bit_and_many, {'bits': 'encrypted'})
inputset = [([0, 1, 0],), ([1, 1, 1],), ([0, 0, 0],)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = bit_and_many(inp[0])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "bit_and_many: all inputs were skipped — test is broken"
print(f"bit_and_many tests passed! ({_successes}/{len(inputset)})")
bit_xor_many()¶
Return the XOR-reduction of a bit iterable with higher performance.
This cell verifies the bit_xor_many function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import bit_xor_many
def test_bit_xor_many(bits):
import numpy as np
res = bit_xor_many(bits)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_bit_xor_many, {'bits': 'encrypted'})
inputset = [([0, 1, 0],), ([1, 1, 1],), ([0, 0, 0],)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = bit_xor_many(inp[0])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "bit_xor_many: all inputs were skipped — test is broken"
print(f"bit_xor_many tests passed! ({_successes}/{len(inputset)})")
integer_to_bits()¶
Return little-endian bits of an unsigned integer expression.
This cell verifies the integer_to_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import integer_to_bits
def test_integer_to_bits(value):
import numpy as np
res = integer_to_bits(value, 4)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_integer_to_bits, {'value': 'encrypted'})
inputset = [(2,), (-2,), (0,), (1,)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = integer_to_bits(inp[0], 4)
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "integer_to_bits: all inputs were skipped — test is broken"
print(f"integer_to_bits tests passed! ({_successes}/{len(inputset)})")
bits_to_unsigned()¶
Convert little-endian bits to an unsigned integer expression.
This cell verifies the bits_to_unsigned function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import bits_to_unsigned
def test_bits_to_unsigned(bits):
import numpy as np
res = bits_to_unsigned(bits)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_bits_to_unsigned, {'bits': 'encrypted'})
inputset = [(0,), (1,)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = bits_to_unsigned(inp[0])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "bits_to_unsigned: all inputs were skipped — test is broken"
print(f"bits_to_unsigned tests passed! ({_successes}/{len(inputset)})")
unsigned_to_bits() (Helper)¶
Demonstrates the unsigned_to_bits function. This is a client-side (cleartext) helper function. It is not an FHE circuit and cannot be compiled with fhe.Compiler.
from concrete_fhe_toolkit.math.bits import unsigned_to_bits
clear_int = 5
bits = unsigned_to_bits(clear_int, width=4)
print(f'Unsigned integer {clear_int} to bits -> {bits}')
assert bits == (1, 0, 1, 0)
print('Conversion successful!')
twos_complement_bits() (Helper)¶
Demonstrates the twos_complement_bits function. This is a client-side (cleartext) helper function. It is not an FHE circuit and cannot be compiled with fhe.Compiler.
from concrete_fhe_toolkit.math.bits import twos_complement_bits
clear_int = -3
bits = twos_complement_bits(clear_int, width=4)
print(f'Two's complement integer {clear_int} to bits -> {bits}')
assert bits == (1, 0, 1, 1)
print('Conversion successful!')
sign_magnitude_to_twos_complement_bits()¶
Convert sign-magnitude bits to two's-complement bits.
This cell verifies the sign_magnitude_to_twos_complement_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import sign_magnitude_to_twos_complement_bits
def test_sign_magnitude_to_twos_complement_bits(magnitude_bits, sign_bit):
import numpy as np
res = sign_magnitude_to_twos_complement_bits(magnitude_bits, sign_bit, 4)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_sign_magnitude_to_twos_complement_bits, {'magnitude_bits': 'encrypted', 'sign_bit': 'encrypted'})
inputset = [([0, 1, 0], 1), ([1, 1, 1], 0), ([0, 0, 0], 0)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = sign_magnitude_to_twos_complement_bits(inp[0], inp[1], 4)
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "sign_magnitude_to_twos_complement_bits: all inputs were skipped — test is broken"
print(f"sign_magnitude_to_twos_complement_bits tests passed! ({_successes}/{len(inputset)})")
twos_complement_add_bits()¶
Add two two's-complement bit lists modulo 2**width.
This cell verifies the twos_complement_add_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import twos_complement_add_bits
def test_twos_complement_add_bits(left_bits, right_bits):
import numpy as np
res = twos_complement_add_bits(left_bits, right_bits, 4)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_twos_complement_add_bits, {'left_bits': 'encrypted', 'right_bits': 'encrypted'})
inputset = [([0, 1, 0], [1, 0, 1]), ([1, 1, 1], [1, 1, 1]), ([0, 0, 0], [0, 0, 0])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = twos_complement_add_bits(inp[0], inp[1], 4)
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "twos_complement_add_bits: all inputs were skipped — test is broken"
print(f"twos_complement_add_bits tests passed! ({_successes}/{len(inputset)})")
twos_complement_multiply_by_constant_bits()¶
Multiply two's-complement bits by a nonnegative clear integer.
This cell verifies the twos_complement_multiply_by_constant_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import twos_complement_multiply_by_constant_bits
def test_twos_complement_multiply_by_constant_bits(signed_bits):
import numpy as np
res = twos_complement_multiply_by_constant_bits(signed_bits, 2, 1)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_twos_complement_multiply_by_constant_bits, {'signed_bits': 'encrypted'})
inputset = [([0, 1, 0],), ([1, 1, 1],), ([0, 0, 0],)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = twos_complement_multiply_by_constant_bits(inp[0], 2, 1)
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "twos_complement_multiply_by_constant_bits: all inputs were skipped — test is broken"
print(f"twos_complement_multiply_by_constant_bits tests passed! ({_successes}/{len(inputset)})")
multiply_bits()¶
Multiply two two's-complement bit lists.
This cell verifies the multiply_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import multiply_bits
def test_multiply_bits(left_bits, right_bits):
import numpy as np
res = multiply_bits(left_bits, right_bits, 4)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_multiply_bits, {'left_bits': 'encrypted', 'right_bits': 'encrypted'})
inputset = [([0, 1, 0], [1, 0, 1]), ([1, 1, 1], [1, 1, 1]), ([0, 0, 0], [0, 0, 0])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = multiply_bits(inp[0], inp[1], 4)
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "multiply_bits: all inputs were skipped — test is broken"
print(f"multiply_bits tests passed! ({_successes}/{len(inputset)})")
shift_left_bits()¶
Logical left shift by a public amount; output keeps the input width.
This cell verifies the shift_left_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import shift_left_bits
def test_shift_left_bits(bits):
import numpy as np
res = shift_left_bits(bits, 1)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_shift_left_bits, {'bits': 'encrypted'})
inputset = [([0, 1, 0],), ([1, 1, 1],), ([0, 0, 0],)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = shift_left_bits(inp[0], 1)
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "shift_left_bits: all inputs were skipped — test is broken"
print(f"shift_left_bits tests passed! ({_successes}/{len(inputset)})")
shift_right_bits()¶
Right shift by a public amount; arithmetic=True sign-extends from the MSB.
This cell verifies the shift_right_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import shift_right_bits
def test_shift_right_bits(bits):
import numpy as np
res = shift_right_bits(bits, 1, arithmetic=1)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_shift_right_bits, {'bits': 'encrypted'})
inputset = [([0, 1, 0],), ([1, 1, 1],), ([0, 0, 0],)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = shift_right_bits(inp[0], 1, arithmetic=1)
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "shift_right_bits: all inputs were skipped — test is broken"
print(f"shift_right_bits tests passed! ({_successes}/{len(inputset)})")
rotate_left_bits()¶
Rotate toward the MSB by a public amount (little-endian bit lists).
This cell verifies the rotate_left_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import rotate_left_bits
def test_rotate_left_bits(bits):
import numpy as np
res = rotate_left_bits(bits, 1)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_rotate_left_bits, {'bits': 'encrypted'})
inputset = [([0, 1, 0],), ([1, 1, 1],), ([0, 0, 0],)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = rotate_left_bits(inp[0], 1)
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "rotate_left_bits: all inputs were skipped — test is broken"
print(f"rotate_left_bits tests passed! ({_successes}/{len(inputset)})")
rotate_right_bits()¶
Rotate toward the LSB by a public amount (little-endian bit lists).
This cell verifies the rotate_right_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import rotate_right_bits
def test_rotate_right_bits(bits):
import numpy as np
res = rotate_right_bits(bits, 1)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_rotate_right_bits, {'bits': 'encrypted'})
inputset = [([0, 1, 0],), ([1, 1, 1],), ([0, 0, 0],)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = rotate_right_bits(inp[0], 1)
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "rotate_right_bits: all inputs were skipped — test is broken"
print(f"rotate_right_bits tests passed! ({_successes}/{len(inputset)})")
popcount_bits()¶
Return the number of set bits as an integer expression (tournament sum).
This cell verifies the popcount_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import popcount_bits
def test_popcount_bits(bits):
import numpy as np
res = popcount_bits(bits)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_popcount_bits, {'bits': 'encrypted'})
inputset = [([0, 1, 0],), ([1, 1, 1],), ([0, 0, 0],)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = popcount_bits(inp[0])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "popcount_bits: all inputs were skipped — test is broken"
print(f"popcount_bits tests passed! ({_successes}/{len(inputset)})")
parity_bits()¶
Return the XOR-parity (1 when an odd number of bits are set).
This cell verifies the parity_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import parity_bits
def test_parity_bits(bits):
import numpy as np
res = parity_bits(bits)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_parity_bits, {'bits': 'encrypted'})
inputset = [([0, 1, 0],), ([1, 1, 1],), ([0, 0, 0],)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = parity_bits(inp[0])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "parity_bits: all inputs were skipped — test is broken"
print(f"parity_bits tests passed! ({_successes}/{len(inputset)})")
bit_length_bits()¶
Return the bit length (index of the highest set bit plus one, 0 for zero).
This cell verifies the bit_length_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import bit_length_bits
def test_bit_length_bits(bits):
import numpy as np
res = bit_length_bits(bits)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_bit_length_bits, {'bits': 'encrypted'})
inputset = [([0, 1, 0],), ([1, 1, 1],), ([0, 0, 0],)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = bit_length_bits(inp[0])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "bit_length_bits: all inputs were skipped — test is broken"
print(f"bit_length_bits tests passed! ({_successes}/{len(inputset)})")
unsigned_compare_bits()¶
Return (is_less, is_equal) bits for two little-endian unsigned bit lists.
This cell verifies the unsigned_compare_bits function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.math.bits import unsigned_compare_bits
def test_unsigned_compare_bits(left_bits, right_bits):
import numpy as np
res = unsigned_compare_bits(left_bits, right_bits)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_unsigned_compare_bits, {'left_bits': 'encrypted', 'right_bits': 'encrypted'})
inputset = [([0, 1, 0], [1, 0, 1]), ([1, 1, 1], [1, 1, 1]), ([0, 0, 0], [0, 0, 0])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = unsigned_compare_bits(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "unsigned_compare_bits: all inputs were skipped — test is broken"
print(f"unsigned_compare_bits tests passed! ({_successes}/{len(inputset)})")