Returns a tensor that contains the addition of a tensor of encrypted integers and a tensor of clear integers.
Performs an addition following the broadcasting rules between a tensor of encrypted integers and a tensor of clear integers. The width of the clear integers must be less than or equal to the width of encrypted integers.
Examples:
// Returns the term-by-term addition of `%a0` with `%a1`
"FHELinalg.add_eint_int"(%a0, %a1) : (tensor<4x!FHE.eint<4>>, tensor<4xi5>) -> tensor<4x!FHE.eint<4>>
// Returns the term-by-term addition of `%a0` with `%a1`, where dimensions equal to one are stretched.
"FHELinalg.add_eint_int"(%a0, %a1) : (tensor<4x1x4x!FHE.eint<4>>, tensor<1x4x4xi5>) -> tensor<4x4x4x!FHE.eint<4>>
// Returns the addition of a 3x3 matrix of encrypted integers and a 3x1 matrix (a column) of integers.
//
// [1,2,3] [1] [2,3,4]
// [4,5,6] + [2] = [6,7,8]
// [7,8,9] [3] [10,11,12]
//
// The dimension #1 of operand #2 is stretched as it is equal to 1.
"FHELinalg.add_eint_int"(%a0, %a1) : (tensor<3x3x!FHE.eint<4>>, tensor<3x1xi5>) -> tensor<3x3x!FHE.eint<4>>
// Returns the addition of a 3x3 matrix of encrypted integers and a 1x3 matrix (a line) of integers.
//
// [1,2,3] [2,4,6]
// [4,5,6] + [1,2,3] = [5,7,9]
// [7,8,9] [8,10,12]
//
// The dimension #2 of operand #2 is stretched as it is equal to 1.
"FHELinalg.add_eint_int"(%a0, %a1) : (tensor<3x3x!FHE.eint<4>>, tensor<1x3xi5>) -> tensor<3x3x!FHE.eint<4>>
// Same behavior as the previous one, but as the dimension #2 is missing of operand #2.
"FHELinalg.add_eint_int(%a0, %a1)" : (tensor<3x4x!FHE.eint<4>>, tensor<3xi5>) -> tensor<4x4x4x!FHE.eint<4>>
Returns a tensor that contains the addition of two tensor of encrypted integers.
Performs an addition following the broadcasting rules between two tensors of encrypted integers. The width of the encrypted integers must be equal.
Examples:
// Returns the term-by-term addition of `%a0` with `%a1`
"FHELinalg.add_eint"(%a0, %a1) : (tensor<4x!FHE.eint<4>>, tensor<4x!FHE.eint<4>>) -> tensor<4x!FHE.eint<4>>
// Returns the term-by-term addition of `%a0` with `%a1`, where dimensions equal to one are stretched.
"FHELinalg.add_eint"(%a0, %a1) : (tensor<4x1x4x!FHE.eint<4>>, tensor<1x4x4x!FHE.eint<4>>) -> tensor<4x4x4x!FHE.eint<4>>
// Returns the addition of a 3x3 matrix of encrypted integers and a 3x1 matrix (a column) of encrypted integers.
//
// [1,2,3] [1] [2,3,4]
// [4,5,6] + [2] = [6,7,8]
// [7,8,9] [3] [10,11,12]
//
// The dimension #1 of operand #2 is stretched as it is equal to 1.
"FHELinalg.add_eint"(%a0, %a1) : (tensor<3x3x!FHE.eint<4>>, tensor<3x1x!FHE.eint<4>>) -> tensor<3x3x!FHE.eint<4>>
// Returns the addition of a 3x3 matrix of encrypted integers and a 1x3 matrix (a line) of encrypted integers.
//
// [1,2,3] [2,4,6]
// [4,5,6] + [1,2,3] = [5,7,9]
// [7,8,9] [8,10,12]
//
// The dimension #2 of operand #2 is stretched as it is equal to 1.
"FHELinalg.add_eint"(%a0, %a1) : (tensor<3x3x!FHE.eint<4>>, tensor<1x3x!FHE.eint<4>>) -> tensor<3x3x!FHE.eint<4>>
// Same behavior as the previous one, but as the dimension #2 of operand #2 is missing.
"FHELinalg.add_eint"(%a0, %a1) : (tensor<3x3x!FHE.eint<4>>, tensor<3x!FHE.eint<4>>) -> tensor<3x3x!FHE.eint<4>>
Returns a tensor that contains the result of the lookup on a table.
For each encrypted index, performs a lookup table of clear integers.
// The result of this operation, is a tensor that contains the result of a lookup table.
// i.e. %res[i, ..., k] = %lut[%t[i, ..., k]]
%res = FHELinalg.apply_lookup_table(%t, %lut): tensor<DNx...xD1x!FHE.eint<$p>>, tensor<D2^$pxi64> -> tensor<DNx...xD1x!FHE.eint<$p>>
The %lut argument must be a tensor with one dimension, where its dimension is 2^p where p is the width of the encrypted integers.
Examples:
// Returns the lookup of 3x3 matrix of encrypted indices of with 2 on a table of size 4=2² of clear integers.
//
// [0,1,2] [1,3,5]
// [3,0,1] lut [1,3,5,7] = [7,1,3]
// [2,3,0] [5,7,1]
"FHELinalg.apply_lookup_table"(%t, %lut) : (tensor<3x3x!FHE.eint<2>>, tensor<4xi64>) -> tensor<3x3x!FHE.eint<3>>
Returns a tensor that contains the result of the lookup on a table, using a different lookup table for each element, specified by a map.
Performs for each encrypted index a lookup table of clear integers. Multiple lookup tables are passed, and the application of lookup tables is performed following the broadcasting rules. The precise lookup is specified by a map.
// The result of this operation, is a tensor that contains the result of the lookup on different tables.
// i.e. %res[i, ..., k] = %luts[ %map[i, ..., k] ][ %t[i, ..., k] ]
%res = FHELinalg.apply_mapped_lookup_table(%t, %luts, %map): tensor<DNx...xD1x!FHE.eint<$p>>, tensor<DM x ^$p>, tensor<DNx...xD1xindex> -> tensor<DNx...xD1x!FHE.eint<$p>>
Examples:
// Returns the lookup of 3x2 matrix of encrypted indices of width 2 on a vector of 2 tables of size 4=2^2 of clear integers.
//
// [0,1] [0, 1] = [1,2]
// [3,0] lut [[1,3,5,7], [0,2,4,6]] with [0, 1] = [7,0]
// [2,3] [0, 1] = [5,6]
"FHELinalg.apply_mapped_lookup_table"(%t, %luts, %map) : (tensor<3x2x!FHE.eint<2>>, tensor<2x4xi64>, tensor<3x2xindex>) -> tensor<3x2x!FHE.eint<3>>
Returns a tensor that contains the result of the lookup on a table, using a different lookup table for each element.
Performs for each encrypted index a lookup table of clear integers. Multiple lookup tables are passed, and the application of lookup tables is performed following the broadcasting rules.
// The result of this operation, is a tensor that contains the result of the lookup on different tables.
// i.e. %res[i, ..., k] = [ %luts[i][%t[i]], ..., %luts[k][%t[k]] ]
%res = FHELinalg.apply_multi_lookup_table(%t, %lut): tensor<DNx...xD1x!FHE.eint<$p>>, tensor<DMx...xD1xD2^$pxi64> -> tensor<DNx...xD1x!FHE.eint<$p>>
The %luts argument should be a tensor with M dimension, where the first M-1 dimensions are broadcastable with the N dimensions of the encrypted tensor, and where the last dimension dimension is equal to 2^p where p is the width of the encrypted integers.
Examples:
// Returns the lookup of 3x2 matrix of encrypted indices of width 2 on a vector of 2 tables of size 4=2² of clear integers.
// The tables are broadcasted along the first dimension of the tensor.
//
// [0,1] = [1,2]
// [3,0] lut [[1,3,5,7], [0,2,4,6]] = [7,0]
// [2,3] = [5,6]
"FHELinalg.apply_multi_lookup_table"(%t, %luts) : (tensor<3x2x!FHE.eint<2>>, tensor<2x4xi64>) -> tensor<3x2x!FHE.eint<3>>
// Returns the lookup of a vector of 3 encrypted indices of width 2 on a vector of 3 tables of size 4=2² of clear integers.
//
// [3,0,1] lut [[1,3,5,7], [0,2,4,6], [1,2,3,4]] = [7,0,2]
"FHELinalg.apply_multi_lookup_table"(%t, %luts) : (tensor<3x!FHE.eint<2>>, tensor<3x4xi64>) -> tensor<3x!FHE.eint<3>>
Extract the lowest significant bit at a given precision.
This operation extracts the lsb of a ciphertext tensor in a specific precision.
Extracting only 1 bit:
// ok
%lsb = "FHE.lsb"(%a): (tensor<1x!FHE.eint<4>)) -> (tensor<1x!FHE.eint<1>>)
If you need to clear the lsb of the original ciphertext, you should extract to the same precision as the ciphertext.
If you need to extract several bits, you can extract sequentially using explicit bitwidth change and bit clearing.
Example:
```mlir
// ok
%a_lsb = "FHELinalg.lsb"(%a): (tensor<1x!FHE.eint<4>)) -> (tensor<1x!FHE.eint<4>))
%a_lsb_cleared = "FHELinalg.sub_eint"(%a, %lsb) : (tensor<1x!FHE.eint<4>), tensor<1x!FHE.eint<4>)) -> (tensor<1x!FHE.eint<4>))
%b = %a : tensor<1x!FHE.eint<3>>
// now you can extract the next lsb from %b
%b_lsb = "FHELinalg.lsb"(%b): (tensor<1x!FHE.eint<3>>) -> (tensor<1x!FHE.eint<3>>)
// later if you need %b_lsb at the original position
%b_lsb_as_in_a = %b_lsb : tensor<1x!FHE.eint<3>>
Returns a tensor that contains the result of the matrix multiplication of a matrix of encrypted integers and a second matrix of encrypted integers.
Performs a matrix multiplication of a matrix of encrypted integers and a second matrix of encrypted integers.
The behavior depends on the arguments in the following way:
- If both arguments are 2-D,
they are multiplied like conventional matrices.
e.g.,
arg0: tensor<MxN> = [...]
arg1: tensor<NxP> = [...]
result: tensor<MxP> = [...]
- If the first argument is a vector (1-D),
it is treated as a matrix with a single row and standard matrix multiplication is performed.
After standard matrix multiplication,
the first dimension is removed from the result.
e.g.,
arg0: tensor<3> = [x, y, z]
arg1: tensor<3xM> = [
[_, _, ..., _, _],
[_, _, ..., _, _],
[_, _, ..., _, _],
]
is treated as
arg0: tensor<1x3> = [
[x, y, z]
]
arg1: tensor<3xM> = [
[_, _, ..., _, _],
[_, _, ..., _, _],
[_, _, ..., _, _],
]
and matrix multiplication is performed with the following form (1x3 @ 3xM -> 1xM)
result: tensor<1xM> = [[_, _, ..., _, _]]
finally, the first dimension is removed by definition so the result has the following form
result: tensor<M> = [_, _, ..., _, _]
- If the second argument is 1-D,
it is treated as a matrix with a single column and standard matrix multiplication is performed.
After standard matrix multiplication,
the last dimension is removed from the result.
e.g.,
arg0: tensor<Mx3> = [
[_, _, _],
[_, _, _],
...,
[_, _, _],
[_, _, _],
]
arg1: tensor<3> = [x, y, z]
is treated as
arg0: tensor<Mx3> = [
[_, _, _],
[_, _, _],
...,
[_, _, _],
[_, _, _],
]
arg1: tensor<3x1> = [
[x],
[y],
[z],
]
and matrix multiplication is performed with the following form (Mx3 @ 3x1 -> Mx1)
result: tensor<Mx1> = [
[_],
[_],
...,
[_],
[_],
]
finally, the last dimension is removed by definition so the result has the following form
result: tensor<M> = [_, _, _]
- If either argument is N-D where N > 2,
the operation is treated as a collection of matrices residing in the last two indices and broadcasted accordingly.
arg0: tensor<Kx1MxN> = [...]
arg1: tensor<LxNxP> = [...]
result: tensor<KxLxMxP> = [...]
Returns a tensor that contains the result of the matrix multiplication of a matrix of encrypted integers and a matrix of clear integers.
Performs a matrix multiplication of a matrix of encrypted integers and a matrix of clear integers. The width of the clear integers must be less than or equal to the width of encrypted integers.
The behavior depends on the arguments in the following way:
- If both arguments are 2-D,
they are multiplied like conventional matrices.
e.g.,
arg0: tensor<MxN> = [...]
arg1: tensor<NxP> = [...]
result: tensor<MxP> = [...]
- If the first argument is a vector (1-D),
it is treated as a matrix with a single row and standard matrix multiplication is performed.
After standard matrix multiplication,
the first dimension is removed from the result.
e.g.,
arg0: tensor<3> = [x, y, z]
arg1: tensor<3xM> = [
[_, _, ..., _, _],
[_, _, ..., _, _],
[_, _, ..., _, _],
]
is treated as
arg0: tensor<1x3> = [
[x, y, z]
]
arg1: tensor<3xM> = [
[_, _, ..., _, _],
[_, _, ..., _, _],
[_, _, ..., _, _],
]
and matrix multiplication is performed with the following form (1x3 @ 3xM -> 1xM)
result: tensor<1xM> = [[_, _, ..., _, _]]
finally, the first dimension is removed by definition so the result has the following form
result: tensor<M> = [_, _, ..., _, _]
- If the second argument is 1-D,
it is treated as a matrix with a single column and standard matrix multiplication is performed.
After standard matrix multiplication,
the last dimension is removed from the result.
e.g.,
arg0: tensor<Mx3> = [
[_, _, _],
[_, _, _],
...,
[_, _, _],
[_, _, _],
]
arg1: tensor<3> = [x, y, z]
is treated as
arg0: tensor<Mx3> = [
[_, _, _],
[_, _, _],
...,
[_, _, _],
[_, _, _],
]
arg1: tensor<3x1> = [
[x],
[y],
[z],
]
and matrix multiplication is performed with the following form (Mx3 @ 3x1 -> Mx1)
result: tensor<Mx1> = [
[_],
[_],
...,
[_],
[_],
]
finally, the last dimension is removed by definition so the result has the following form
result: tensor<M> = [_, _, _]
- If either argument is N-D where N > 2,
the operation is treated as a collection of matrices residing in the last two indices and broadcasted accordingly.
arg0: tensor<Kx1MxN> = [...]
arg1: tensor<LxNxP> = [...]
result: tensor<KxLxMxP> = [...]
Returns a tensor that contains the result of the matrix multiplication of a matrix of clear integers and a matrix of encrypted integers.
Performs a matrix multiplication of a matrix of clear integers and a matrix of encrypted integers. The width of the clear integers must be less than or equal to the width of encrypted integers.
The behavior depends on the arguments in the following way:
- If both arguments are 2-D,
they are multiplied like conventional matrices.
e.g.,
arg0: tensor<MxN> = [...]
arg1: tensor<NxP> = [...]
result: tensor<MxP> = [...]
- If the first argument is a vector (1-D),
it is treated as a matrix with a single row and standard matrix multiplication is performed.
After standard matrix multiplication,
the first dimension is removed from the result.
e.g.,
arg0: tensor<3> = [x, y, z]
arg1: tensor<3xM> = [
[_, _, ..., _, _],
[_, _, ..., _, _],
[_, _, ..., _, _],
]
is treated as
arg0: tensor<1x3> = [
[x, y, z]
]
arg1: tensor<3xM> = [
[_, _, ..., _, _],
[_, _, ..., _, _],
[_, _, ..., _, _],
]
and matrix multiplication is performed with the following form (1x3 @ 3xM -> 1xM)
result: tensor<1xM> = [[_, _, ..., _, _]]
finally, the first dimension is removed by definition so the result has the following form
result: tensor<M> = [_, _, ..., _, _]
- If the second argument is 1-D,
it is treated as a matrix with a single column and standard matrix multiplication is performed.
After standard matrix multiplication,
the last dimension is removed from the result.
e.g.,
arg0: tensor<Mx3> = [
[_, _, _],
[_, _, _],
...,
[_, _, _],
[_, _, _],
]
arg1: tensor<3> = [x, y, z]
is treated as
arg0: tensor<Mx3> = [
[_, _, _],
[_, _, _],
...,
[_, _, _],
[_, _, _],
]
arg1: tensor<3x1> = [
[x],
[y],
[z],
]
and matrix multiplication is performed with the following form (Mx3 @ 3x1 -> Mx1)
result: tensor<Mx1> = [
[_],
[_],
...,
[_],
[_],
]
finally, the last dimension is removed by definition so the result has the following form
result: tensor<M> = [_, _, _]
- If either argument is N-D where N > 2,
the operation is treated as a collection of matrices residing in the last two indices and broadcasted accordingly.
arg0: tensor<Kx1MxN> = [...]
arg1: tensor<LxNxP> = [...]
result: tensor<KxLxMxP> = [...]
Returns a tensor that contains the multiplication of a tensor of encrypted integers and a tensor of clear integers.
Performs a multiplication following the broadcasting rules between a tensor of encrypted integers and a tensor of clear integers. The width of the clear integers must be less than or equal to the width of encrypted integers.
Examples:
// Returns the term-by-term multiplication of `%a0` with `%a1`
"FHELinalg.mul_eint_int"(%a0, %a1) : (tensor<4x!FHE.eint<4>>, tensor<4xi5>) -> tensor<4x!FHE.eint<4>>
// Returns the term-by-term multiplication of `%a0` with `%a1`, where dimensions equal to one are stretched.
"FHELinalg.mul_eint_int"(%a0, %a1) : (tensor<4x1x4x!FHE.eint<4>>, tensor<1x4x4xi5>) -> tensor<4x4x4x!FHE.eint<4>>
// Returns the multiplication of a 3x3 matrix of encrypted integers and a 3x1 matrix (a column) of integers.
//
// [1,2,3] [1] [1,2,3]
// [4,5,6] * [2] = [8,10,18]
// [7,8,9] [3] [21,24,27]
//
// The dimension #1 of operand #2 is stretched as it is equal to 1.
"FHELinalg.mul_eint_int"(%a0, %a1) : (tensor<3x3x!FHE.eint<4>>, tensor<3x1xi5>) -> tensor<3x3x!FHE.eint<4>>
// Returns the multiplication of a 3x3 matrix of encrypted integers and a 1x3 matrix (a line) of integers.
//
// [1,2,3] [2,4,6]
// [4,5,6] * [1,2,3] = [5,7,9]
// [7,8,9] [8,10,12]
//
// The dimension #2 of operand #2 is stretched as it is equal to 1.
"FHELinalg.mul_eint_int"(%a0, %a1) : (tensor<3x3x!FHE.eint<4>>, tensor<1x3xi5>) -> tensor<3x3x!FHE.eint<4>>
// Same behavior as the previous one, but as the dimension #2 is missing of operand #2.
"FHELinalg.mul_eint_int"(%a0, %a1) : (tensor<3x3x!FHE.eint<4>>, tensor<3xi5>) -> tensor<3x3x!FHE.eint<4>>
Returns a tensor that contains the multiplication of two tensor of encrypted integers.
Performs an addition following the broadcasting rules between two tensors of encrypted integers. The width of the encrypted integers must be equal.
Examples:
// Returns the term-by-term multiplication of `%a0` with `%a1`
"FHELinalg.mul_eint"(%a0, %a1) : (tensor<4x!FHE.eint<8>>, tensor<4x!FHE.eint<8>>) -> tensor<4x!FHE.eint<8>>
// Returns the term-by-term multiplication of `%a0` with `%a1`, where dimensions equal to one are stretched.
"FHELinalg.mul_eint"(%a0, %a1) : (tensor<4x1x4x!FHE.eint<8>>, tensor<1x4x4x!FHE.eint<8>>) -> tensor<4x4x4x!FHE.eint<8>>
// Returns the multiplication of a 3x3 matrix of encrypted integers and a 3x1 matrix (a column) of encrypted integers.
//
// [1,2,3] [1] [1,2,3]
// [4,5,6] * [2] = [8,10,12]
// [7,8,9] [3] [21,24,27]
//
// The dimension #1 of operand #2 is stretched as it is equal to 1.
"FHELinalg.mul_eint"(%a0, %a1) : (tensor<3x3x!FHE.eint<8>>, tensor<3x1x!FHE.eint<8>>) -> tensor<3x3x!FHE.eint<8>>
// Returns the multiplication of a 3x3 matrix of encrypted integers and a 1x3 matrix (a line) of encrypted integers.
//
// [1,2,3] [1,4,9]
// [4,5,6] * [1,2,3] = [4,10,18]
// [7,8,9] [7,16,27]
//
// The dimension #2 of operand #2 is stretched as it is equal to 1.
"FHELinalg.mul_eint"(%a0, %a1) : (tensor<3x3x!FHE.eint<8>>, tensor<1x3x!FHE.eint<8>>) -> tensor<3x3x!FHE.eint<8>>
// Same behavior as the previous one, but as the dimension #2 of operand #2 is missing.
"FHELinalg.mul_eint"(%a0, %a1) : (tensor<3x3x!FHE.eint<8>>, tensor<3x!FHE.eint<8>>) -> tensor<3x3x!FHE.eint<8>>
Reinterpret the ciphertext tensor with a different precision.
It's a reinterpretation cast which changes only the precision. On CRT represention, it does nothing. On Native representation, it moves the message/noise further forward, effectively changing the precision. Changing to - a bigger precision is safe, as the crypto-parameters are chosen such that only zeros will come from the noise part. This is equivalent to a shift left for the value - a smaller precision is only safe if you clear the lowest message bits first. If not, you can assume small errors with high probability and frequent bigger errors, which can be contained to small errors using margins. This is equivalent to a shift right for the value
Example:
// assuming a is encoded as 4bits but can be stored in 2bits
// we can obtain a to a smaller 2 bits precision
%shifted_a = "FHELinalg.mul_eint_intlsb"(%a, %c_4): (tensor<1x!FHE.eint<4>>) -> (tensor<1x!FHE.eint<2>>)
%a_small_precision = "FHELinalg.reinterpret_precision"(%shifted_a, %lsb) : (tensor<1x!FHE.eint<4>>) -> (tensor<1x!FHE.eint<2>>)
Rounds a tensor of ciphertexts into a smaller precision.
Assuming a ciphertext whose message is implemented over `p` bits, this
operation rounds it to fit to `q` bits where `p>q`.
Example:
```mlir
// ok
"FHELinalg.round"(%a): (tensor<3x!FHE.eint<6>>) -> (tensor<3x!FHE.eint<5>>)
"FHELinalg.round"(%a): (tensor<3x!FHE.eint<5>>) -> (tensor<3x!FHE.eint<3>>)
"FHELinalg.round"(%a): (tensor<3x!FHE.eint<3>>) -> (tensor<3x!FHE.eint<2>>)
"FHELinalg.round"(%a): (tensor<3x!FHE.esint<3>>) -> (tensor<3x!FHE.esint<2>>)
// error
"FHELinalg.round"(%a): (tensor<3x!FHE.eint<6>>) -> (tensor<3x!FHE.eint<6>>)
"FHELinalg.round"(%a): (tensor<3x!FHE.eint<4>>) -> (tensor<3x!FHE.eint<5>>)
"FHELinalg.round"(%a): (tensor<3x!FHE.eint<4>>) -> (tensor<3x!FHE.esint<2>>)
Traits: AlwaysSpeculatableImplTrait, TensorUnaryEint
Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface), UnaryEint
Effects: MemoryEffects::Effect{}
#### Operands:
| Operand | Description |
| :-----: | ----------- |
| `input` |
#### Results:
| Result | Description |
| :----: | ----------- |
| `output` |
### `FHELinalg.sub_eint_int` (::mlir::concretelang::FHELinalg::SubEintIntOp)
Returns a tensor that contains the subtraction of a tensor of clear integers from a tensor of encrypted integers.
Performs a subtraction following the broadcasting rules between a tensor of clear integers from a tensor of encrypted integers.
The width of the clear integers must be less than or equal to the width of encrypted integers.
Examples:
```mlir
// Returns the term-by-term subtraction of `%a0` with `%a1`
"FHELinalg.sub_eint_int"(%a0, %a1) : (tensor<4x!FHE.eint<4>>, tensor<4xi5>) -> tensor<4x!FHE.eint<4>>
// Returns the term-by-term subtraction of `%a0` with `%a1`, where dimensions equal to one are stretched.
"FHELinalg.sub_eint_int"(%a0, %a1) : (tensor<1x4x4x!FHE.eint<4>>, tensor<4x1x4xi5>) -> tensor<4x4x4x!FHE.eint<4>>
// Returns the subtraction of a 3x3 matrix of integers and a 3x1 matrix (a column) of encrypted integers.
//
// [1,2,3] [1] [0,2,3]
// [4,5,6] - [2] = [2,3,4]
// [7,8,9] [3] [4,5,6]
//
// The dimension #1 of operand #2 is stretched as it is equal to 1.
"FHELinalg.sub_eint_int"(%a0, %a1) : (tensor<3x1x!FHE.eint<4>>, tensor<3x3xi5>) -> tensor<3x3x!FHE.eint<4>>
// Returns the subtraction of a 3x3 matrix of integers and a 1x3 matrix (a line) of encrypted integers.
//
// [1,2,3] [0,0,0]
// [4,5,6] - [1,2,3] = [3,3,3]
// [7,8,9] [6,6,6]
//
// The dimension #2 of operand #2 is stretched as it is equal to 1.
"FHELinalg.sub_eint_int"(%a0, %a1) : (tensor<1x3x!FHE.eint<4>>, tensor<3x3xi5>) -> tensor<3x3x!FHE.eint<4>>
// Same behavior as the previous one, but as the dimension #2 is missing of operand #2.
"FHELinalg.sub_eint_int"(%a0, %a1) : (tensor<3x!FHE.eint<4>>, tensor<3x3xi5>) -> tensor<3x3x!FHE.eint<4>>
Returns a tensor that contains the subtraction of two tensor of encrypted integers.
Performs an subtraction following the broadcasting rules between two tensors of encrypted integers. The width of the encrypted integers must be equal.
Examples:
// Returns the term-by-term subtraction of `%a0` with `%a1`
"FHELinalg.sub_eint"(%a0, %a1) : (tensor<4x!FHE.eint<4>>, tensor<4x!FHE.eint<4>>) -> tensor<4x!FHE.eint<4>>
// Returns the term-by-term subtraction of `%a0` with `%a1`, where dimensions equal to one are stretched.
"FHELinalg.sub_eint"(%a0, %a1) : (tensor<4x1x4x!FHE.eint<4>>, tensor<1x4x4x!FHE.eint<4>>) -> tensor<4x4x4x!FHE.eint<4>>
// Returns the subtraction of a 3x3 matrix of integers and a 3x1 matrix (a column) of encrypted integers.
//
// [1,2,3] [1] [0,2,3]
// [4,5,6] - [2] = [2,3,4]
// [7,8,9] [3] [4,5,6]
//
// The dimension #1 of operand #2 is stretched as it is equal to 1.
"FHELinalg.sub_eint"(%a0, %a1) : (tensor<3x3x!FHE.eint<4>>, tensor<3x1x!FHE.eint<4>>) -> tensor<3x3x!FHE.eint<4>>
// Returns the subtraction of a 3x3 matrix of integers and a 1x3 matrix (a line) of encrypted integers.
//
// [1,2,3] [0,0,0]
// [4,5,6] - [1,2,3] = [3,3,3]
// [7,8,9] [6,6,6]
//
// The dimension #2 of operand #2 is stretched as it is equal to 1.
"FHELinalg.sub_eint"(%a0, %a1) : (tensor<3x3x!FHE.eint<4>>, tensor<1x3x!FHE.eint<4>>) -> tensor<3x3x!FHE.eint<4>>
// Same behavior as the previous one, but as the dimension #2 of operand #2 is missing.
"FHELinalg.sub_eint"(%a0, %a1) : (tensor<3x3x!FHE.eint<4>>, tensor<3x!FHE.eint<4>>) -> tensor<3x3x!FHE.eint<4>>
Returns a tensor that contains the subtraction of a tensor of clear integers and a tensor of encrypted integers.
Performs a subtraction following the broadcasting rules between a tensor of clear integers and a tensor of encrypted integers. The width of the clear integers must be less than or equal to the width of encrypted integers.
Examples:
// Returns the term-by-term subtraction of `%a0` with `%a1`
"FHELinalg.sub_int_eint"(%a0, %a1) : (tensor<4xi5>, tensor<4x!FHE.eint<4>>) -> tensor<4x!FHE.eint<4>>
// Returns the term-by-term subtraction of `%a0` with `%a1`, where dimensions equal to one are stretched.
"FHELinalg.sub_int_eint"(%a0, %a1) : (tensor<4x1x4xi5>, tensor<1x4x4x!FHE.eint<4>>) -> tensor<4x4x4x!FHE.eint<4>>
// Returns the subtraction of a 3x3 matrix of integers and a 3x1 matrix (a column) of encrypted integers.
//
// [1,2,3] [1] [0,2,3]
// [4,5,6] - [2] = [2,3,4]
// [7,8,9] [3] [4,5,6]
//
// The dimension #1 of operand #2 is stretched as it is equal to 1.
"FHELinalg.sub_int_eint"(%a0, %a1) : (tensor<3x3xi5>, tensor<3x1x!FHE.eint<4>>) -> tensor<3x3x!FHE.eint<4>>
// Returns the subtraction of a 3x3 matrix of integers and a 1x3 matrix (a line) of encrypted integers.
//
// [1,2,3] [0,0,0]
// [4,5,6] - [1,2,3] = [3,3,3]
// [7,8,9] [6,6,6]
//
// The dimension #2 of operand #2 is stretched as it is equal to 1.
"FHELinalg.sub_int_eint"(%a0, %a1) : (tensor<3x3xi5>, tensor<1x3x!FHE.eint<4>>) -> tensor<3x3x!FHE.eint<4>>
// Same behavior as the previous one, but as the dimension #2 is missing of operand #2.
"FHELinalg.sub_int_eint"(%a0, %a1) : (tensor<3x3xi5>, tensor<3x!FHE.eint<4>>) -> tensor<3x3x!FHE.eint<4>>
Returns the sum of elements of a tensor of encrypted integers along specified axes.
Attributes:
keep_dims: boolean = false whether to keep the rank of the tensor after the sum operation if true, reduced axes will have the size of 1
axes: I64ArrayAttr = [] list of dimension to perform the sum along think of it as the dimensions to reduce (see examples below to get an intuition)
Examples:
// Returns the sum of all elements of `%a0`
"FHELinalg.sum"(%a0) : (tensor<3x3x!FHE.eint<4>>) -> !FHE.eint<4>
//
// ( [1,2,3] )
// sum ( [4,5,6] ) = 45
// ( [7,8,9] )
//
// Returns the sum of all elements of `%a0` along columns
"FHELinalg.sum"(%a0) { axes = [0] } : (tensor<3x2x!FHE.eint<4>>) -> tensor<2x!FHE.eint<4>>
//
// ( [1,2] )
// sum ( [3,4] ) = [9, 12]
// ( [5,6] )
//
// Returns the sum of all elements of `%a0` along columns while preserving dimensions
"FHELinalg.sum"(%a0) { axes = [0], keep_dims = true } : (tensor<3x2x!FHE.eint<4>>) -> tensor<1x2x!FHE.eint<4>>
//
// ( [1,2] )
// sum ( [3,4] ) = [[9, 12]]
// ( [5,6] )
//
// Returns the sum of all elements of `%a0` along rows
"FHELinalg.sum"(%a0) { axes = [1] } : (tensor<3x2x!FHE.eint<4>>) -> tensor<3x!FHE.eint<4>>
//
// ( [1,2] )
// sum ( [3,4] ) = [3, 7, 11]
// ( [5,6] )
//
// Returns the sum of all elements of `%a0` along rows while preserving dimensions
"FHELinalg.sum"(%a0) { axes = [1], keep_dims = true } : (tensor<3x2x!FHE.eint<4>>) -> tensor<3x1x!FHE.eint<4>>
//
// ( [1,2] ) [3]
// sum ( [3,4] ) = [7]
// ( [5,6] ) [11]
//
Returns a tensor that contains the transposition of the input tensor.
Performs a transpose operation on an N-dimensional tensor.
Attributes:
axes: I64ArrayAttr = [] list of dimension to perform the transposition contains a permutation of [0,1,..,N-1] where N is the number of axes think of it as a way to rearrange axes (see the example below)