Files
concrete/docs/user/tutorial/TABLE_LOOKUP.md

2.0 KiB

Table Lookup

In this tutorial, we are going to go over the ways to perform table lookups in Concrete. Please read Compiling and Executing before reading further to see how you can compile the functions below.

Direct table lookup

Concrete provides a special class to allow direct table lookups. Here is how to import and use it:

from concrete.common.extensions.table import LookupTable

table = LookupTable([2, 1, 3, 0])

def f(x):
    return table[x]

where

  • x = EncryptedScalar(UnsignedInteger(2))

results in

engine.run(0) == 2
engine.run(1) == 1
engine.run(2) == 3
engine.run(3) == 0

Fused table lookup

Direct tables are tedious to prepare by hand. When possible, Concrete fuses the floating point operations into a single table lookup automatically. There are some limitations on fusing operations, which you can learn more about on the next tutorial, Working With Floating Points.

Here is an example function that results in fused table lookup:

def f(x):
    return 127 - (50 * (np.sin(x) + 1)).astype(np.uint32) # astype is to go back to integer world

where

  • x = EncryptedScalar(UnsignedInteger(3))

results in

engine.run(0) == 77
engine.run(1) == 35
engine.run(2) == 32
engine.run(3) == 70
engine.run(4) == 115
engine.run(5) == 125
engine.run(6) == 91
engine.run(7) == 45

Initially, the function is converted to this operation graph

and after floating point operations are fused, we get the following operation graph

Internally, it uses the following lookup table

table = LookupTable([50, 92, 95, 57, 12, 2, 36, 82])

which is calculated by:

[(50 * (np.sin(x) + 1)).astype(np.uint32) for x in range(2 ** 3)]