mirror of
https://github.com/zama-ai/concrete.git
synced 2026-02-09 03:55:04 -05:00
doc: write table lookup and working with floating points tutorials
This commit is contained in:
@@ -1,3 +1,77 @@
|
||||
# Table Lookup
|
||||
|
||||
Umut to do: #314
|
||||
In this tutorial, we are going to go over the ways to perform table lookups in **concrete**. Please read [Compiling and Executing](../howto/COMPILING_AND_EXECUTING.md) 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:
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
```python
|
||||
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](./WORKING_WITH_FLOATING_POINTS.md).
|
||||
|
||||
Here is an example function that results in fused table lookup:
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
```python
|
||||
table = LookupTable([50, 92, 95, 57, 12, 2, 36, 82])
|
||||
```
|
||||
|
||||
which is calculated by:
|
||||
|
||||
```python
|
||||
[(50 * (np.sin(x) + 1)).astype(np.uint32) for x in range(2 ** 3)]
|
||||
```
|
||||
|
||||
@@ -1,3 +1,68 @@
|
||||
# Working With Floating Points
|
||||
|
||||
Umut to do: #313
|
||||
## An example
|
||||
|
||||
```python
|
||||
def f(x):
|
||||
np.fabs(100 * (2 * np.sin(x) * np.cos(x))).astype(np.uint32) # astype is to go back to integer world
|
||||
```
|
||||
|
||||
where
|
||||
|
||||
- `x = EncryptedScalar(UnsignedInteger(bits))`
|
||||
|
||||
results in
|
||||
|
||||
```python
|
||||
engine.run(3) == 27
|
||||
engine.run(0) == 0
|
||||
engine.run(1) == 90
|
||||
engine.run(10) == 91
|
||||
engine.run(60) == 58
|
||||
```
|
||||
|
||||
## Supported operations
|
||||
|
||||
The following operations are supported in the latest release, and we'll add more operations in the upcoming releases.
|
||||
|
||||
- np.arccos
|
||||
- np.arccosh
|
||||
- np.arcsin
|
||||
- np.arcsinh
|
||||
- np.arctan
|
||||
- np.arctanh
|
||||
- np.cbrt
|
||||
- np.ceil
|
||||
- np.cos
|
||||
- np.cosh
|
||||
- np.deg2rad
|
||||
- np.degrees
|
||||
- np.exp
|
||||
- np.exp2
|
||||
- np.expm1
|
||||
- np.fabs
|
||||
- np.floor
|
||||
- np.log
|
||||
- np.log10
|
||||
- np.log1p
|
||||
- np.log2
|
||||
- np.rad2deg
|
||||
- np.radians
|
||||
- np.rint
|
||||
- np.sin
|
||||
- np.sinh
|
||||
- np.spacing
|
||||
- np.sqrt
|
||||
- np.tan
|
||||
- np.tanh
|
||||
- np.trunc
|
||||
|
||||
## Limitations
|
||||
|
||||
Floating point support in **concrete** is very limited for the time being. They can't appear on inputs, or they can't be outputs. However, they can be used in intermediate results. Unfortunately, there are limitations on that front as well.
|
||||
|
||||
This biggest one is that, because floating point operations are fused into table lookups with a single unsigned integer input and single unsigned integer output, only univariate portion of code can be replaced with table lookups, which means multivariate portions cannot be compiled.
|
||||
|
||||
To give a precise example, `100 - np.fabs(50 * (np.sin(x) + np.sin(y)))` cannot be compiled because the floating point part depends on both `x` and `y` (i.e., it cannot be rewritten in the form `100 - table[z]` for a `z` that could be computed easily from `x` and `y`).
|
||||
|
||||
To dive into implementation details, you may refer to [Fusing Floating Point Operations](../../dev/explanation/FLOAT-FUSING.md) document.
|
||||
|
||||
Reference in New Issue
Block a user