mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-11 23:58:23 -05:00
Compare commits
18 Commits
create-pul
...
alpha/1.4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da15ae85a1 | ||
|
|
a5de357afd | ||
|
|
18a0af8466 | ||
|
|
b2a396d3eb | ||
|
|
8c24c30320 | ||
|
|
8ec0fdb793 | ||
|
|
ee8b26f49d | ||
|
|
ef0485f618 | ||
|
|
cc11b7bef7 | ||
|
|
eda9b9e3d1 | ||
|
|
da974f0bad | ||
|
|
ddf945996a | ||
|
|
99f40e2b80 | ||
|
|
7c5c33063d | ||
|
|
eafc61423d | ||
|
|
03c68dac28 | ||
|
|
ebbf5563c7 | ||
|
|
fd63db1f6f |
23
.github/workflows/make_release_tfhe.yml
vendored
23
.github/workflows/make_release_tfhe.yml
vendored
@@ -39,16 +39,14 @@ jobs:
|
||||
make-release:
|
||||
name: make_release_tfhe/make-release
|
||||
uses: ./.github/workflows/make_release_common.yml
|
||||
if: ${{ inputs.push_to_crates }}
|
||||
with:
|
||||
package-name: "tfhe"
|
||||
dry-run: ${{ inputs.dry_run }}
|
||||
permissions:
|
||||
# Needed to detect the GitHub Actions environment
|
||||
actions: read
|
||||
# Needed to create the provenance via GitHub OIDC
|
||||
id-token: write
|
||||
# Needed to upload assets/artifacts
|
||||
contents: write
|
||||
actions: read # Needed to detect the GitHub Actions environment
|
||||
id-token: write # Needed to create the provenance via GitHub OIDC
|
||||
contents: write # Needed to upload assets/artifacts
|
||||
secrets:
|
||||
BOT_USERNAME: ${{ secrets.BOT_USERNAME }}
|
||||
SLACK_CHANNEL: ${{ secrets.SLACK_CHANNEL }}
|
||||
@@ -60,14 +58,15 @@ jobs:
|
||||
make-release-js:
|
||||
name: make_release_tfhe/make-release-js
|
||||
needs: make-release
|
||||
if: ${{ always() && needs.make-release.result != 'failure' }}
|
||||
runs-on: ubuntu-latest
|
||||
# For provenance of npmjs publish
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write # also needed for OIDC token exchange on crates.io
|
||||
id-token: write # also needed for OIDC token exchange on crates.io and npmjs.com
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: 'false'
|
||||
@@ -83,11 +82,16 @@ jobs:
|
||||
run: |
|
||||
make build_web_js_api_parallel
|
||||
|
||||
- name: Authenticate on NPM
|
||||
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
|
||||
with:
|
||||
node-version: '24'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Publish web package
|
||||
if: ${{ inputs.push_web_package }}
|
||||
uses: JS-DevTools/npm-publish@7f8fe47b3bea1be0c3aec2b717c5ec1f3e03410b
|
||||
with:
|
||||
token: ${{ secrets.NPM_TOKEN }}
|
||||
package: tfhe/pkg/package.json
|
||||
dry-run: ${{ inputs.dry_run }}
|
||||
tag: ${{ env.NPM_TAG }}
|
||||
@@ -105,7 +109,6 @@ jobs:
|
||||
if: ${{ inputs.push_node_package }}
|
||||
uses: JS-DevTools/npm-publish@7f8fe47b3bea1be0c3aec2b717c5ec1f3e03410b
|
||||
with:
|
||||
token: ${{ secrets.NPM_TOKEN }}
|
||||
package: tfhe/pkg/package.json
|
||||
dry-run: ${{ inputs.dry_run }}
|
||||
tag: ${{ env.NPM_TAG }}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
resolver = "3"
|
||||
members = [
|
||||
"tfhe",
|
||||
"tfhe-benchmark",
|
||||
@@ -24,7 +24,7 @@ exclude = [
|
||||
]
|
||||
[workspace.dependencies]
|
||||
aligned-vec = { version = "0.6", default-features = false }
|
||||
bytemuck = "1.14.3"
|
||||
bytemuck = "<1.24"
|
||||
dyn-stack = { version = "0.11", default-features = false }
|
||||
itertools = "0.14"
|
||||
num-complex = "0.4"
|
||||
|
||||
8
Makefile
8
Makefile
@@ -22,12 +22,13 @@ BENCH_TYPE?=latency
|
||||
BENCH_PARAM_TYPE?=classical
|
||||
BENCH_PARAMS_SET?=default
|
||||
BENCH_CUSTOM_COMMAND:=
|
||||
NODE_VERSION=22.6
|
||||
NODE_VERSION=24.12
|
||||
BACKWARD_COMPAT_DATA_DIR=utils/tfhe-backward-compat-data
|
||||
WASM_PACK_VERSION="0.13.1"
|
||||
WASM_BINDGEN_VERSION:=$(shell cargo tree --target wasm32-unknown-unknown -e all --prefix none | grep "wasm-bindgen v" | head -n 1 | cut -d 'v' -f2)
|
||||
WEB_RUNNER_DIR=web-test-runner
|
||||
WEB_SERVER_DIR=tfhe/web_wasm_parallel_tests
|
||||
TYPOS_VERSION=1.39.0
|
||||
# This is done to avoid forgetting it, we still precise the RUSTFLAGS in the commands to be able to
|
||||
# copy paste the command in the terminal and change them if required without forgetting the flags
|
||||
export RUSTFLAGS?=-C target-cpu=native
|
||||
@@ -165,9 +166,8 @@ install_cargo_audit: install_rs_build_toolchain
|
||||
|
||||
.PHONY: install_typos_checker # Install typos checker
|
||||
install_typos_checker: install_rs_build_toolchain
|
||||
@typos --version > /dev/null 2>&1 || \
|
||||
cargo $(CARGO_RS_BUILD_TOOLCHAIN) install --locked typos-cli || \
|
||||
( echo "Unable to install typos-cli, unknown error." && exit 1 )
|
||||
@./scripts/install_typos.sh --rust-toolchain $(CARGO_RS_BUILD_TOOLCHAIN) \
|
||||
--typos-version $(TYPOS_VERSION)
|
||||
|
||||
.PHONY: install_zizmor # Install zizmor workflow security checker
|
||||
install_zizmor: install_rs_build_toolchain
|
||||
|
||||
@@ -13,6 +13,7 @@ extend-ignore-identifiers-re = [
|
||||
# Example in trivium
|
||||
"C9217BA0D762ACA1",
|
||||
"0x[0-9a-fA-F]+",
|
||||
"xrt_coreutil",
|
||||
]
|
||||
|
||||
[files]
|
||||
|
||||
@@ -36,7 +36,7 @@ __device__ Torus *get_ith_block(Torus *ksk, int i, int level,
|
||||
*
|
||||
*/
|
||||
// Each thread in x are used to calculate one output.
|
||||
// threads in y are used to paralelize the lwe_dimension_in loop.
|
||||
// threads in y are used to parallelize the lwe_dimension_in loop.
|
||||
// shared memory is used to store intermediate results of the reduction.
|
||||
// Note: To reduce register pressure we have slightly changed the algorithm,
|
||||
// the idea consists in calculating the negate value of the output. So, instead
|
||||
|
||||
@@ -33,7 +33,7 @@ serde = { version = "1", features = ["derive"] }
|
||||
toml = { version = "0.8", features = [] }
|
||||
paste = "1.0.15"
|
||||
thiserror = "1.0.61"
|
||||
bytemuck = "1.16.0"
|
||||
bytemuck = { workspace = true }
|
||||
anyhow = "1.0.82"
|
||||
lazy_static = "1.4.0"
|
||||
rand = "0.8.5"
|
||||
@@ -61,8 +61,12 @@ bitvec = { version = "1.0", optional = true }
|
||||
serde_json = { version = "1.0", optional = true }
|
||||
|
||||
# Dependencies used for v80 pdi handling
|
||||
bincode ={ version = "1.3", optional = true}
|
||||
serde_derive ={ version = "1.0", optional = true}
|
||||
bincode = { version = "1.3", optional = true }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
|
||||
# Fix build for toolchain < 1.85, newer versions are edition 2024 which requires rust 1.85
|
||||
ignore = { version = "<0.4.24" }
|
||||
globset = { version = "<0.4.17" }
|
||||
|
||||
# Binary for manual debugging
|
||||
# Enable to access Hpu register and drive some custom sequence by hand
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
lut_pc = {Hbm={pc=34}}
|
||||
|
||||
fw_size= 16777215 # i.e. 16 MiB
|
||||
fw_pc = {Ddr= {offset= 0x3900_0000}} # NB: Allocation must take place in the Discret DDR
|
||||
fw_pc = {Ddr= {offset= 0x3900_0000}} # NB: Allocation must take place in the Discrete DDR
|
||||
|
||||
bsk_pc = [
|
||||
{Hbm={pc=8}},
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
lut_pc = {Hbm={pc=34}}
|
||||
|
||||
fw_size= 16777216 # i.e. 16 MiB
|
||||
fw_pc = {Ddr= {offset= 0x3900_0000}} # NB: Allocation must take place in the Discret DDR
|
||||
fw_pc = {Ddr= {offset= 0x3900_0000}} # NB: Allocation must take place in the Discrete DDR
|
||||
|
||||
bsk_pc = [
|
||||
{Hbm={pc=8}},
|
||||
|
||||
@@ -81,7 +81,7 @@ pub enum ImmId {
|
||||
}
|
||||
|
||||
impl ImmId {
|
||||
/// Create new immediat template
|
||||
/// Create new immediate template
|
||||
pub fn new_var(tid: u8, bid: u8) -> Self {
|
||||
Self::Var { tid, bid }
|
||||
}
|
||||
@@ -132,7 +132,7 @@ pub struct PeArithInsn {
|
||||
}
|
||||
|
||||
/// PeaMsg instructions
|
||||
/// Arithmetic operation that use one destination register, one source register and an immediat
|
||||
/// Arithmetic operation that use one destination register, one source register and an immediate
|
||||
/// value
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct PeArithMsgInsn {
|
||||
|
||||
@@ -69,7 +69,7 @@ impl From<&PeArithHex> for PeArithInsn {
|
||||
}
|
||||
|
||||
/// PeaMsg instructions
|
||||
/// Arithmetic operation that use one destination register, one source register and an immediat
|
||||
/// Arithmetic operation that use one destination register, one source register and an immediate
|
||||
/// value
|
||||
#[bitfield(u32)]
|
||||
pub struct PeArithMsgHex {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
use super::*;
|
||||
use field::{
|
||||
FwMode, IOpHeader, IOpcode, ImmBundle, Immediat, Operand, OperandBlock, OperandBundle,
|
||||
FwMode, IOpHeader, IOpcode, ImmBundle, Immediate, Operand, OperandBlock, OperandBundle,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
@@ -393,7 +393,7 @@ impl std::str::FromStr for ImmBundle {
|
||||
.map_err(|err| ParsingError::InvalidArg(err.to_string()))?
|
||||
};
|
||||
|
||||
Ok(Immediat::from_cst(imm))
|
||||
Ok(Immediate::from_cst(imm))
|
||||
})
|
||||
.collect::<Result<Vec<_>, ParsingError>>()?;
|
||||
|
||||
@@ -475,7 +475,7 @@ impl std::fmt::Display for IOp {
|
||||
// Source operands list
|
||||
write!(f, " <{}>", self.src)?;
|
||||
|
||||
// Immediat operands list [Optional]
|
||||
// Immediate operands list [Optional]
|
||||
if self.header.has_imm {
|
||||
write!(f, " <{}>", self.imm)?;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ impl Operand {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a dedicated type for a collection of Immediat
|
||||
/// Create a dedicated type for a collection of Immediate
|
||||
/// This is to enable trait implementation on it (c.f arg)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OperandBundle(Vec<Operand>);
|
||||
@@ -142,32 +142,32 @@ impl OperandBundle {
|
||||
|
||||
// Immediate operands
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/// Immediat Size
|
||||
/// => Number of valid digit in following immediat
|
||||
/// Immediate Size
|
||||
/// => Number of valid digit in following immediate
|
||||
/// To obtain the number of valid bits, user should multiply by the msg_width
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct ImmBlock(pub u16);
|
||||
|
||||
/// Immediat header
|
||||
/// Immediate header
|
||||
/// Use to implement top-level parser manually
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct ImmediatHeader {
|
||||
pub struct ImmediateHeader {
|
||||
pub(super) lsb_msg: u16,
|
||||
pub(super) block: ImmBlock,
|
||||
pub(super) is_last: bool,
|
||||
pub(super) kind: OperandKind,
|
||||
}
|
||||
|
||||
/// Full Immediat representation (i.e. header + data)
|
||||
/// Full Immediate representation (i.e. header + data)
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Immediat {
|
||||
pub struct Immediate {
|
||||
pub(super) kind: OperandKind,
|
||||
pub(super) is_last: bool,
|
||||
pub(super) block: ImmBlock,
|
||||
pub(super) msg: Vec<u16>,
|
||||
}
|
||||
|
||||
impl Immediat {
|
||||
impl Immediate {
|
||||
/// Access imm msg for template patching
|
||||
/// Extract the correct block (i.e. MSG_WIDTH chunk)
|
||||
pub fn msg_block(&self, bid: u8) -> u16 {
|
||||
@@ -217,7 +217,7 @@ impl Immediat {
|
||||
}
|
||||
}
|
||||
|
||||
impl Immediat {
|
||||
impl Immediate {
|
||||
#[tracing::instrument(level = "trace", ret)]
|
||||
pub fn from_words(stream: &[IOpWordRepr]) -> Result<(Self, usize), HexParsingError> {
|
||||
// Keep track of the current peak index
|
||||
@@ -226,7 +226,7 @@ impl Immediat {
|
||||
// 1. Parse header
|
||||
let header = if let Some(header_word) = stream.get(peak_words) {
|
||||
peak_words += 1;
|
||||
ImmediatHeader::from(&fmt::ImmediatHeaderHex::from_bits(*header_word))
|
||||
ImmediateHeader::from(&fmt::ImmediateHeaderHex::from_bits(*header_word))
|
||||
} else {
|
||||
return Err(HexParsingError::EmptyStream);
|
||||
};
|
||||
@@ -276,13 +276,13 @@ impl Immediat {
|
||||
|
||||
pub fn to_words(&self) -> Vec<IOpWordRepr> {
|
||||
let mut words = Vec::new();
|
||||
let header = ImmediatHeader {
|
||||
let header = ImmediateHeader {
|
||||
lsb_msg: *self.msg.first().unwrap_or(&0),
|
||||
block: self.block,
|
||||
is_last: self.is_last,
|
||||
kind: self.kind,
|
||||
};
|
||||
words.push(fmt::ImmediatHeaderHex::from(&header).into_bits());
|
||||
words.push(fmt::ImmediateHeaderHex::from(&header).into_bits());
|
||||
|
||||
if self.msg.len() > 1 {
|
||||
for imm in self.msg[1..]
|
||||
@@ -302,10 +302,10 @@ impl Immediat {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a dedicated type for a collection of Immediat
|
||||
/// Create a dedicated type for a collection of Immediate
|
||||
/// This is to enable trait implementation on it (c.f arg)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ImmBundle(Vec<Immediat>);
|
||||
pub struct ImmBundle(Vec<Immediate>);
|
||||
|
||||
impl ImmBundle {
|
||||
#[tracing::instrument(level = "trace", ret)]
|
||||
@@ -315,7 +315,7 @@ impl ImmBundle {
|
||||
|
||||
let mut imm_list = Vec::new();
|
||||
loop {
|
||||
let (imm, peaked) = Immediat::from_words(&stream[peak_words..])?;
|
||||
let (imm, peaked) = Immediate::from_words(&stream[peak_words..])?;
|
||||
peak_words += peaked;
|
||||
|
||||
let is_last = imm.is_last;
|
||||
@@ -335,9 +335,9 @@ impl ImmBundle {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<Immediat>> for ImmBundle {
|
||||
impl From<Vec<Immediate>> for ImmBundle {
|
||||
#[tracing::instrument(level = "trace", ret)]
|
||||
fn from(inner: Vec<Immediat>) -> Self {
|
||||
fn from(inner: Vec<Immediate>) -> Self {
|
||||
let mut inner = inner;
|
||||
// Enforce correct is_last handling
|
||||
inner.iter_mut().for_each(|op| op.is_last = false);
|
||||
@@ -349,7 +349,7 @@ impl From<Vec<Immediat>> for ImmBundle {
|
||||
}
|
||||
|
||||
impl std::ops::Deref for ImmBundle {
|
||||
type Target = Vec<Immediat>;
|
||||
type Target = Vec<Immediate>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
@@ -392,7 +392,7 @@ use std::collections::VecDeque;
|
||||
/// Implement construction
|
||||
/// Used to construct IOp from Backend HpuVar
|
||||
impl IOp {
|
||||
pub fn new(opcode: IOpcode, dst: Vec<Operand>, src: Vec<Operand>, imm: Vec<Immediat>) -> Self {
|
||||
pub fn new(opcode: IOpcode, dst: Vec<Operand>, src: Vec<Operand>, imm: Vec<Immediate>) -> Self {
|
||||
let dst_align = dst.iter().map(|x| x.block).max().unwrap();
|
||||
let src_align = src.iter().map(|x| x.block).max().unwrap();
|
||||
let has_imm = !imm.is_empty();
|
||||
@@ -504,7 +504,7 @@ impl IOp {
|
||||
src
|
||||
};
|
||||
|
||||
// 4. Parse Immediat [Optional]
|
||||
// 4. Parse Immediate [Optional]
|
||||
let (imm, peaked) = if header.has_imm {
|
||||
ImmBundle::from_words(&stream.as_slices().0[peak_words..])?
|
||||
} else {
|
||||
@@ -533,7 +533,7 @@ impl IOp {
|
||||
words.extend(self.dst.to_words());
|
||||
// 3. Sources
|
||||
words.extend(self.src.to_words());
|
||||
// 4. Immediat
|
||||
// 4. Immediate
|
||||
words.extend(self.imm.to_words());
|
||||
words
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ impl From<&Operand> for OperandHex {
|
||||
}
|
||||
|
||||
#[bitfield(u32)]
|
||||
pub struct ImmediatHeaderHex {
|
||||
pub struct ImmediateHeaderHex {
|
||||
#[bits(16)]
|
||||
lsb_msg: u16,
|
||||
#[bits(12)]
|
||||
@@ -73,8 +73,8 @@ pub struct ImmediatHeaderHex {
|
||||
kind: u8,
|
||||
}
|
||||
|
||||
impl From<&ImmediatHeaderHex> for field::ImmediatHeader {
|
||||
fn from(value: &ImmediatHeaderHex) -> Self {
|
||||
impl From<&ImmediateHeaderHex> for field::ImmediateHeader {
|
||||
fn from(value: &ImmediateHeaderHex) -> Self {
|
||||
let kind = if value.kind() == OperandKind::Src as u8 {
|
||||
OperandKind::Src
|
||||
} else if value.kind() == OperandKind::Dst as u8 {
|
||||
@@ -94,8 +94,8 @@ impl From<&ImmediatHeaderHex> for field::ImmediatHeader {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&field::ImmediatHeader> for ImmediatHeaderHex {
|
||||
fn from(value: &field::ImmediatHeader) -> Self {
|
||||
impl From<&field::ImmediateHeader> for ImmediateHeaderHex {
|
||||
fn from(value: &field::ImmediateHeader) -> Self {
|
||||
Self::new()
|
||||
.with_lsb_msg(value.lsb_msg)
|
||||
.with_block(value.block.0)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//! IOp definition
|
||||
|
||||
mod field;
|
||||
pub use field::{HexParsingError, IOp, IOpcode, Immediat, Operand, OperandKind};
|
||||
pub use field::{HexParsingError, IOp, IOpcode, Immediate, Operand, OperandKind};
|
||||
mod fmt;
|
||||
pub use fmt::{IOpRepr, IOpWordRepr};
|
||||
mod iop_macro;
|
||||
|
||||
@@ -20,7 +20,7 @@ SUB R2 R1 R3
|
||||
MUL R2 R1 R3
|
||||
MAC R2 R1 R3 4
|
||||
|
||||
; Test ArithMsg operation with various immediat template format
|
||||
; Test ArithMsg operation with various immediate template format
|
||||
ADDS R2 R1 10
|
||||
SUBS R2 R1 TI[4].0
|
||||
SSUB R2 R1 TI[2].4
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
; with the != available arguments modes
|
||||
|
||||
; Simple Mode:
|
||||
; 1 destination, 2 sources, no immediat
|
||||
; 1 destination, 2 sources, no immediate
|
||||
; With raw opcode -> 0x35
|
||||
IOP[0x35] <I8 I8> <I8@0x08> <I8@0x0 I8@0x4>
|
||||
; With raw opcode -> 40 and dynamic Fw generation
|
||||
@@ -11,7 +11,7 @@ IOP[0x35] <dyn I8 I8> <I8@0x08> <I8@0x0 I8@0x4>
|
||||
; With opcode alias -> MUL
|
||||
MUL <I8 I8> <I8@0x08> <I8@0x0 I4@0x4>
|
||||
|
||||
; Simple Mode with immediat
|
||||
; Simple Mode with immediate
|
||||
; Source operands are defined through vector mode
|
||||
MULS <I8 I8> <I8@0x8> <I8[2]@0x0> <0xaf>
|
||||
|
||||
@@ -26,6 +26,6 @@ IOP[0x60] <dyn I8 I8> <I8@0x10 I8@0x14> <I8@0x0 I8@0x4>
|
||||
; Previous operation could be defined with vector format.
|
||||
IOP[0x40] <dyn I8 I8> <I8[2]@0x10> <I8[2]@0x0>
|
||||
|
||||
; With multiple immediat
|
||||
; With multiple immediate
|
||||
; Example this operation could compute D <- A*4 + B*8
|
||||
IOP[0x0] <I16 I16> <I16@16> <I16@0x0 I8@0x8> <0xdeadc0de>
|
||||
|
||||
@@ -84,7 +84,7 @@ impl HpuV80Pdi {
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
/// Deconstruct HpuV80Pdi into a folder with discret files
|
||||
/// Deconstruct HpuV80Pdi into a folder with discrete files
|
||||
pub fn to_folder(&self, folder_path: &str) -> Result<(), Box<dyn Error>> {
|
||||
let metadata_path = Path::new(folder_path).join("metadata.toml");
|
||||
self.metadata.to_toml(
|
||||
|
||||
@@ -100,11 +100,11 @@ pub fn iop_adds(prog: &mut Program) {
|
||||
let mut dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("ADDS Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("ADDS Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic addx function
|
||||
iop_addx(prog, &mut dst, None, &src_a, &src_b);
|
||||
}
|
||||
@@ -134,18 +134,18 @@ pub fn iop_overflow_adds(prog: &mut Program) {
|
||||
let mut flag = prog.iop_template_var(OperandKind::Dst, 1);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("ADDS Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("ADDS Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic addx function
|
||||
iop_addx(prog, &mut dst, Some(&mut flag[0]), &src_a, &src_b);
|
||||
}
|
||||
|
||||
/// Generic Add operation
|
||||
/// One destination and two sources operation
|
||||
/// Source could be Operand or Immediat
|
||||
/// Source could be Operand or Immediate
|
||||
#[instrument(level = "trace", skip(prog))]
|
||||
pub fn iop_addx(
|
||||
prog: &mut Program,
|
||||
@@ -191,7 +191,7 @@ pub fn iop_sub(prog: &mut Program) {
|
||||
let mut dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Src, 1);
|
||||
|
||||
// Add Comment header
|
||||
@@ -207,11 +207,11 @@ pub fn iop_subs(prog: &mut Program) {
|
||||
let mut dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("SUBS Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("SUBS Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic subx function
|
||||
iop_subx(prog, &mut dst, None, &src_a, &src_b);
|
||||
}
|
||||
@@ -224,7 +224,7 @@ pub fn iop_overflow_sub(prog: &mut Program) {
|
||||
let mut flag = prog.iop_template_var(OperandKind::Dst, 1);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Src, 1);
|
||||
|
||||
// Add Comment header
|
||||
@@ -241,18 +241,18 @@ pub fn iop_overflow_subs(prog: &mut Program) {
|
||||
let mut flag = prog.iop_template_var(OperandKind::Dst, 1);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("SUBS Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("SUBS Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic subx function
|
||||
iop_subx(prog, &mut dst, Some(&mut flag[0]), &src_a, &src_b);
|
||||
}
|
||||
|
||||
/// Generic sub operation
|
||||
/// One destination and two sources operation
|
||||
/// Source could be Operand or Immediat
|
||||
/// Source could be Operand or Immediate
|
||||
#[instrument(level = "trace", skip(prog))]
|
||||
pub fn iop_subx(
|
||||
prog: &mut Program,
|
||||
@@ -324,18 +324,18 @@ pub fn iop_ssub(prog: &mut Program) {
|
||||
let mut dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("SSUB Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("SSUB Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic subx function
|
||||
iop_ssubx(prog, &mut dst, None, &src_a, &src_b);
|
||||
}
|
||||
|
||||
/// Generic SSUB operation
|
||||
/// One destination and two sources operation
|
||||
/// Source could be Operand or Immediat
|
||||
/// Source could be Operand or Immediate
|
||||
#[instrument(level = "trace", skip(prog))]
|
||||
pub fn iop_ssubx(
|
||||
prog: &mut Program,
|
||||
@@ -406,11 +406,11 @@ pub fn iop_overflow_ssub(prog: &mut Program) {
|
||||
let mut flag = prog.iop_template_var(OperandKind::Dst, 1);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("SUBS Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("SUBS Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic ssubx function
|
||||
iop_ssubx(prog, &mut dst, Some(&mut flag[0]), &src_a, &src_b);
|
||||
}
|
||||
@@ -422,7 +422,7 @@ pub fn iop_mul(prog: &mut Program) {
|
||||
let mut dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Src, 1);
|
||||
|
||||
// Add Comment header
|
||||
@@ -437,11 +437,11 @@ pub fn iop_muls(prog: &mut Program) {
|
||||
let mut dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("MULS Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("MULS Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic mulx function
|
||||
iop_mulx(prog, &mut dst, None, &src_a, &src_b);
|
||||
}
|
||||
@@ -454,7 +454,7 @@ pub fn iop_overflow_mul(prog: &mut Program) {
|
||||
let mut flag = prog.iop_template_var(OperandKind::Dst, 1);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Src, 1);
|
||||
|
||||
// Add Comment header
|
||||
@@ -471,18 +471,18 @@ pub fn iop_overflow_muls(prog: &mut Program) {
|
||||
let mut flag = prog.iop_template_var(OperandKind::Dst, 1);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("MULS Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("MULS Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic mulx function
|
||||
iop_mulx(prog, &mut dst, Some(&mut flag[0]), &src_a, &src_b);
|
||||
}
|
||||
|
||||
/// Generic mul operation
|
||||
/// One destination and two sources operation
|
||||
/// Source could be Operand or Immediat
|
||||
/// Source could be Operand or Immediate
|
||||
#[instrument(level = "trace", skip(prog))]
|
||||
pub fn iop_mulx(
|
||||
prog: &mut Program,
|
||||
@@ -994,11 +994,11 @@ pub fn iop_shift_scalar_right(prog: &mut Program) {
|
||||
let mut dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// Src -> Operand
|
||||
let src = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// Amount-> Immediat
|
||||
// Amount-> Immediate
|
||||
let amount = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("SHIFTS_R Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("SHIFTS_R Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic rotx function
|
||||
iop_scalar_shiftrotx(prog, ShiftKind::ShiftRight, &mut dst, &src, &amount);
|
||||
}
|
||||
@@ -1010,11 +1010,11 @@ pub fn iop_shift_scalar_left(prog: &mut Program) {
|
||||
let mut dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// Src -> Operand
|
||||
let src = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// Amount-> Immediat
|
||||
// Amount-> Immediate
|
||||
let amount = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("SHIFTS_L Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("SHIFTS_L Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic rotx function
|
||||
iop_scalar_shiftrotx(prog, ShiftKind::ShiftLeft, &mut dst, &src, &amount);
|
||||
}
|
||||
@@ -1026,11 +1026,11 @@ pub fn iop_rotate_scalar_right(prog: &mut Program) {
|
||||
let mut dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// Src -> Operand
|
||||
let src = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// Amount-> Immediat
|
||||
// Amount-> Immediate
|
||||
let amount = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("ROTS_R Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("ROTS_R Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic rotx function
|
||||
iop_scalar_shiftrotx(prog, ShiftKind::RotRight, &mut dst, &src, &amount);
|
||||
}
|
||||
@@ -1041,11 +1041,11 @@ pub fn iop_rotate_scalar_left(prog: &mut Program) {
|
||||
let mut dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// Src -> Operand
|
||||
let src = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// Amount-> Immediat
|
||||
// Amount-> Immediate
|
||||
let amount = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("ROTS_L Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("ROTS_L Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic rotx function
|
||||
iop_scalar_shiftrotx(prog, ShiftKind::RotRight, &mut dst, &src, &amount);
|
||||
}
|
||||
@@ -1118,7 +1118,7 @@ pub fn iop_cmp(prog: &mut Program, cmp_op: Pbs) {
|
||||
|
||||
/// Generic Cmp operation
|
||||
/// One destination block and two sources operands
|
||||
/// Source could be Operand or Immediat
|
||||
/// Source could be Operand or Immediate
|
||||
#[instrument(level = "trace", skip(prog))]
|
||||
pub fn iop_cmpx(
|
||||
prog: &mut Program,
|
||||
|
||||
@@ -21,7 +21,7 @@ pub fn iop_div(prog: &mut Program) {
|
||||
let mut dst_remain = prog.iop_template_var(OperandKind::Dst, 1);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Src, 1);
|
||||
|
||||
// Add Comment header
|
||||
@@ -37,11 +37,11 @@ pub fn iop_divs(prog: &mut Program) {
|
||||
let mut dst_remain = prog.iop_template_var(OperandKind::Dst, 1);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("DIVS Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("DIVS Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic divx function
|
||||
// TODO: do computation on immediate directly for more efficiency.
|
||||
// Workaround: transform immediate into ct.
|
||||
@@ -52,7 +52,7 @@ pub fn iop_divs(prog: &mut Program) {
|
||||
|
||||
/// Generic div operation
|
||||
/// One destination and two sources operation
|
||||
/// Source could be Operand or Immediat
|
||||
/// Source could be Operand or Immediate
|
||||
pub fn iop_divx(
|
||||
prog: &mut Program,
|
||||
dst_quotient: &mut [metavar::MetaVarCell],
|
||||
@@ -80,7 +80,7 @@ pub fn iop_mod(prog: &mut Program) {
|
||||
let mut dst_remain = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Src, 1);
|
||||
|
||||
// Add Comment header
|
||||
@@ -95,11 +95,11 @@ pub fn iop_mods(prog: &mut Program) {
|
||||
let mut dst_remain = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("MODS Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("MODS Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
// Deferred implementation to generic modx function
|
||||
// TODO: do computation on immediate directly for more efficiency.
|
||||
// Workaround: transform immediate into ct.
|
||||
@@ -110,7 +110,7 @@ pub fn iop_mods(prog: &mut Program) {
|
||||
|
||||
/// Generic mod operation
|
||||
/// One destination and two sources operation
|
||||
/// Source could be Operand or Immediat
|
||||
/// Source could be Operand or Immediate
|
||||
pub fn iop_modx(
|
||||
prog: &mut Program,
|
||||
dst_remain: &mut [metavar::MetaVarCell],
|
||||
|
||||
@@ -98,7 +98,7 @@ pub fn iop_add(prog: &mut Program) {
|
||||
let dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Src, 1);
|
||||
|
||||
// Add Comment header
|
||||
@@ -123,11 +123,11 @@ pub fn iop_adds(prog: &mut Program) {
|
||||
let dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("ADDS Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("ADDS Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
iop_addx(prog, dst, src_a, src_b);
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ pub fn iop_sub(prog: &mut Program) {
|
||||
let dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Src, 1);
|
||||
|
||||
// Add Comment header
|
||||
@@ -152,11 +152,11 @@ pub fn iop_subs(prog: &mut Program) {
|
||||
let dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("SUBS Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("SUBS Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
iop_subx(prog, dst, src_a, src_b);
|
||||
}
|
||||
|
||||
@@ -166,11 +166,11 @@ pub fn iop_ssub(prog: &mut Program) {
|
||||
let dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Src, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("SSUB Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("SSUB Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
iop_subx(prog, dst, src_a, src_b);
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ pub fn iop_mul(prog: &mut Program) {
|
||||
let dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Src, 1);
|
||||
|
||||
// Add Comment header
|
||||
@@ -215,11 +215,11 @@ pub fn iop_muls(prog: &mut Program) {
|
||||
let dst = prog.iop_template_var(OperandKind::Dst, 0);
|
||||
// SrcA -> Operand
|
||||
let src_a = prog.iop_template_var(OperandKind::Src, 0);
|
||||
// SrcB -> Immediat
|
||||
// SrcB -> Immediate
|
||||
let src_b = prog.iop_template_var(OperandKind::Imm, 0);
|
||||
|
||||
// Add Comment header
|
||||
prog.push_comment("MULS Operand::Dst Operand::Src Operand::Immediat".to_string());
|
||||
prog.push_comment("MULS Operand::Dst Operand::Src Operand::Immediate".to_string());
|
||||
|
||||
iop_mulx(prog, dst, src_a, src_b).add_to_prog(prog);
|
||||
}
|
||||
@@ -534,7 +534,7 @@ pub fn iop_mulx(
|
||||
|
||||
/// Generic mul operation
|
||||
/// One destination and two sources operation
|
||||
/// Source could be Operand or Immediat
|
||||
/// Source could be Operand or Immediate
|
||||
#[instrument(level = "trace", skip(prog))]
|
||||
pub fn iop_mulx_ser(
|
||||
prog: &mut Program,
|
||||
@@ -654,7 +654,7 @@ pub fn iop_mulx_ser(
|
||||
|
||||
/// Generic Cmp operation
|
||||
/// One destination block and two sources operands
|
||||
/// Source could be Operand or Immediat
|
||||
/// Source could be Operand or Immediate
|
||||
#[instrument(level = "trace", skip(prog))]
|
||||
pub fn iop_cmpx(
|
||||
prog: &mut Program,
|
||||
@@ -673,7 +673,7 @@ pub fn iop_cmpx(
|
||||
|
||||
/// Generic Cmp operation
|
||||
/// One destination block and two sources operands
|
||||
/// Source could be Operand or Immediat
|
||||
/// Source could be Operand or Immediate
|
||||
#[instrument(level = "trace", skip(prog))]
|
||||
pub fn iop_cmpx_rtl(
|
||||
prog: &mut Program,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//!
|
||||
//! Provide two concrete implementation of those traits
|
||||
//! * DigitOperations (DOp)
|
||||
//! * IntegerOperarions (IOp)
|
||||
//! * IntegerOperations (IOp)
|
||||
|
||||
pub mod fw_impl;
|
||||
pub mod isc_sim;
|
||||
@@ -72,7 +72,7 @@ impl From<FwParameters> for asm::DigitParameters {
|
||||
}
|
||||
|
||||
/// Fw trait abstraction
|
||||
/// Use to handle Fw implemantion in an abstract way
|
||||
/// Use to handle Fw implementation in an abstract way
|
||||
#[enum_dispatch]
|
||||
pub trait Fw {
|
||||
/// Expand a program of IOp into a program of DOp
|
||||
|
||||
@@ -382,9 +382,9 @@ impl Program {
|
||||
}
|
||||
|
||||
/// Create templated arguments
|
||||
/// kind is used to specify if it's bind to src/dst or immediat template
|
||||
/// kind is used to specify if it's bind to src/dst or immediate template
|
||||
/// pos_id is used to bind the template to an IOp operand position
|
||||
// TODO pass the associated operand or immediat to obtain the inner blk properties instead of
|
||||
// TODO pass the associated operand or immediate to obtain the inner blk properties instead of
|
||||
// using the global one
|
||||
pub fn iop_template_var(&mut self, kind: asm::OperandKind, pos_id: u8) -> Vec<MetaVarCell> {
|
||||
let nb_blk = self.params().blk_w() as u8;
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
/// Help with IOp management over HPU
|
||||
/// Track IOp status and handle backward update of associated HpuVariable
|
||||
use super::*;
|
||||
use crate::asm::iop::{Immediat, Operand, OperandKind};
|
||||
use crate::asm::iop::{Immediate, Operand, OperandKind};
|
||||
use crate::asm::{IOp, IOpcode};
|
||||
use variable::HpuVarWrapped;
|
||||
|
||||
/// Underlying type used for Immediat value;
|
||||
/// Underlying type used for Immediate value;
|
||||
pub type HpuImm = u128;
|
||||
|
||||
/// Structure that hold an IOp with there associated operands
|
||||
@@ -15,7 +15,7 @@ pub struct HpuCmd {
|
||||
pub(crate) op: IOp,
|
||||
pub(crate) dst: Vec<HpuVarWrapped>,
|
||||
pub(crate) src: Vec<HpuVarWrapped>,
|
||||
// NB: No need to track Immediat lifetime. It's simply constant completely held by the IOp
|
||||
// NB: No need to track Immediate lifetime. It's simply constant completely held by the IOp
|
||||
// definition
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ impl HpuCmd {
|
||||
.collect::<Vec<_>>();
|
||||
let imm_op = imm
|
||||
.iter()
|
||||
.map(|var| Immediat::from_cst(*var))
|
||||
.map(|var| Immediate::from_cst(*var))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let op = IOp::new(opcode, dst_op, src_op, imm_op);
|
||||
|
||||
@@ -18,7 +18,7 @@ ipc-channel = "0.18.3"
|
||||
|
||||
strum = { version = "0.26.2", features = ["derive"] }
|
||||
strum_macros = "0.26.2"
|
||||
bytemuck = "1.16.0"
|
||||
bytemuck = { workspace = true }
|
||||
|
||||
clap = { version = "4.4.4", features = ["derive"] }
|
||||
clap-num = "*"
|
||||
|
||||
@@ -113,7 +113,7 @@ impl UCore {
|
||||
patch_imm(iop, imm);
|
||||
dop_patch
|
||||
}
|
||||
// TODO Patch immediat
|
||||
// TODO Patch immediate
|
||||
_ => dop_patch,
|
||||
}
|
||||
})
|
||||
@@ -126,7 +126,7 @@ impl UCore {
|
||||
}
|
||||
}
|
||||
|
||||
/// Utility function to patch immediat argument
|
||||
/// Utility function to patch immediate argument
|
||||
fn patch_imm(iop: &hpu_asm::IOp, imm: &mut hpu_asm::ImmId) {
|
||||
*imm = match imm {
|
||||
hpu_asm::ImmId::Cst(val) => hpu_asm::ImmId::Cst(*val),
|
||||
|
||||
64
scripts/install_typos.sh
Executable file
64
scripts/install_typos.sh
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
rust_toolchain=
|
||||
required_typos_version=""
|
||||
|
||||
function usage() {
|
||||
echo "$0: install typos-cli"
|
||||
echo
|
||||
echo "--help Print this message"
|
||||
echo "--rust-toolchain The toolchain to use"
|
||||
echo "--typos-version Version of typos-cli to install"
|
||||
echo
|
||||
}
|
||||
|
||||
while [ -n "$1" ]
|
||||
do
|
||||
case "$1" in
|
||||
"--rust-toolchain" )
|
||||
shift
|
||||
rust_toolchain="$1"
|
||||
;;
|
||||
|
||||
"--typos-version" )
|
||||
shift
|
||||
required_typos_version="$1"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown param : $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ "${rust_toolchain::1}" != "+" ]]; then
|
||||
rust_toolchain=${rust_toolchain:"+${rust_toolchain}"}
|
||||
fi
|
||||
|
||||
if ! which typos ; then
|
||||
cargo ${rust_toolchain:+"$rust_toolchain"} install --locked typos-cli --version ~"${required_typos_version}" || \
|
||||
( echo "Unable to install typos-cli, unknown error." && exit 1 )
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ver_string="$(typos --version | cut -d ' ' -f 2)"
|
||||
|
||||
ver_major="$(echo "${ver_string}" | cut -d '.' -f 1)"
|
||||
ver_minor="$(echo "${ver_string}" | cut -d '.' -f 2)"
|
||||
|
||||
min_ver_major="$(echo "${required_typos_version}" | cut -d '.' -f 1)"
|
||||
min_ver_minor="$(echo "${required_typos_version}" | cut -d '.' -f 2)"
|
||||
|
||||
if [[ "${ver_major}" -gt "${min_ver_major}" ]]; then
|
||||
exit 0
|
||||
elif [[ "${ver_major}" -eq "${min_ver_major}" ]] && [[ "${ver_minor}" -ge "${min_ver_minor}" ]]; then
|
||||
exit 0
|
||||
else
|
||||
cargo ${rust_toolchain:+"$rust_toolchain"} install --locked typos-cli --version ~"${required_typos_version}" || \
|
||||
( echo "Unable to install typos-cli, unknown error." && exit 1 )
|
||||
fi
|
||||
@@ -945,10 +945,10 @@ fn bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
let bench_id =
|
||||
format!("{bench_name}::throughput::{fn_name}::{type_name}::{num_elems}_elems");
|
||||
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
|
||||
let pendings_0_in = (0..num_elems)
|
||||
let pending_0_in = (0..num_elems)
|
||||
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
|
||||
.collect::<Vec<_>>();
|
||||
let pendings_1_in = (0..num_elems)
|
||||
let pending_1_in = (0..num_elems)
|
||||
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
|
||||
.collect::<Vec<_>>();
|
||||
let total_tokens_0_in = (0..num_elems).map(|_| rng.gen::<u64>()).collect::<Vec<_>>();
|
||||
@@ -969,9 +969,9 @@ fn bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
b.iter(|| {
|
||||
let (amounts_0_out, amounts_1_out): (Vec<_>, Vec<_>) = pendings_0_in
|
||||
let (amounts_0_out, amounts_1_out): (Vec<_>, Vec<_>) = pending_0_in
|
||||
.par_iter()
|
||||
.zip(pendings_1_in.par_iter())
|
||||
.zip(pending_1_in.par_iter())
|
||||
.zip(total_tokens_0_in.par_iter())
|
||||
.zip(total_tokens_1_in.par_iter())
|
||||
.zip(total_tokens_0_out.par_iter())
|
||||
@@ -1084,10 +1084,10 @@ fn cuda_bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
let bench_id =
|
||||
format!("{bench_name}::throughput::{fn_name}::{type_name}::{num_elems}_elems");
|
||||
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
|
||||
let pendings_0_in = (0..num_elems)
|
||||
let pending_0_in = (0..num_elems)
|
||||
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
|
||||
.collect::<Vec<_>>();
|
||||
let pendings_1_in = (0..num_elems)
|
||||
let pending_1_in = (0..num_elems)
|
||||
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
|
||||
.collect::<Vec<_>>();
|
||||
let total_tokens_0_in = (0..num_elems).map(|_| rng.gen::<u64>()).collect::<Vec<_>>();
|
||||
@@ -1116,9 +1116,9 @@ fn cuda_bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
let num_streams_per_gpu = 2.min(num_elems / num_gpus);
|
||||
let chunk_size = (num_elems / num_gpus) as usize;
|
||||
b.iter(|| {
|
||||
pendings_0_in
|
||||
pending_0_in
|
||||
.par_chunks(chunk_size)
|
||||
.zip(pendings_1_in.par_chunks(chunk_size))
|
||||
.zip(pending_1_in.par_chunks(chunk_size))
|
||||
.zip(total_tokens_0_in.par_chunks(chunk_size))
|
||||
.zip(total_tokens_1_in.par_chunks(chunk_size))
|
||||
.zip(total_tokens_0_out.par_chunks(chunk_size))
|
||||
@@ -1131,7 +1131,7 @@ fn cuda_bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
(
|
||||
(
|
||||
(
|
||||
(pendings_0_in_gpu_i, pendings_1_in_gpu_i),
|
||||
(pending_0_in_gpu_i, pending_1_in_gpu_i),
|
||||
total_tokens_0_in_gpu_i,
|
||||
),
|
||||
total_tokens_1_in_gpu_i,
|
||||
@@ -1142,10 +1142,10 @@ fn cuda_bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
),
|
||||
)| {
|
||||
let stream_chunk_size =
|
||||
pendings_0_in_gpu_i.len() / num_streams_per_gpu as usize;
|
||||
pendings_0_in_gpu_i
|
||||
pending_0_in_gpu_i.len() / num_streams_per_gpu as usize;
|
||||
pending_0_in_gpu_i
|
||||
.par_chunks(stream_chunk_size)
|
||||
.zip(pendings_1_in_gpu_i.par_chunks(stream_chunk_size))
|
||||
.zip(pending_1_in_gpu_i.par_chunks(stream_chunk_size))
|
||||
.zip(total_tokens_0_in_gpu_i.par_chunks(stream_chunk_size))
|
||||
.zip(total_tokens_1_in_gpu_i.par_chunks(stream_chunk_size))
|
||||
.zip(total_tokens_0_out_gpu_i.par_chunks(stream_chunk_size))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tfhe-zk-pok"
|
||||
version = "0.7.3"
|
||||
version = "0.7.4"
|
||||
edition = "2021"
|
||||
keywords = ["zero", "knowledge", "proof", "vector-commitments"]
|
||||
homepage = "https://zama.ai/"
|
||||
|
||||
@@ -416,3 +416,27 @@ pub mod g2 {
|
||||
/// 107680854723992552431070996218129928499826544031468382031848626814251381379173928074140221537929995580031433096217223703806029068859074
|
||||
pub const G2_GENERATOR_Y_C1: Fq = MontFp!("107680854723992552431070996218129928499826544031468382031848626814251381379173928074140221537929995580031433096217223703806029068859074");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::serialization::{InvalidFpError, SerializableFp};
|
||||
|
||||
use super::Fq;
|
||||
use ark_ff::Field;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
// This one is only used to have the correct number of serialized bytes
|
||||
let a = Fq::ONE;
|
||||
let s: SerializableFp = a.into();
|
||||
|
||||
let mut data = vec![];
|
||||
bincode::serialize_into(&mut data, &s).unwrap();
|
||||
// First u64 is the vec size
|
||||
data[std::mem::size_of::<u64>()..].fill(u8::MAX);
|
||||
|
||||
let s2: SerializableFp = bincode::deserialize(&data).unwrap();
|
||||
let a2 = Fq::try_from(s2);
|
||||
assert!(matches!(a2, Err(InvalidFpError::GreaterThanModulus)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,7 +529,7 @@ mod g2 {
|
||||
}
|
||||
|
||||
mod gt {
|
||||
use crate::serialization::InvalidArraySizeError;
|
||||
use crate::serialization::InvalidFpError;
|
||||
|
||||
use super::*;
|
||||
use ark_ec::pairing::Pairing;
|
||||
@@ -550,7 +550,7 @@ mod gt {
|
||||
}
|
||||
|
||||
impl TryFrom<SerializableFp12> for Gt {
|
||||
type Error = InvalidArraySizeError;
|
||||
type Error = InvalidFpError;
|
||||
|
||||
fn try_from(value: SerializableFp12) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
@@ -682,7 +682,7 @@ mod gt {
|
||||
}
|
||||
|
||||
mod zp {
|
||||
use crate::serialization::InvalidArraySizeError;
|
||||
use crate::serialization::InvalidFpError;
|
||||
|
||||
use super::*;
|
||||
use ark_ff::Fp;
|
||||
@@ -737,7 +737,7 @@ mod zp {
|
||||
}
|
||||
}
|
||||
impl TryFrom<SerializableFp> for Zp {
|
||||
type Error = InvalidArraySizeError;
|
||||
type Error = InvalidFpError;
|
||||
|
||||
fn try_from(value: SerializableFp) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
|
||||
@@ -958,7 +958,7 @@ mod gt {
|
||||
mod zp {
|
||||
use super::*;
|
||||
use crate::curve_446::FrConfig;
|
||||
use crate::serialization::InvalidArraySizeError;
|
||||
use crate::serialization::InvalidFpError;
|
||||
use ark_ff::{Fp, FpConfig, MontBackend, PrimeField};
|
||||
use tfhe_versionable::Versionize;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
@@ -1013,7 +1013,7 @@ mod zp {
|
||||
}
|
||||
}
|
||||
impl TryFrom<SerializableFp> for Zp {
|
||||
type Error = InvalidArraySizeError;
|
||||
type Error = InvalidFpError;
|
||||
|
||||
fn try_from(value: SerializableFp) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
|
||||
@@ -12,7 +12,9 @@ use crate::backward_compatibility::{
|
||||
};
|
||||
use ark_ec::short_weierstrass::{Affine, SWCurveConfig};
|
||||
use ark_ec::AffineRepr;
|
||||
use ark_ff::{BigInt, Field, Fp, Fp2, Fp6, Fp6Config, FpConfig, QuadExtConfig, QuadExtField};
|
||||
use ark_ff::{
|
||||
BigInt, Field, Fp, Fp2, Fp6, Fp6Config, FpConfig, PrimeField, QuadExtConfig, QuadExtField,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tfhe_versionable::Versionize;
|
||||
|
||||
@@ -47,6 +49,34 @@ impl Display for InvalidArraySizeError {
|
||||
|
||||
impl Error for InvalidArraySizeError {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum InvalidFpError {
|
||||
InvalidArraySizeError(InvalidArraySizeError),
|
||||
GreaterThanModulus,
|
||||
}
|
||||
|
||||
impl From<InvalidArraySizeError> for InvalidFpError {
|
||||
fn from(value: InvalidArraySizeError) -> Self {
|
||||
Self::InvalidArraySizeError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for InvalidFpError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::InvalidArraySizeError(e) => e.fmt(f),
|
||||
Self::GreaterThanModulus => {
|
||||
write!(
|
||||
f,
|
||||
"The deserialized value was bigger than what its type modulus allowed"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for InvalidFpError {}
|
||||
|
||||
/// Tries to convert a Vec into a constant size array, and returns an [`InvalidArraySizeError`] if
|
||||
/// the size does not match
|
||||
pub(crate) fn try_vec_to_array<T, const N: usize>(
|
||||
@@ -77,16 +107,20 @@ impl<P: FpConfig<N>, const N: usize> From<Fp<P, N>> for SerializableFp {
|
||||
}
|
||||
|
||||
impl<P: FpConfig<N>, const N: usize> TryFrom<SerializableFp> for Fp<P, N> {
|
||||
type Error = InvalidArraySizeError;
|
||||
type Error = InvalidFpError;
|
||||
|
||||
fn try_from(value: SerializableFp) -> Result<Self, Self::Error> {
|
||||
Ok(Fp(BigInt(try_vec_to_array(value.val)?), PhantomData))
|
||||
let fp = BigInt(try_vec_to_array(value.val)?);
|
||||
if fp >= Fp::<P, N>::MODULUS {
|
||||
return Err(InvalidFpError::GreaterThanModulus);
|
||||
}
|
||||
Ok(Fp(fp, PhantomData))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum InvalidSerializedAffineError {
|
||||
InvalidFp(InvalidArraySizeError),
|
||||
InvalidFp(InvalidFpError),
|
||||
InvalidCompressedXCoordinate,
|
||||
}
|
||||
|
||||
@@ -115,8 +149,8 @@ impl Error for InvalidSerializedAffineError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InvalidArraySizeError> for InvalidSerializedAffineError {
|
||||
fn from(value: InvalidArraySizeError) -> Self {
|
||||
impl From<InvalidFpError> for InvalidSerializedAffineError {
|
||||
fn from(value: InvalidFpError) -> Self {
|
||||
Self::InvalidFp(value)
|
||||
}
|
||||
}
|
||||
@@ -163,7 +197,7 @@ impl<F> SerializableAffine<F> {
|
||||
|
||||
impl<F, C: SWCurveConfig> TryFrom<SerializableAffine<F>> for Affine<C>
|
||||
where
|
||||
F: TryInto<C::BaseField, Error = InvalidArraySizeError>,
|
||||
F: TryInto<C::BaseField, Error = InvalidFpError>,
|
||||
{
|
||||
type Error = InvalidSerializedAffineError;
|
||||
|
||||
@@ -207,9 +241,9 @@ where
|
||||
|
||||
impl<F, P: QuadExtConfig> TryFrom<SerializableQuadExtField<F>> for QuadExtField<P>
|
||||
where
|
||||
F: TryInto<P::BaseField, Error = InvalidArraySizeError>,
|
||||
F: TryInto<P::BaseField, Error = InvalidFpError>,
|
||||
{
|
||||
type Error = InvalidArraySizeError;
|
||||
type Error = InvalidFpError;
|
||||
|
||||
fn try_from(value: SerializableQuadExtField<F>) -> Result<Self, Self::Error> {
|
||||
Ok(QuadExtField {
|
||||
@@ -244,9 +278,9 @@ where
|
||||
|
||||
impl<F, P6: Fp6Config> TryFrom<SerializableCubicExtField<F>> for Fp6<P6>
|
||||
where
|
||||
F: TryInto<Fp2<P6::Fp2Config>, Error = InvalidArraySizeError>,
|
||||
F: TryInto<Fp2<P6::Fp2Config>, Error = InvalidFpError>,
|
||||
{
|
||||
type Error = InvalidArraySizeError;
|
||||
type Error = InvalidFpError;
|
||||
|
||||
fn try_from(value: SerializableCubicExtField<F>) -> Result<Self, Self::Error> {
|
||||
Ok(Fp6 {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tfhe"
|
||||
version = "1.4.0-alpha.3"
|
||||
version = "1.4.0-alpha.4"
|
||||
edition = "2021"
|
||||
readme = "../README.md"
|
||||
keywords = ["fully", "homomorphic", "encryption", "fhe", "cryptography"]
|
||||
@@ -77,7 +77,7 @@ blake3 = { version = "1.8", optional = true }
|
||||
itertools = { workspace = true }
|
||||
rand_core = { version = "0.6.4", features = ["std"] }
|
||||
strum = { version = "0.27", features = ["derive"], optional = true }
|
||||
tfhe-zk-pok = { version = "0.7.3", path = "../tfhe-zk-pok", optional = true }
|
||||
tfhe-zk-pok = { version = "0.7.4", path = "../tfhe-zk-pok", optional = true }
|
||||
tfhe-versionable = { version = "0.6.2", path = "../utils/tfhe-versionable" }
|
||||
|
||||
# wasm deps
|
||||
|
||||
@@ -127,7 +127,7 @@ $ cargo run --release
|
||||
|
||||
You can learn more about homomorphic types and associated compilation features in the [configuration documentation.](../configuration/rust-configuration.md)
|
||||
|
||||
## Perforance tips
|
||||
## Performance tips
|
||||
Performance can be further improved by setting `lto="fat"` in `Cargo.toml`
|
||||
```toml
|
||||
[profile.release]
|
||||
|
||||
@@ -56,7 +56,7 @@ pub struct Args {
|
||||
#[arg(long, value_parser = maybe_hex::<u128>)]
|
||||
pub src: Vec<u128>,
|
||||
|
||||
/// Force immediat input values
|
||||
/// Force immediate input values
|
||||
#[arg(long, value_parser = maybe_hex::<u128>)]
|
||||
pub imm: Vec<u128>,
|
||||
|
||||
|
||||
@@ -92,8 +92,8 @@ pub enum Candidate {
|
||||
}
|
||||
|
||||
pub enum CandidateResult {
|
||||
SatisfiyingBound(Candidate),
|
||||
BestNotSatisfiyingBound(Candidate),
|
||||
SatisfyingBound(Candidate),
|
||||
BestNotSatisfyingBound(Candidate),
|
||||
}
|
||||
|
||||
pub fn choose_candidate_to_improve_modulus_switch_noise_for_binary_key<Scalar, C1, C2>(
|
||||
@@ -155,7 +155,7 @@ where
|
||||
let mut best_measure = base_measure;
|
||||
|
||||
if base_measure <= bound.0 {
|
||||
return CandidateResult::SatisfiyingBound(best_candidate);
|
||||
return CandidateResult::SatisfyingBound(best_candidate);
|
||||
}
|
||||
|
||||
for (index, encryption_of_zero) in encryptions_of_zero.iter().enumerate() {
|
||||
@@ -187,11 +187,11 @@ where
|
||||
}
|
||||
|
||||
if measure <= bound.0 {
|
||||
return CandidateResult::SatisfiyingBound(best_candidate);
|
||||
return CandidateResult::SatisfyingBound(best_candidate);
|
||||
}
|
||||
}
|
||||
|
||||
CandidateResult::BestNotSatisfiyingBound(best_candidate)
|
||||
CandidateResult::BestNotSatisfyingBound(best_candidate)
|
||||
}
|
||||
|
||||
/// This function can be called before doing a modulus switch.
|
||||
@@ -222,13 +222,13 @@ pub fn improve_lwe_ciphertext_modulus_switch_noise_for_binary_key<Scalar, C1, C2
|
||||
|
||||
#[cfg(test)]
|
||||
assert!(
|
||||
matches!(candidate, CandidateResult::SatisfiyingBound(_)),
|
||||
matches!(candidate, CandidateResult::SatisfyingBound(_)),
|
||||
"MS noise reduction bound not reached for any candidate"
|
||||
);
|
||||
|
||||
let candidate = match candidate {
|
||||
CandidateResult::SatisfiyingBound(candidate) => candidate,
|
||||
CandidateResult::BestNotSatisfiyingBound(candidate) => candidate,
|
||||
CandidateResult::SatisfyingBound(candidate) => candidate,
|
||||
CandidateResult::BestNotSatisfyingBound(candidate) => candidate,
|
||||
};
|
||||
|
||||
match candidate {
|
||||
|
||||
@@ -292,8 +292,8 @@ fn improve_modulus_switch_noise_test_average_number_checks(params: MsNoiseReduct
|
||||
input_variance,
|
||||
log_modulus,
|
||||
) {
|
||||
CandidateResult::SatisfiyingBound(candidate) => candidate,
|
||||
CandidateResult::BestNotSatisfiyingBound(_) => {
|
||||
CandidateResult::SatisfyingBound(candidate) => candidate,
|
||||
CandidateResult::BestNotSatisfyingBound(_) => {
|
||||
panic!("No candidate was good enough")
|
||||
}
|
||||
};
|
||||
|
||||
@@ -62,7 +62,7 @@ pub struct LweSize(pub usize);
|
||||
impl LweSize {
|
||||
/// Return the associated [`LweDimension`].
|
||||
pub fn to_lwe_dimension(&self) -> LweDimension {
|
||||
LweDimension(self.0 - 1)
|
||||
LweDimension(self.0.saturating_sub(1))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ pub struct LweDimension(pub usize);
|
||||
impl LweDimension {
|
||||
/// Return the associated [`LweSize`].
|
||||
pub fn to_lwe_size(&self) -> LweSize {
|
||||
LweSize(self.0 + 1)
|
||||
LweSize(self.0.saturating_add(1))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,3 +399,26 @@ pub struct NoiseEstimationMeasureBound(pub f64);
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Versionize)]
|
||||
#[versionize(ChunkSizeVersions)]
|
||||
pub struct ChunkSize(pub usize);
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_bad_lwe_size() {
|
||||
// Check that it does not underflow
|
||||
let lwe_size = LweSize(0);
|
||||
|
||||
let lwe_dim = lwe_size.to_lwe_dimension();
|
||||
assert_eq!(lwe_dim.0, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bad_lwe_dimension() {
|
||||
// Check that it does not overflow
|
||||
let lwe_dim = LweDimension(usize::MAX);
|
||||
|
||||
let lwe_size = lwe_dim.to_lwe_size();
|
||||
assert_eq!(lwe_size.0, usize::MAX);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,8 +534,8 @@ impl<Scalar: UnsignedInteger + CastInto<usize> + CastFrom<usize>> ParameterSetCo
|
||||
&& lwe_ct_parameters.ct_modulus.is_power_of_two()
|
||||
&& match lwe_ct_parameters.ms_decompression_method {
|
||||
MsDecompressionType::ClassicPbs => false,
|
||||
MsDecompressionType::MultiBitPbs(expected_gouping_factor) => {
|
||||
expected_gouping_factor.0 == grouping_factor.0
|
||||
MsDecompressionType::MultiBitPbs(expected_grouping_factor) => {
|
||||
expected_grouping_factor.0 == grouping_factor.0
|
||||
}
|
||||
}
|
||||
&& *uncompressed_ciphertext_modulus == lwe_ct_parameters.ct_modulus
|
||||
|
||||
@@ -46,14 +46,20 @@ pub fn lwe_compact_ciphertext_list_mask_count(
|
||||
lwe_dimension: LweDimension,
|
||||
lwe_ciphertext_count: LweCiphertextCount,
|
||||
) -> LweMaskCount {
|
||||
LweMaskCount(
|
||||
lwe_ciphertext_count.0 / lwe_dimension.0
|
||||
+ if lwe_ciphertext_count.0 % lwe_dimension.0 == 0 {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
},
|
||||
)
|
||||
if lwe_dimension.0 == 0 {
|
||||
return LweMaskCount(0);
|
||||
}
|
||||
|
||||
let base = lwe_ciphertext_count.0 / lwe_dimension.0;
|
||||
let remainder = if lwe_ciphertext_count.0 % lwe_dimension.0 == 0 {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
};
|
||||
|
||||
// Cannot overflow since base can only be equal to usize::MAX if lwe_ciphertext_count is
|
||||
// usize::MAX and lwe_dimension is 1, and in that case remainder is 0
|
||||
LweMaskCount(base + remainder)
|
||||
}
|
||||
|
||||
pub fn lwe_compact_ciphertext_list_size(
|
||||
@@ -395,3 +401,19 @@ impl<Scalar: UnsignedInteger> LweCompactCiphertextListOwned<Scalar> {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_bad_lwe_list_mask_count() {
|
||||
let lwe_dim = LweDimension(0);
|
||||
let lwe_ct_count = LweCiphertextCount(33);
|
||||
|
||||
assert_eq!(
|
||||
lwe_compact_ciphertext_list_mask_count(lwe_dim, lwe_ct_count).0,
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1159,6 +1159,23 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_list() {
|
||||
let config = crate::ConfigBuilder::default().build();
|
||||
|
||||
let ck = crate::ClientKey::generate(config);
|
||||
let sk = crate::ServerKey::new(&ck);
|
||||
let pk = crate::CompactPublicKey::new(&ck);
|
||||
|
||||
set_server_key(sk);
|
||||
|
||||
let compact_list = CompactCiphertextList::builder(&pk).build_packed();
|
||||
|
||||
let expander = compact_list.expand().unwrap();
|
||||
|
||||
assert!(expander.get::<FheBool>(0).unwrap().is_none());
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
#[test]
|
||||
fn test_gpu_compact_list() {
|
||||
@@ -1455,6 +1472,39 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "zk-pok")]
|
||||
#[test]
|
||||
fn test_empty_proven_list() {
|
||||
let config = crate::ConfigBuilder::with_custom_parameters(
|
||||
PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
)
|
||||
.use_dedicated_compact_public_key_parameters((
|
||||
PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
))
|
||||
.build();
|
||||
|
||||
let ck = crate::ClientKey::generate(config);
|
||||
let sk = crate::ServerKey::new(&ck);
|
||||
let pk = crate::CompactPublicKey::new(&ck);
|
||||
|
||||
set_server_key(sk);
|
||||
|
||||
let crs = CompactPkeCrs::from_config(config, 32).unwrap();
|
||||
|
||||
let metadata = [b'h', b'l', b'a', b'p', b'i'];
|
||||
|
||||
let compact_list = CompactCiphertextList::builder(&pk)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let expander = compact_list
|
||||
.verify_and_expand(&crs, &pk, &metadata)
|
||||
.unwrap();
|
||||
|
||||
assert!(expander.get::<FheBool>(0).unwrap().is_none());
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "zk-pok", feature = "gpu"))]
|
||||
#[test]
|
||||
fn test_gpu_proven_compact_list() {
|
||||
|
||||
@@ -94,7 +94,7 @@ impl<Id: FheUintId> FheUint<Id> {
|
||||
}
|
||||
/// Generates an encrypted `num_block` blocks unsigned integer
|
||||
/// taken uniformly in `[0, 2^random_bits_count[` using the given seed.
|
||||
/// The encryted value is oblivious to the server.
|
||||
/// The encrypted value is oblivious to the server.
|
||||
/// It can be useful to make server random generation deterministic.
|
||||
///
|
||||
/// ```rust
|
||||
@@ -188,7 +188,7 @@ impl<Id: FheUintId> FheUint<Id> {
|
||||
impl<Id: FheIntId> FheInt<Id> {
|
||||
/// Generates an encrypted signed integer
|
||||
/// taken uniformly in its full range using the given seed.
|
||||
/// The encryted value is oblivious to the server.
|
||||
/// The encrypted value is oblivious to the server.
|
||||
/// It can be useful to make server random generation deterministic.
|
||||
///
|
||||
/// ```rust
|
||||
@@ -275,7 +275,7 @@ impl<Id: FheIntId> FheInt<Id> {
|
||||
}
|
||||
/// Generates an encrypted `num_block` blocks signed integer
|
||||
/// taken uniformly in `[0, 2^random_bits_count[` using the given seed.
|
||||
/// The encryted value is oblivious to the server.
|
||||
/// The encrypted value is oblivious to the server.
|
||||
/// It can be useful to make server random generation deterministic.
|
||||
///
|
||||
/// ```rust
|
||||
|
||||
@@ -10,7 +10,6 @@ use crate::integer::BooleanBlock;
|
||||
#[cfg(feature = "zk-pok")]
|
||||
use crate::integer::ProvenCompactCiphertextList;
|
||||
use crate::shortint::ciphertext::CompressedModulusSwitchedCiphertext;
|
||||
use std::convert::Infallible;
|
||||
use std::num::NonZero;
|
||||
use tfhe_versionable::{Upgrade, Version, VersionsDispatch};
|
||||
|
||||
@@ -36,15 +35,24 @@ pub struct CompactCiphertextListV0 {
|
||||
}
|
||||
|
||||
impl Upgrade<CompactCiphertextList> for CompactCiphertextListV0 {
|
||||
type Error = Infallible;
|
||||
type Error = crate::Error;
|
||||
|
||||
fn upgrade(self) -> Result<CompactCiphertextList, Self::Error> {
|
||||
let radix_count =
|
||||
self.ct_list.ct_list.lwe_ciphertext_count().0 / self.num_blocks_per_integer;
|
||||
let lwe_count = self.ct_list.ct_list.lwe_ciphertext_count().0;
|
||||
|
||||
if !lwe_count % self.num_blocks_per_integer == 0 {
|
||||
return Err(crate::error!("Invalid CompactCiphertextListV0, the total lwe count should be a multiple of num_blocks_per_integer"));
|
||||
}
|
||||
|
||||
let radix_count = lwe_count
|
||||
.checked_div(self.num_blocks_per_integer)
|
||||
.ok_or_else(|| {
|
||||
crate::error!("Invalid CompactCiphertextListV0, num_blocks_per_integer is 0")
|
||||
})?;
|
||||
|
||||
// Since we can't guess the type of data here, we set them by default as unsigned integer.
|
||||
// Since it this data comes from 0.6, if it is included in a homogeneous compact list it
|
||||
// will be converted to the right type at expand time.
|
||||
|
||||
let info = NonZero::new(self.num_blocks_per_integer)
|
||||
.map(|n| vec![DataKind::Unsigned(n); radix_count])
|
||||
.unwrap_or_default();
|
||||
|
||||
@@ -923,6 +923,10 @@ impl CompactCiphertextList {
|
||||
&self,
|
||||
expansion_mode: IntegerCompactCiphertextListExpansionMode<'_>,
|
||||
) -> crate::Result<CompactCiphertextListExpander> {
|
||||
if self.is_empty() {
|
||||
return Ok(CompactCiphertextListExpander::new(vec![], vec![]));
|
||||
}
|
||||
|
||||
let is_packed = self.is_packed();
|
||||
|
||||
let expanded_blocks = expansion_helper(
|
||||
@@ -952,17 +956,27 @@ impl CompactCiphertextList {
|
||||
self.ct_list.message_modulus
|
||||
}
|
||||
|
||||
/// Computes the expected number of blocks based on the `info` metadata.
|
||||
///
|
||||
/// Returns an error if the sum overflows
|
||||
fn expected_num_block(&self) -> Result<usize, ()> {
|
||||
DataKind::total_block_count(&self.info, self.message_modulus())
|
||||
}
|
||||
|
||||
fn is_conformant_with_shortint_params(
|
||||
&self,
|
||||
shortint_params: CiphertextConformanceParams,
|
||||
) -> bool {
|
||||
let Self { ct_list, info } = self;
|
||||
let Self {
|
||||
ct_list,
|
||||
info: _info,
|
||||
} = self;
|
||||
|
||||
let Ok(mut num_blocks) = self.expected_num_block() else {
|
||||
// Return early if the sum overflowed
|
||||
return false;
|
||||
};
|
||||
|
||||
let mut num_blocks: usize = info
|
||||
.iter()
|
||||
.copied()
|
||||
.map(|kind| kind.num_blocks(self.message_modulus()))
|
||||
.sum();
|
||||
// This expects packing, halve the number of blocks with enough capacity
|
||||
if shortint_params.degree.get()
|
||||
== (shortint_params.message_modulus.0 * shortint_params.carry_modulus.0) - 1
|
||||
@@ -1077,6 +1091,10 @@ impl ProvenCompactCiphertextList {
|
||||
}
|
||||
|
||||
pub fn needs_casting(&self) -> bool {
|
||||
if self.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.ct_list.proved_lists[0].0.needs_casting()
|
||||
}
|
||||
|
||||
@@ -1099,6 +1117,13 @@ impl ProvenCompactCiphertextList {
|
||||
pub fn get_kind_of(&self, index: usize) -> Option<DataKind> {
|
||||
self.info.get(index).copied()
|
||||
}
|
||||
|
||||
/// Computes the expected number of blocks based on the `info` metadata.
|
||||
///
|
||||
/// Returns an error if the sum overflows
|
||||
fn expected_num_block(&self) -> Result<usize, ()> {
|
||||
DataKind::total_block_count(&self.info, self.message_modulus())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "zk-pok")]
|
||||
@@ -1166,6 +1191,14 @@ impl ParameterSetConformant for ProvenCompactCiphertextList {
|
||||
fn is_conformant(&self, parameter_set: &Self::ParameterSet) -> bool {
|
||||
let Self { ct_list, info } = self;
|
||||
|
||||
// Early return if the list is considered empty
|
||||
match (ct_list.proved_lists.is_empty(), info.is_empty()) {
|
||||
(true, true) => return true,
|
||||
(true, false) => return false,
|
||||
(false, true) => return false,
|
||||
(false, false) => {}
|
||||
}
|
||||
|
||||
let is_packed = self.is_packed();
|
||||
|
||||
let all_have_same_packing = ct_list
|
||||
@@ -1177,10 +1210,10 @@ impl ParameterSetConformant for ProvenCompactCiphertextList {
|
||||
return false;
|
||||
}
|
||||
|
||||
let total_expected_num_blocks: usize = info
|
||||
.iter()
|
||||
.map(|a| a.num_blocks(self.message_modulus()))
|
||||
.sum();
|
||||
let Ok(total_expected_num_blocks) = self.expected_num_block() else {
|
||||
// Return early if the sum overflowed
|
||||
return false;
|
||||
};
|
||||
|
||||
let total_expected_lwe_count =
|
||||
total_expected_num_blocks.div_ceil(if is_packed { 2 } else { 1 });
|
||||
@@ -1299,7 +1332,7 @@ mod zk_pok_tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_list() {
|
||||
fn test_zk_empty_list() {
|
||||
let pke_params = PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let ksk_params = PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let fhe_params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
@@ -1313,6 +1346,11 @@ mod zk_pok_tests {
|
||||
let ksk = KeySwitchingKey::new((&compact_private_key, None), (&cks, &sk), ksk_params);
|
||||
let pk = CompactPublicKey::new(&compact_private_key);
|
||||
|
||||
let conformance_params =
|
||||
IntegerProvenCompactCiphertextListConformanceParams::from_crs_and_parameters(
|
||||
pke_params, &crs,
|
||||
);
|
||||
|
||||
// Test by pushing with zero blocks
|
||||
{
|
||||
let proven_ct = CompactCiphertextList::builder(&pk)
|
||||
@@ -1327,6 +1365,7 @@ mod zk_pok_tests {
|
||||
proven_ct.verify(&crs, &pk, &metadata),
|
||||
ZkVerificationOutcome::Valid
|
||||
);
|
||||
assert!(proven_ct.is_conformant(&conformance_params));
|
||||
assert!(matches!(
|
||||
proven_ct.verify_and_expand(
|
||||
&crs,
|
||||
@@ -1350,6 +1389,7 @@ mod zk_pok_tests {
|
||||
proven_ct.verify(&crs, &pk, &metadata),
|
||||
ZkVerificationOutcome::Valid
|
||||
);
|
||||
assert!(proven_ct.is_conformant(&conformance_params));
|
||||
assert!(matches!(
|
||||
proven_ct.verify_and_expand(
|
||||
&crs,
|
||||
@@ -1360,6 +1400,32 @@ mod zk_pok_tests {
|
||||
Ok(vec) if vec.is_empty()
|
||||
));
|
||||
}
|
||||
|
||||
// Test with empty ct vec and not empty info vec
|
||||
{
|
||||
let mut proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.push(1u8)
|
||||
.push(-1i8)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
proven_ct.ct_list.proved_lists = Vec::new();
|
||||
|
||||
assert!(!proven_ct.is_conformant(&conformance_params));
|
||||
}
|
||||
|
||||
// Test with not empty ct vec and empty info vec
|
||||
{
|
||||
let mut proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.push(1u8)
|
||||
.push(-1i8)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
proven_ct.info = Vec::new();
|
||||
|
||||
assert!(!proven_ct.is_conformant(&conformance_params));
|
||||
}
|
||||
}
|
||||
|
||||
/// In this test we check the behavior of the proven list when the info vec
|
||||
|
||||
@@ -25,11 +25,32 @@ impl DataKind {
|
||||
Self::Unsigned(n) | Self::Signed(n) => n.get(),
|
||||
Self::Boolean => 1,
|
||||
Self::String { n_chars, .. } => {
|
||||
if message_modulus.0 == 0 || message_modulus.0 == 1 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let blocks_per_char = 7u32.div_ceil(message_modulus.0.ilog2());
|
||||
(n_chars * blocks_per_char) as usize
|
||||
// Use saturating mul to avoid panic here, maybe on the long run this function
|
||||
// should return a Result
|
||||
n_chars.saturating_mul(blocks_per_char) as usize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn total_block_count(
|
||||
info: &[Self],
|
||||
message_modulus: MessageModulus,
|
||||
) -> Result<usize, ()> {
|
||||
if message_modulus.0 == 0 {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
info.iter()
|
||||
.try_fold(0usize, |acc, &x| {
|
||||
acc.checked_add(x.num_blocks(message_modulus))
|
||||
})
|
||||
.ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Expandable: Sized {
|
||||
@@ -80,3 +101,33 @@ impl Expandable for BooleanBlock {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
/// Check that strings num_blocks does not panic
|
||||
#[test]
|
||||
fn test_string_num_blocks() {
|
||||
let kind = DataKind::String {
|
||||
n_chars: 10,
|
||||
padded: true,
|
||||
};
|
||||
|
||||
let num_blocks = kind.num_blocks(MessageModulus(0));
|
||||
|
||||
assert_eq!(num_blocks, 0);
|
||||
|
||||
let num_blocks = kind.num_blocks(MessageModulus(1));
|
||||
|
||||
assert_eq!(num_blocks, 0);
|
||||
|
||||
let kind = DataKind::String {
|
||||
n_chars: u32::MAX,
|
||||
padded: true,
|
||||
};
|
||||
|
||||
let num_blocks = kind.num_blocks(MessageModulus(2));
|
||||
assert_eq!(num_blocks, u32::MAX as usize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::integer::gpu::{get_grouped_oprf_size_on_gpu, grouped_oprf_async, Cuda
|
||||
impl CudaServerKey {
|
||||
/// Generates an encrypted `num_block` blocks unsigned integer
|
||||
/// taken uniformly in its full range using the given seed.
|
||||
/// The encryted value is oblivious to the server.
|
||||
/// The encrypted value is oblivious to the server.
|
||||
/// It can be useful to make server random generation deterministic.
|
||||
///
|
||||
/// ```rust
|
||||
@@ -56,7 +56,7 @@ impl CudaServerKey {
|
||||
|
||||
/// Generates an encrypted `num_block` blocks unsigned integer
|
||||
/// taken uniformly in `[0, 2^random_bits_count[` using the given seed.
|
||||
/// The encryted value is oblivious to the server.
|
||||
/// The encrypted value is oblivious to the server.
|
||||
/// It can be useful to make server random generation deterministic.
|
||||
///
|
||||
/// ```rust
|
||||
@@ -115,7 +115,7 @@ impl CudaServerKey {
|
||||
|
||||
/// Generates an encrypted `num_block` blocks signed integer
|
||||
/// taken uniformly in its full range using the given seed.
|
||||
/// The encryted value is oblivious to the server.
|
||||
/// The encrypted value is oblivious to the server.
|
||||
/// It can be useful to make server random generation deterministic.
|
||||
///
|
||||
/// ```rust
|
||||
@@ -155,7 +155,7 @@ impl CudaServerKey {
|
||||
|
||||
/// Generates an encrypted `num_block` blocks signed integer
|
||||
/// taken uniformly in `[0, 2^random_bits_count[` using the given seed.
|
||||
/// The encryted value is oblivious to the server.
|
||||
/// The encrypted value is oblivious to the server.
|
||||
/// It can be useful to make server random generation deterministic.
|
||||
///
|
||||
/// ```rust
|
||||
|
||||
@@ -8,7 +8,7 @@ pub use tfhe_csprng::seeders::{Seed, Seeder};
|
||||
impl ServerKey {
|
||||
/// Generates an encrypted `num_block` blocks unsigned integer
|
||||
/// taken uniformly in its full range using the given seed.
|
||||
/// The encryted value is oblivious to the server.
|
||||
/// The encrypted value is oblivious to the server.
|
||||
/// It can be useful to make server random generation deterministic.
|
||||
///
|
||||
/// ```rust
|
||||
@@ -78,7 +78,7 @@ impl ServerKey {
|
||||
|
||||
/// Generates an encrypted `num_block` blocks unsigned integer
|
||||
/// taken uniformly in `[0, 2^random_bits_count[` using the given seed.
|
||||
/// The encryted value is oblivious to the server.
|
||||
/// The encrypted value is oblivious to the server.
|
||||
/// It can be useful to make server random generation deterministic.
|
||||
///
|
||||
/// ```rust
|
||||
@@ -159,7 +159,7 @@ impl ServerKey {
|
||||
impl ServerKey {
|
||||
/// Generates an encrypted `num_block` blocks signed integer
|
||||
/// taken uniformly in its full range using the given seed.
|
||||
/// The encryted value is oblivious to the server.
|
||||
/// The encrypted value is oblivious to the server.
|
||||
/// It can be useful to make server random generation deterministic.
|
||||
///
|
||||
/// ```rust
|
||||
@@ -206,7 +206,7 @@ impl ServerKey {
|
||||
|
||||
/// Generates an encrypted `num_block` blocks signed integer
|
||||
/// taken uniformly in `[0, 2^random_bits_count[` using the given seed.
|
||||
/// The encryted value is oblivious to the server.
|
||||
/// The encrypted value is oblivious to the server.
|
||||
/// It can be useful to make server random generation deterministic.
|
||||
///
|
||||
/// ```rust
|
||||
|
||||
@@ -108,7 +108,7 @@ pub trait AtomicPattern {
|
||||
/// `full_bits_count` is the size of the lwe message, ie the shortint message + carry + padding
|
||||
/// bit.
|
||||
/// The output in in the form 0000rrr000noise (random_bits_count=3, full_bits_count=7)
|
||||
/// The encryted value is oblivious to the server
|
||||
/// The encrypted value is oblivious to the server
|
||||
fn generate_oblivious_pseudo_random(
|
||||
&self,
|
||||
seed: Seed,
|
||||
|
||||
@@ -178,7 +178,7 @@ pub(crate) fn raw_seeded_msed_to_lwe<Scalar: UnsignedInteger + CastFrom<usize>>(
|
||||
/// `full_bits_count` is the size of the lwe message, ie the shortint message + carry + padding
|
||||
/// bit.
|
||||
/// The output in in the form 0000rrr000noise (rbc=3, fbc=7)
|
||||
/// The encryted value is oblivious to the server.
|
||||
/// The encrypted value is oblivious to the server.
|
||||
///
|
||||
/// It is the reponsiblity of the calling AP to transform this into a shortint ciphertext. The
|
||||
/// returned LWE is in the post PBS state, so a Keyswitch might be needed if the order is PBS-KS.
|
||||
@@ -261,7 +261,7 @@ where
|
||||
impl<AP: AtomicPattern> GenericServerKey<AP> {
|
||||
/// Uniformly generates a random encrypted value in `[0, 2^random_bits_count[`
|
||||
/// `2^random_bits_count` must be smaller than the message modulus
|
||||
/// The encryted value is oblivious to the server
|
||||
/// The encrypted value is oblivious to the server
|
||||
pub fn generate_oblivious_pseudo_random(
|
||||
&self,
|
||||
seed: Seed,
|
||||
@@ -281,7 +281,7 @@ impl<AP: AtomicPattern> GenericServerKey<AP> {
|
||||
}
|
||||
|
||||
/// Uniformly generates a random value in `[0, 2^random_bits_count[`
|
||||
/// The encryted value is oblivious to the server
|
||||
/// The encrypted value is oblivious to the server
|
||||
pub(crate) fn generate_oblivious_pseudo_random_message_and_carry(
|
||||
&self,
|
||||
seed: Seed,
|
||||
|
||||
@@ -107,7 +107,7 @@ pub struct MessageModulus(pub u64);
|
||||
|
||||
impl MessageModulus {
|
||||
pub fn corresponding_max_degree(&self) -> MaxDegree {
|
||||
MaxDegree::new(self.0 - 1)
|
||||
MaxDegree::new(self.0.saturating_sub(1))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user