Compare commits
1 Commits
ns/chore/u
...
ts/bench/m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47e75759c9 |
10
.github/workflows/gpu_core_h100_tests.yml
vendored
@@ -23,7 +23,7 @@ on:
|
||||
# Allows you to run this workflow manually from the Actions tab as an alternative.
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [ labeled, opened, synchronize ]
|
||||
types: [ labeled ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -38,7 +38,6 @@ jobs:
|
||||
pull-requests: read # Needed to check for file change
|
||||
outputs:
|
||||
gpu_test: ${{ env.IS_PULL_REQUEST == 'false' || steps.changed-files.outputs.gpu_any_changed }}
|
||||
core_crypto_changed: ${{ steps.changed-files.outputs.core_crypto_any_changed }}
|
||||
steps:
|
||||
- name: Checkout tfhe-rs
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
@@ -63,16 +62,15 @@ jobs:
|
||||
- tfhe/src/integer/server_key/radix_parallel/tests_cases_unsigned.rs
|
||||
- tfhe/src/shortint/parameters/**
|
||||
- tfhe/src/c_api/**
|
||||
- 'tfhe/docs/**/**.md'
|
||||
- '.github/workflows/gpu_core_h100_tests.yml'
|
||||
core_crypto:
|
||||
- tfhe/src/core_crypto/gpu/**
|
||||
|
||||
setup-instance:
|
||||
name: gpu_core_h100_tests/setup-instance
|
||||
needs: should-run
|
||||
if: github.event_name != 'pull_request' ||
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true') ||
|
||||
(github.event.action != 'labeled' && needs.should-run.outputs.core_crypto_changed == 'true')
|
||||
(github.event.action != 'labeled' && needs.should-run.outputs.gpu_test == 'true') ||
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true')
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
runner-name: ${{ steps.start-remote-instance.outputs.label || steps.start-github-instance.outputs.runner_group }}
|
||||
|
||||
9
.github/workflows/gpu_hlapi_h100_tests.yml
vendored
@@ -23,7 +23,7 @@ on:
|
||||
# Allows you to run this workflow manually from the Actions tab as an alternative.
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [ labeled, opened, synchronize ]
|
||||
types: [ labeled ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -38,7 +38,6 @@ jobs:
|
||||
pull-requests: read # Needed to check for file change
|
||||
outputs:
|
||||
gpu_test: ${{ env.IS_PULL_REQUEST == 'false' || steps.changed-files.outputs.gpu_any_changed }}
|
||||
core_crypto_changed: ${{ steps.changed-files.outputs.core_crypto_any_changed }}
|
||||
steps:
|
||||
- name: Checkout tfhe-rs
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
@@ -66,15 +65,13 @@ jobs:
|
||||
- tfhe/src/c_api/**
|
||||
- 'tfhe/docs/**/**.md'
|
||||
- '.github/workflows/gpu_hlapi_h100_tests.yml'
|
||||
core_crypto:
|
||||
- tfhe/src/core_crypto/gpu/**
|
||||
|
||||
setup-instance:
|
||||
name: gpu_hlapi_h100_tests/setup-instance
|
||||
needs: should-run
|
||||
if: github.event_name != 'pull_request' ||
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true') ||
|
||||
(github.event.action != 'labeled' && needs.should-run.outputs.core_crypto_changed == 'true')
|
||||
(github.event.action != 'labeled' && needs.should-run.outputs.gpu_test == 'true') ||
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true')
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
runner-name: ${{ steps.start-remote-instance.outputs.label || steps.start-github-instance.outputs.runner_group }}
|
||||
|
||||
39
.github/workflows/gpu_integer_long_run_tests.yml
vendored
@@ -17,8 +17,8 @@ on:
|
||||
# Allows you to run this workflow manually from the Actions tab as an alternative.
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Weekly tests will be triggered every Monday at 8p.m.
|
||||
- cron: "0 20 * * 1"
|
||||
# Nightly tests will be triggered each evening 8p.m.
|
||||
- cron: "0 20 * * *"
|
||||
pull_request:
|
||||
|
||||
|
||||
@@ -28,41 +28,10 @@ permissions:
|
||||
# zizmor: ignore[concurrency-limits] concurrency is managed after instance setup to ensure safe provisioning
|
||||
|
||||
jobs:
|
||||
should-run:
|
||||
name: gpu_integer_long_run_tests/should-run
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: read # Needed to check for file change
|
||||
outputs:
|
||||
is_needed_in_gpu_ci: ${{ env.IS_PR == 'false' || steps.changed-files.outputs.gpu_any_changed }}
|
||||
steps:
|
||||
- name: Checkout tfhe-rs
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: 'false'
|
||||
token: ${{ env.CHECKOUT_TOKEN }}
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
- tfhe/Cargo.toml
|
||||
- tfhe/build.rs
|
||||
- backends/tfhe-cuda-backend/**
|
||||
- tfhe/src/core_crypto/gpu/**
|
||||
- tfhe/src/integer/gpu/**
|
||||
- tfhe/src/shortint/parameters/**
|
||||
- '.github/workflows/gpu_integer_long_run_tests.yml'
|
||||
|
||||
setup-instance:
|
||||
name: gpu_integer_long_run_tests/setup-instance
|
||||
needs: [should-run]
|
||||
if: github.event_name == 'workflow_dispatch' ||
|
||||
(github.event_name == 'schedule' && github.repository == 'zama-ai/tfhe-rs') ||
|
||||
needs.should-run.outputs.is_needed_in_gpu_ci == 'true'
|
||||
if: github.event_name != 'schedule' ||
|
||||
(github.event_name == 'schedule' && github.repository == 'zama-ai/tfhe-rs')
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
runner-name: ${{ steps.start-instance.outputs.label }}
|
||||
|
||||
8
.github/workflows/gpu_pcc.yml
vendored
@@ -131,10 +131,6 @@ jobs:
|
||||
env:
|
||||
GCC_VERSION: ${{ matrix.gcc }}
|
||||
|
||||
- name: Run semgrep and lint checks on CUDA code
|
||||
run: |
|
||||
make semgrep_and_lint_gpu_code
|
||||
|
||||
- name: Run fmt checks
|
||||
run: |
|
||||
make check_fmt_gpu
|
||||
@@ -143,6 +139,10 @@ jobs:
|
||||
run: |
|
||||
make pcc_gpu
|
||||
|
||||
- name: Run semgrep and lint checks on CUDA code
|
||||
run: |
|
||||
make semgrep_and_lint_gpu_code
|
||||
|
||||
- name: Run semver checks on tfhe-cuda-backend
|
||||
run: |
|
||||
make semver_check_cuda_backend
|
||||
|
||||
@@ -63,6 +63,7 @@ jobs:
|
||||
- tfhe/src/shortint/parameters/**
|
||||
- tfhe/src/high_level_api/**
|
||||
- tfhe/src/c_api/**
|
||||
- 'tfhe/docs/**/**.md'
|
||||
- '.github/workflows/gpu_signed_integer_classic_tests.yml'
|
||||
- scripts/integer-tests.sh
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ on:
|
||||
# Allows you to run this workflow manually from the Actions tab as an alternative.
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [ labeled, opened, synchronize ]
|
||||
types: [ labeled ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -38,7 +38,6 @@ jobs:
|
||||
pull-requests: read # Needed to check for file change
|
||||
outputs:
|
||||
gpu_test: ${{ env.IS_PULL_REQUEST == 'false' || steps.changed-files.outputs.gpu_any_changed }}
|
||||
core_crypto_changed: ${{ steps.changed-files.outputs.core_crypto_any_changed }}
|
||||
steps:
|
||||
- name: Checkout tfhe-rs
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
@@ -64,17 +63,16 @@ jobs:
|
||||
- tfhe/src/shortint/parameters/**
|
||||
- tfhe/src/high_level_api/**
|
||||
- tfhe/src/c_api/**
|
||||
- 'tfhe/docs/**/**.md'
|
||||
- '.github/workflows/gpu_signed_integer_h100_tests.yml'
|
||||
- scripts/integer-tests.sh
|
||||
core_crypto:
|
||||
- tfhe/src/core_crypto/gpu/**
|
||||
|
||||
setup-instance:
|
||||
name: gpu_signed_integer_h100_tests/setup-instance
|
||||
needs: should-run
|
||||
if: github.event_name != 'pull_request' ||
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true') ||
|
||||
(github.event.action != 'labeled' && needs.should-run.outputs.core_crypto_changed == 'true')
|
||||
(github.event.action != 'labeled' && needs.should-run.outputs.gpu_test == 'true') ||
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true')
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
runner-name: ${{ steps.start-remote-instance.outputs.label || steps.start-github-instance.outputs.runner_group }}
|
||||
|
||||
@@ -64,6 +64,7 @@ jobs:
|
||||
- tfhe/src/shortint/parameters/**
|
||||
- tfhe/src/high_level_api/**
|
||||
- tfhe/src/c_api/**
|
||||
- 'tfhe/docs/**/**.md'
|
||||
- '.github/workflows/gpu_signed_integer_tests.yml'
|
||||
- scripts/integer-tests.sh
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ jobs:
|
||||
- tfhe/src/shortint/parameters/**
|
||||
- tfhe/src/high_level_api/**
|
||||
- tfhe/src/c_api/**
|
||||
- 'tfhe/docs/**/**.md'
|
||||
- '.github/workflows/gpu_unsigned_integer_classic_tests.yml'
|
||||
- scripts/integer-tests.sh
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ on:
|
||||
# Allows you to run this workflow manually from the Actions tab as an alternative.
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [ labeled, opened, synchronize ]
|
||||
types: [ labeled ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -38,7 +38,6 @@ jobs:
|
||||
pull-requests: read # Needed to check for file change
|
||||
outputs:
|
||||
gpu_test: ${{ env.IS_PULL_REQUEST == 'false' || steps.changed-files.outputs.gpu_any_changed }}
|
||||
core_crypto_changed: ${{ steps.changed-files.outputs.core_crypto_any_changed }}
|
||||
steps:
|
||||
- name: Checkout tfhe-rs
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
@@ -64,17 +63,16 @@ jobs:
|
||||
- tfhe/src/shortint/parameters/**
|
||||
- tfhe/src/high_level_api/**
|
||||
- tfhe/src/c_api/**
|
||||
- 'tfhe/docs/**/**.md'
|
||||
- '.github/workflows/gpu_unsigned_integer_h100_tests.yml'
|
||||
- scripts/integer-tests.sh
|
||||
core_crypto:
|
||||
- tfhe/src/core_crypto/gpu/**
|
||||
|
||||
setup-instance:
|
||||
name: gpu_unsigned_integer_h100_tests/setup-instance
|
||||
needs: should-run
|
||||
if: github.event_name == 'workflow_dispatch' ||
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true') ||
|
||||
(github.event.action != 'labeled' && needs.should-run.outputs.core_crypto_changed == 'true')
|
||||
(github.event.action != 'labeled' && needs.should-run.outputs.gpu_test == 'true') ||
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true')
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
runner-name: ${{ steps.start-remote-instance.outputs.label || steps.start-github-instance.outputs.runner_group }}
|
||||
|
||||
@@ -64,6 +64,7 @@ jobs:
|
||||
- tfhe/src/shortint/parameters/**
|
||||
- tfhe/src/high_level_api/**
|
||||
- tfhe/src/c_api/**
|
||||
- 'tfhe/docs/**/**.md'
|
||||
- '.github/workflows/gpu_unsigned_integer_tests.yml'
|
||||
- scripts/integer-tests.sh
|
||||
|
||||
|
||||
3
.github/workflows/gpu_zk_tests.yml
vendored
@@ -55,9 +55,12 @@ jobs:
|
||||
- tfhe/build.rs
|
||||
- backends/tfhe-cuda-backend/**
|
||||
- backends/zk-cuda-backend/**
|
||||
- tfhe/src/core_crypto/gpu/**
|
||||
- tfhe/src/integer/gpu/**
|
||||
- tfhe/src/shortint/parameters/**
|
||||
- tfhe/src/zk/**
|
||||
- tfhe-zk-pok/**
|
||||
- 'tfhe/docs/**/**.md'
|
||||
- '.github/workflows/gpu_zk_tests.yml'
|
||||
- ci/slab.toml
|
||||
|
||||
|
||||
14
Makefile
@@ -312,7 +312,7 @@ semgrep_and_lint_gpu_code: semgrep_lint_setup_venv
|
||||
find "$(TFHECUDA_SRC)" -name '*.h' -o -name '*.cuh' -o -name '*.cu' \
|
||||
| grep -v '/cmake-build-debug/' \
|
||||
| grep -v '/build/' \
|
||||
| xargs venv/bin/semgrep --error --config "$(TFHECUDA_SRC)/.semgrep/release-ordering.yaml" --scan-unknown-extensions
|
||||
| xargs venv/bin/semgrep --config "$(TFHECUDA_SRC)/.semgrep/release-ordering.yaml" --scan-unknown-extensions
|
||||
venv/bin/python3 "scripts/check_scratch_cleanup.py"
|
||||
|
||||
.PHONY: semver_check_cuda_backend # Run semver checks on tfhe-cuda-backend
|
||||
@@ -587,17 +587,6 @@ clippy_backward_compat_data: install_rs_check_toolchain # the toolchain is selec
|
||||
echo "Cannot run clippy for backward compat crate on non x86 platform for now."; \
|
||||
fi
|
||||
|
||||
.PHONY: check_backward_compat_locks_did_not_change # Check backward compat Cargo.lock files are up to date
|
||||
check_backward_compat_locks_did_not_change: install_rs_check_toolchain
|
||||
@for crate in `ls -1 $(BACKWARD_COMPAT_DATA_DIR)/crates/ | grep generate_`; do \
|
||||
echo "checking Cargo.lock for $$crate"; \
|
||||
cargo "$(CARGO_RS_CHECK_TOOLCHAIN)" -Z unstable-options \
|
||||
-C $(BACKWARD_COMPAT_DATA_DIR)/crates/$$crate metadata --locked --format-version 1 > /dev/null || \
|
||||
( echo "Cargo.lock for $$crate is out of date. Update it with:" && \
|
||||
echo " cd $(BACKWARD_COMPAT_DATA_DIR)/crates/$$crate && cargo metadata --format-version 1 > /dev/null" && \
|
||||
echo "then commit the updated Cargo.lock." && exit 1 ); \
|
||||
done
|
||||
|
||||
.PHONY: clippy_test_vectors # Run clippy lints on the test vectors app
|
||||
clippy_test_vectors: install_rs_check_toolchain
|
||||
cd apps/test-vectors; RUSTFLAGS="$(RUSTFLAGS)" cargo "$(CARGO_RS_CHECK_TOOLCHAIN)" clippy --all-targets \
|
||||
@@ -2276,7 +2265,6 @@ pcc_batch_5:
|
||||
$(call run_recipe_with_details,clippy_tfhe_lints)
|
||||
$(call run_recipe_with_details,check_compile_tests)
|
||||
$(call run_recipe_with_details,clippy_backward_compat_data)
|
||||
$(call run_recipe_with_details,check_backward_compat_locks_did_not_change)
|
||||
|
||||
.PHONY: pcc_batch_6 # duration: 6'32''
|
||||
pcc_batch_6:
|
||||
|
||||
@@ -390,7 +390,7 @@ __host__ void vectorized_sbox_n_bytes(CudaStreams streams,
|
||||
XOR(&wires_a[6], &wires_a[15], &input_bits[7]);
|
||||
XOR(&wires_a[10], &wires_a[15], &wires_b[0]);
|
||||
XOR(&wires_a[11], &wires_a[20], &wires_a[9]);
|
||||
FLUSH(&wires_a[6], &wires_a[10], &wires_a[11]);
|
||||
FLUSH(&wires_a[6], &wires_a[10]);
|
||||
XOR(&wires_a[7], &input_bits[7], &wires_a[11]);
|
||||
FLUSH(&wires_a[7]);
|
||||
XOR(&wires_a[17], &wires_a[10], &wires_a[11]);
|
||||
@@ -426,7 +426,7 @@ __host__ void vectorized_sbox_n_bytes(CudaStreams streams,
|
||||
XOR(&wires_b[22], &wires_b[18], &wires_a[19]);
|
||||
XOR(&wires_b[23], &wires_b[19], &wires_a[21]);
|
||||
XOR(&wires_b[24], &wires_b[20], &wires_a[18]);
|
||||
FLUSH(&wires_b[21], &wires_b[22], &wires_b[23], &wires_b[24]);
|
||||
FLUSH(&wires_b[21], &wires_b[23], &wires_b[24]);
|
||||
XOR(&wires_b[25], &wires_b[21], &wires_b[22]);
|
||||
FLUSH(&wires_b[25]);
|
||||
|
||||
@@ -468,7 +468,7 @@ __host__ void vectorized_sbox_n_bytes(CudaStreams streams,
|
||||
|
||||
XOR(&wires_b[37], &wires_b[36], &wires_b[34]);
|
||||
XOR(&wires_b[38], &wires_b[27], &wires_b[36]);
|
||||
FLUSH(&wires_b[38], &wires_b[37]);
|
||||
FLUSH(&wires_b[38]);
|
||||
XOR(&wires_b[44], &wires_b[33], &wires_b[37]);
|
||||
|
||||
CudaRadixCiphertextFFI *and_outs_6[] = {&wires_b[39]};
|
||||
@@ -479,7 +479,7 @@ __host__ void vectorized_sbox_n_bytes(CudaStreams streams,
|
||||
XOR(&wires_b[40], &wires_b[25], &wires_b[39]);
|
||||
XOR(&wires_b[41], &wires_b[40], &wires_b[37]);
|
||||
XOR(&wires_b[43], &wires_b[29], &wires_b[40]);
|
||||
FLUSH(&wires_b[41], &wires_b[40], &wires_b[43], &wires_b[44]);
|
||||
FLUSH(&wires_b[41]);
|
||||
XOR(&wires_b[45], &wires_b[42], &wires_b[41]);
|
||||
FLUSH(&wires_b[45]);
|
||||
|
||||
@@ -514,7 +514,6 @@ __host__ void vectorized_sbox_n_bytes(CudaStreams streams,
|
||||
XOR(&wires_b[57], &wires_b[50], &wires_b[53]);
|
||||
XOR(&wires_b[58], &wires_c[4], &wires_b[46]);
|
||||
XOR(&wires_b[59], &wires_c[3], &wires_b[54]);
|
||||
FLUSH(&wires_b[57], &wires_b[58]);
|
||||
XOR(&wires_b[60], &wires_b[46], &wires_b[57]);
|
||||
XOR(&wires_b[61], &wires_c[14], &wires_b[57]);
|
||||
XOR(&wires_b[62], &wires_b[52], &wires_b[58]);
|
||||
@@ -590,7 +589,6 @@ __host__ void vectorized_sbox_n_bytes(CudaStreams streams,
|
||||
#undef FLUSH
|
||||
#undef AND
|
||||
#undef ADD_ONE_FLUSH
|
||||
#undef ADD_ONE
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -489,7 +489,7 @@ template <typename Torus>
|
||||
__host__ void host_modulus_switch_multi_bit(
|
||||
cudaStream_t stream, uint32_t gpu_index, Torus *array_out, Torus *array_in,
|
||||
int size, uint32_t log_modulus, uint32_t degree, uint32_t grouping_factor) {
|
||||
check_cuda_error(cudaSetDevice(gpu_index));
|
||||
cudaSetDevice(gpu_index);
|
||||
int multibit_size = size / grouping_factor;
|
||||
int num_threads = 0, num_blocks = 0;
|
||||
getNumBlocksAndThreads(multibit_size, 1024, num_blocks, num_threads);
|
||||
|
||||
@@ -308,7 +308,6 @@ void cleanup_cuda_multi_bit_programmable_bootstrap_noise_tests_128(
|
||||
void *stream, uint32_t gpu_index, int8_t **pbs_buffer) {
|
||||
cleanup_cuda_multi_bit_programmable_bootstrap_128(stream, gpu_index,
|
||||
pbs_buffer);
|
||||
cuda_synchronize_stream(static_cast<cudaStream_t>(stream), gpu_index);
|
||||
}
|
||||
|
||||
// Noise tests variant of the 128-bit multi-bit PBS, restricted to
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tfhe-hpu-backend"
|
||||
version = "0.5.0"
|
||||
version = "0.4.0"
|
||||
edition = "2021"
|
||||
license = "BSD-3-Clause-Clear"
|
||||
description = "HPU implementation on FPGA of TFHE-rs primitives."
|
||||
@@ -36,7 +36,7 @@ thiserror = "1.0.61"
|
||||
bytemuck = { workspace = true }
|
||||
anyhow = "1.0.82"
|
||||
lazy_static = "1.4.0"
|
||||
rand = "0.10.1"
|
||||
rand = "0.8.5"
|
||||
regex = "1.10.4"
|
||||
bitflags = { version = "2.5.0", features = ["serde"] }
|
||||
itertools = "0.11.0"
|
||||
|
||||
@@ -24,7 +24,7 @@ use mem_alloc::{MemAlloc, MemChunk};
|
||||
|
||||
mod qdma;
|
||||
use qdma::QdmaDriver;
|
||||
use rand::RngExt;
|
||||
use rand::Rng;
|
||||
|
||||
const DMA_XFER_ALIGN: usize = 4096_usize;
|
||||
|
||||
@@ -148,8 +148,8 @@ impl HpuHw {
|
||||
tracing::debug!("Load stage1 through JTAG");
|
||||
let pdi_stg1_tmp = format!(
|
||||
"hpu_stg1_{}.pdi",
|
||||
rand::rng()
|
||||
.sample_iter(rand::distr::Alphanumeric)
|
||||
rand::thread_rng()
|
||||
.sample_iter(rand::distributions::Alphanumeric)
|
||||
.take(5)
|
||||
.map(char::from)
|
||||
.collect::<String>()
|
||||
|
||||
@@ -16,14 +16,19 @@ tfhe = { path = "../../tfhe", features = ["hpu", "hpu-debug"] }
|
||||
|
||||
ipc-channel = "0.18.3"
|
||||
|
||||
strum = { version = "0.26.2", features = ["derive"] }
|
||||
strum_macros = "0.26.2"
|
||||
bytemuck = { workspace = true }
|
||||
|
||||
clap = { version = "4.4.4", features = ["derive"] }
|
||||
clap-num = "*"
|
||||
anyhow = "1.0.82"
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "json"] }
|
||||
serde_json = "1.0"
|
||||
rand = "0.8.5"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
bitflags = "2.6.0"
|
||||
|
||||
[[bin]]
|
||||
name = "hpu_mockup"
|
||||
|
||||
@@ -36,12 +36,12 @@ pub fn bench_fhe_type_op<FheType, Op>(
|
||||
let inputs = op.setup_inputs(client_key, &mut rng);
|
||||
|
||||
let bench_type = get_bench_type();
|
||||
let benchmark_spec = BenchmarkSpec::new_hlapi(
|
||||
let benchmark_spec = BenchmarkSpec::new_hlapi_ops(
|
||||
hlapi_op,
|
||||
¶m_name,
|
||||
&operand_type,
|
||||
Some(type_name),
|
||||
bench_type,
|
||||
*bench_type,
|
||||
bench_backend_from_cfg(),
|
||||
);
|
||||
let bench_id = benchmark_spec.to_string();
|
||||
|
||||
@@ -5,12 +5,12 @@ use benchmark::params_aliases::{
|
||||
BENCH_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
BENCH_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
};
|
||||
use benchmark::utilities::{bench_backend_from_cfg, write_to_json, OperatorType};
|
||||
#[cfg(feature = "gpu")]
|
||||
use benchmark::utilities::{configure_gpu, get_param_type, ParamType};
|
||||
use benchmark::utilities::{write_to_json_unchecked, OperatorType};
|
||||
use benchmark_spec::{get_bench_type, BenchmarkType};
|
||||
use criterion::measurement::WallTime;
|
||||
use criterion::{BenchmarkGroup, Criterion, Throughput};
|
||||
use benchmark_spec::tfhe::hlapi::dex::{Dex, DexFlavor};
|
||||
use benchmark_spec::{get_bench_type, BenchmarkMetric, BenchmarkSpec, BenchmarkType, OperandType};
|
||||
use criterion::{Criterion, Throughput};
|
||||
use rand::prelude::*;
|
||||
use rand::thread_rng;
|
||||
use rayon::prelude::*;
|
||||
@@ -220,21 +220,15 @@ where
|
||||
|
||||
#[cfg(feature = "pbs-stats")]
|
||||
mod pbs_stats {
|
||||
use super::*;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
fn write_result(file: &mut File, name: &str, value: usize) {
|
||||
let line = format!("{name},{value}\n");
|
||||
let error_message = format!("cannot write {name} result into file");
|
||||
file.write_all(line.as_bytes()).expect(&error_message);
|
||||
}
|
||||
use benchmark_spec::TestResult;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub fn print_swap_request_update_dex_balance_pbs_counts<FheType, F>(
|
||||
client_key: &ClientKey,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Dex,
|
||||
swap_request_update_dex_balance_func: F,
|
||||
) where
|
||||
FheType: FheEncrypt<u64, ClientKey>,
|
||||
@@ -258,29 +252,24 @@ mod pbs_stats {
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let test_name = if cfg!(feature = "gpu") {
|
||||
format!("hlapi::cuda::dex::pbs_count::swap_request_update_dex_balance::{fn_name}::{params_name}::{type_name}")
|
||||
} else {
|
||||
format!(
|
||||
"hlapi::dex::pbs_count::swap_request_update_dex_balance::{fn_name}::{params_name}::{type_name}"
|
||||
)
|
||||
};
|
||||
let test_name = BenchmarkSpec::new_hlapi_dex(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::PbsCount,
|
||||
bench_backend_from_cfg(),
|
||||
None,
|
||||
);
|
||||
|
||||
let results_file = Path::new("dex_swap_request_update_dex_balance_pbs_count.csv");
|
||||
if !results_file.exists() {
|
||||
File::create(results_file).expect("create results file failed");
|
||||
}
|
||||
let mut file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open results file");
|
||||
let mut benchmark_test_result =
|
||||
TestResult::new("dex_swap_request_update_dex_balance_pbs_count.csv");
|
||||
|
||||
write_result(&mut file, &test_name, count as usize);
|
||||
benchmark_test_result.write_result(&test_name.to_string(), count as usize);
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
write_to_json::<u64, _>(
|
||||
&test_name,
|
||||
params,
|
||||
params_name,
|
||||
"pbs-count",
|
||||
&OperatorType::Atomic,
|
||||
0,
|
||||
@@ -290,6 +279,7 @@ mod pbs_stats {
|
||||
pub fn print_swap_request_finalize_pbs_counts<FheType, F>(
|
||||
client_key: &ClientKey,
|
||||
type_name: &str,
|
||||
fn_name: Dex,
|
||||
swap_request_finalize_func: F,
|
||||
) where
|
||||
FheType: FheEncrypt<u64, ClientKey>,
|
||||
@@ -313,29 +303,23 @@ mod pbs_stats {
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let test_name = if cfg!(feature = "gpu") {
|
||||
format!(
|
||||
"hlapi::cuda::dex::pbs_count::swap_request_finalize::{params_name}::{type_name}"
|
||||
)
|
||||
} else {
|
||||
format!("hlapi::dex::pbs_count::swap_request_finalize::{params_name}::{type_name}")
|
||||
};
|
||||
let test_name = BenchmarkSpec::new_hlapi_dex(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::PbsCount,
|
||||
bench_backend_from_cfg(),
|
||||
None,
|
||||
);
|
||||
|
||||
let results_file = Path::new("dex_swap_request_finalize_pbs_count.csv");
|
||||
if !results_file.exists() {
|
||||
File::create(results_file).expect("create results file failed");
|
||||
}
|
||||
let mut file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open results file");
|
||||
let mut benchmark_test_result = TestResult::new("dex_swap_request_finalize_pbs_count.csv");
|
||||
|
||||
write_result(&mut file, &test_name, count as usize);
|
||||
benchmark_test_result.write_result(&test_name.to_string(), count as usize);
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
write_to_json::<u64, _>(
|
||||
&test_name,
|
||||
params,
|
||||
params_name,
|
||||
"pbs-count",
|
||||
&OperatorType::Atomic,
|
||||
0,
|
||||
@@ -345,6 +329,7 @@ mod pbs_stats {
|
||||
pub fn print_swap_claim_prepare_pbs_counts<FheType, F>(
|
||||
client_key: &ClientKey,
|
||||
type_name: &str,
|
||||
fn_name: Dex,
|
||||
swap_claim_prepare_func: F,
|
||||
) where
|
||||
FheType: FheEncrypt<u64, ClientKey>,
|
||||
@@ -378,27 +363,23 @@ mod pbs_stats {
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let test_name = if cfg!(feature = "gpu") {
|
||||
format!("hlapi::cuda::pbs_count::dex::swap_claim_prepare::{params_name}::{type_name}")
|
||||
} else {
|
||||
format!("hlapi::dex::pbs_count::swap_claim_prepare::{params_name}::{type_name}")
|
||||
};
|
||||
let test_name = BenchmarkSpec::new_hlapi_dex(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::PbsCount,
|
||||
bench_backend_from_cfg(),
|
||||
None,
|
||||
);
|
||||
|
||||
let results_file = Path::new("dex_swap_claim_prepare_pbs_count.csv");
|
||||
if !results_file.exists() {
|
||||
File::create(results_file).expect("create results file failed");
|
||||
}
|
||||
let mut file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open results file");
|
||||
let mut benchmark_test_result = TestResult::new("dex_swap_claim_prepare_pbs_count.csv");
|
||||
|
||||
write_result(&mut file, &test_name, count as usize);
|
||||
benchmark_test_result.write_result(&test_name.to_string(), count as usize);
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
write_to_json::<u64, _>(
|
||||
&test_name,
|
||||
params,
|
||||
params_name,
|
||||
"pbs-count",
|
||||
&OperatorType::Atomic,
|
||||
0,
|
||||
@@ -408,7 +389,7 @@ mod pbs_stats {
|
||||
pub fn print_swap_claim_update_dex_balance_pbs_counts<FheType, F>(
|
||||
client_key: &ClientKey,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Dex,
|
||||
swap_claim_update_dex_balance_func: F,
|
||||
) where
|
||||
FheType: FheEncrypt<u64, ClientKey>,
|
||||
@@ -438,27 +419,24 @@ mod pbs_stats {
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let test_name = if cfg!(feature = "gpu") {
|
||||
format!("hlapi::cuda::pbs_count::dex::swap_claim_update_dex_balance::{fn_name}::{params_name}::{type_name}")
|
||||
} else {
|
||||
format!("hlapi::dex::pbs_count::swap_claim_update_dex_balance::{fn_name}::{params_name}::{type_name}")
|
||||
};
|
||||
let test_name = BenchmarkSpec::new_hlapi_dex(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::PbsCount,
|
||||
bench_backend_from_cfg(),
|
||||
None,
|
||||
);
|
||||
|
||||
let results_file = Path::new("dex_swap_claim_update_dex_balance_pbs_count.csv");
|
||||
if !results_file.exists() {
|
||||
File::create(results_file).expect("create results file failed");
|
||||
}
|
||||
let mut file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open results file");
|
||||
let mut benchmark_test_result =
|
||||
TestResult::new("dex_swap_claim_update_dex_balance_pbs_count.csv");
|
||||
|
||||
write_result(&mut file, &test_name, count as usize);
|
||||
benchmark_test_result.write_result(&test_name.to_string(), count as usize);
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
write_to_json::<u64, _>(
|
||||
&test_name,
|
||||
params,
|
||||
params_name,
|
||||
"pbs-count",
|
||||
&OperatorType::Atomic,
|
||||
0,
|
||||
@@ -468,11 +446,10 @@ mod pbs_stats {
|
||||
}
|
||||
|
||||
fn bench_swap_request_latency<FheType, F1, F2>(
|
||||
c: &mut BenchmarkGroup<'_, WallTime>,
|
||||
c: &mut Criterion,
|
||||
client_key: &ClientKey,
|
||||
bench_name: &str,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Dex,
|
||||
swap_request_update_dex_balance_func: F1,
|
||||
swap_request_finalize_func: F2,
|
||||
) where
|
||||
@@ -486,8 +463,19 @@ fn bench_swap_request_latency<FheType, F1, F2>(
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let bench_id = format!("{bench_name}::{fn_name}::{type_name}");
|
||||
c.bench_function(&bench_id, |b| {
|
||||
let mut c = c.benchmark_group(type_name);
|
||||
|
||||
let bench_spec = BenchmarkSpec::new_hlapi_dex(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::Latency,
|
||||
bench_backend_from_cfg(),
|
||||
None,
|
||||
);
|
||||
|
||||
c.bench_function(bench_spec.to_string(), |b| {
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let from_balance_0 = FheType::encrypt(rng.gen::<u64>(), client_key);
|
||||
@@ -525,10 +513,9 @@ fn bench_swap_request_latency<FheType, F1, F2>(
|
||||
})
|
||||
});
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&bench_id,
|
||||
write_to_json::<u64, _>(
|
||||
&bench_spec,
|
||||
params,
|
||||
params_name,
|
||||
"dex-swap-request",
|
||||
&OperatorType::Atomic,
|
||||
64,
|
||||
@@ -538,11 +525,10 @@ fn bench_swap_request_latency<FheType, F1, F2>(
|
||||
|
||||
#[cfg(not(feature = "gpu"))]
|
||||
fn bench_swap_request_throughput<FheType, F1, F2>(
|
||||
group: &mut BenchmarkGroup<'_, WallTime>,
|
||||
c: &mut Criterion,
|
||||
client_key: &ClientKey,
|
||||
bench_name: &str,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Dex,
|
||||
swap_request_update_dex_balance_func: F1,
|
||||
swap_request_finalize_func: F2,
|
||||
) where
|
||||
@@ -555,12 +541,22 @@ fn bench_swap_request_throughput<FheType, F1, F2>(
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let mut group = c.benchmark_group(type_name);
|
||||
|
||||
for num_elems in [10, 50, 100] {
|
||||
group.throughput(Throughput::Elements(num_elems));
|
||||
let bench_id = format!(
|
||||
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
|
||||
|
||||
let bench_spec = BenchmarkSpec::new_hlapi_dex(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::Throughput,
|
||||
bench_backend_from_cfg(),
|
||||
Some(num_elems.try_into().unwrap()),
|
||||
);
|
||||
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
|
||||
|
||||
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
|
||||
let from_balances_0 = (0..num_elems)
|
||||
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
|
||||
.collect::<Vec<_>>();
|
||||
@@ -641,10 +637,9 @@ fn bench_swap_request_throughput<FheType, F1, F2>(
|
||||
})
|
||||
});
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&bench_id,
|
||||
write_to_json::<u64, _>(
|
||||
&bench_spec,
|
||||
params,
|
||||
¶ms_name,
|
||||
"dex-swap-request",
|
||||
&OperatorType::Atomic,
|
||||
64,
|
||||
@@ -654,11 +649,10 @@ fn bench_swap_request_throughput<FheType, F1, F2>(
|
||||
}
|
||||
#[cfg(feature = "gpu")]
|
||||
fn cuda_bench_swap_request_throughput<FheType, F1, F2>(
|
||||
group: &mut BenchmarkGroup<'_, WallTime>,
|
||||
c: &mut Criterion,
|
||||
client_key: &ClientKey,
|
||||
bench_name: &str,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Dex,
|
||||
swap_request_update_dex_balance_func: F1,
|
||||
swap_request_finalize_func: F2,
|
||||
) where
|
||||
@@ -678,12 +672,20 @@ fn cuda_bench_swap_request_throughput<FheType, F1, F2>(
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let mut group = c.benchmark_group(type_name);
|
||||
|
||||
for num_elems in [5 * num_gpus, 10 * num_gpus, 20 * num_gpus] {
|
||||
group.throughput(Throughput::Elements(num_elems));
|
||||
let bench_id = format!(
|
||||
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
|
||||
let bench_spec = BenchmarkSpec::new_hlapi_dex(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::Throughput,
|
||||
bench_backend_from_cfg(),
|
||||
Some(num_elems.try_into().unwrap()),
|
||||
);
|
||||
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
|
||||
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
|
||||
let from_balances_0 = (0..num_elems)
|
||||
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
|
||||
.collect::<Vec<_>>();
|
||||
@@ -853,10 +855,9 @@ fn cuda_bench_swap_request_throughput<FheType, F1, F2>(
|
||||
})
|
||||
});
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&bench_id,
|
||||
write_to_json::<u64, _>(
|
||||
&bench_spec,
|
||||
params,
|
||||
¶ms_name,
|
||||
"dex-swap-request",
|
||||
&OperatorType::Atomic,
|
||||
64,
|
||||
@@ -866,11 +867,10 @@ fn cuda_bench_swap_request_throughput<FheType, F1, F2>(
|
||||
}
|
||||
|
||||
fn bench_swap_claim_latency<FheType, F1, F2>(
|
||||
c: &mut BenchmarkGroup<'_, WallTime>,
|
||||
c: &mut Criterion,
|
||||
client_key: &ClientKey,
|
||||
bench_name: &str,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Dex,
|
||||
swap_claim_prepare_func: F1,
|
||||
swap_claim_update_dex_balance_func: F2,
|
||||
) where
|
||||
@@ -884,8 +884,19 @@ fn bench_swap_claim_latency<FheType, F1, F2>(
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let bench_id = format!("{bench_name}::{fn_name}::{params_name}::{type_name}");
|
||||
c.bench_function(&bench_id, |b| {
|
||||
let mut c = c.benchmark_group(type_name);
|
||||
|
||||
let bench_spec = BenchmarkSpec::new_hlapi_dex(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::Latency,
|
||||
bench_backend_from_cfg(),
|
||||
None,
|
||||
);
|
||||
|
||||
c.bench_function(bench_spec.to_string(), |b| {
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let pending_0_in = FheType::encrypt(rng.gen::<u64>(), client_key);
|
||||
@@ -929,10 +940,9 @@ fn bench_swap_claim_latency<FheType, F1, F2>(
|
||||
});
|
||||
});
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&bench_id,
|
||||
write_to_json::<u64, _>(
|
||||
&bench_spec,
|
||||
params,
|
||||
¶ms_name,
|
||||
"dex-swap-claim",
|
||||
&OperatorType::Atomic,
|
||||
64,
|
||||
@@ -942,11 +952,10 @@ fn bench_swap_claim_latency<FheType, F1, F2>(
|
||||
|
||||
#[cfg(not(feature = "gpu"))]
|
||||
fn bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
group: &mut BenchmarkGroup<'_, WallTime>,
|
||||
c: &mut Criterion,
|
||||
client_key: &ClientKey,
|
||||
bench_name: &str,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Dex,
|
||||
swap_claim_prepare_func: F1,
|
||||
swap_claim_update_dex_balance_func: F2,
|
||||
) where
|
||||
@@ -959,12 +968,22 @@ fn bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let mut group = c.benchmark_group(type_name);
|
||||
|
||||
for num_elems in [2, 6, 10] {
|
||||
group.throughput(Throughput::Elements(num_elems));
|
||||
let bench_id = format!(
|
||||
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
|
||||
|
||||
let bench_spec = BenchmarkSpec::new_hlapi_dex(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::Throughput,
|
||||
bench_backend_from_cfg(),
|
||||
Some(num_elems.try_into().unwrap()),
|
||||
);
|
||||
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
|
||||
|
||||
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
|
||||
let pending_0_in = (0..num_elems)
|
||||
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
|
||||
.collect::<Vec<_>>();
|
||||
@@ -1063,10 +1082,9 @@ fn bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
});
|
||||
});
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&bench_id,
|
||||
write_to_json::<u64, _>(
|
||||
&bench_spec,
|
||||
params,
|
||||
¶ms_name,
|
||||
"dex-swap-claim",
|
||||
&OperatorType::Atomic,
|
||||
64,
|
||||
@@ -1076,11 +1094,10 @@ fn bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
}
|
||||
#[cfg(feature = "gpu")]
|
||||
fn cuda_bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
group: &mut BenchmarkGroup<'_, WallTime>,
|
||||
c: &mut Criterion,
|
||||
client_key: &ClientKey,
|
||||
bench_name: &str,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Dex,
|
||||
swap_claim_prepare_func: F1,
|
||||
swap_claim_update_dex_balance_func: F2,
|
||||
) where
|
||||
@@ -1100,12 +1117,20 @@ fn cuda_bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let mut group = c.benchmark_group(type_name);
|
||||
|
||||
for num_elems in [num_gpus, 2 * num_gpus] {
|
||||
group.throughput(Throughput::Elements(num_elems));
|
||||
let bench_id = format!(
|
||||
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
|
||||
let bench_spec = BenchmarkSpec::new_hlapi_dex(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::Throughput,
|
||||
bench_backend_from_cfg(),
|
||||
Some(num_elems.try_into().unwrap()),
|
||||
);
|
||||
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
|
||||
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
|
||||
let pending_0_in = (0..num_elems)
|
||||
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
|
||||
.collect::<Vec<_>>();
|
||||
@@ -1270,10 +1295,9 @@ fn cuda_bench_swap_claim_throughput<FheType, F1, F2>(
|
||||
});
|
||||
});
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&bench_id,
|
||||
write_to_json::<u64, _>(
|
||||
&bench_spec,
|
||||
params,
|
||||
¶ms_name,
|
||||
"dex-swap-claim",
|
||||
&OperatorType::Atomic,
|
||||
64,
|
||||
@@ -1306,8 +1330,6 @@ fn main() {
|
||||
|
||||
let mut c = Criterion::default().sample_size(10).configure_from_args();
|
||||
|
||||
let bench_name = "hlapi::dex";
|
||||
|
||||
// FheUint64 PBS counts
|
||||
// We don't run multiple times since every input is encrypted
|
||||
// PBS count is always the same
|
||||
@@ -1316,120 +1338,109 @@ fn main() {
|
||||
print_swap_request_update_dex_balance_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"whitepaper",
|
||||
Dex::SwapRequest(DexFlavor::Whitepaper),
|
||||
swap_request_update_dex_balance_whitepaper::<FheUint64>,
|
||||
);
|
||||
print_swap_request_update_dex_balance_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"no_cmux",
|
||||
Dex::SwapRequest(DexFlavor::NoCmux),
|
||||
swap_request_update_dex_balance_no_cmux::<FheUint64>,
|
||||
);
|
||||
print_swap_request_finalize_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
Dex::SwapRequest(DexFlavor::Finalize),
|
||||
swap_request_finalize::<FheUint64>,
|
||||
);
|
||||
print_swap_claim_prepare_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
Dex::SwapClaim(DexFlavor::Prepare),
|
||||
swap_claim_prepare::<FheUint64, FheUint128>,
|
||||
);
|
||||
print_swap_claim_update_dex_balance_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"whitepaper",
|
||||
Dex::SwapClaim(DexFlavor::Whitepaper),
|
||||
swap_claim_update_dex_balance_whitepaper::<FheUint64>,
|
||||
);
|
||||
print_swap_claim_update_dex_balance_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"no_cmux",
|
||||
Dex::SwapClaim(DexFlavor::NoCmux),
|
||||
swap_claim_update_dex_balance_no_cmux::<FheUint64>,
|
||||
);
|
||||
}
|
||||
|
||||
match get_bench_type() {
|
||||
BenchmarkType::Latency => {
|
||||
let mut group = c.benchmark_group(bench_name);
|
||||
bench_swap_request_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_request::whitepaper",
|
||||
Dex::SwapRequest(DexFlavor::Whitepaper),
|
||||
swap_request_update_dex_balance_whitepaper::<FheUint64>,
|
||||
swap_request_finalize::<FheUint64>,
|
||||
);
|
||||
bench_swap_request_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_request::no_cmux",
|
||||
Dex::SwapRequest(DexFlavor::NoCmux),
|
||||
swap_request_update_dex_balance_no_cmux::<FheUint64>,
|
||||
swap_request_finalize::<FheUint64>,
|
||||
);
|
||||
bench_swap_claim_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_claim::whitepaper",
|
||||
Dex::SwapClaim(DexFlavor::Whitepaper),
|
||||
swap_claim_prepare::<FheUint64, FheUint128>,
|
||||
swap_claim_update_dex_balance_whitepaper::<FheUint64>,
|
||||
);
|
||||
bench_swap_claim_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_claim::no_cmux",
|
||||
Dex::SwapClaim(DexFlavor::NoCmux),
|
||||
swap_claim_prepare::<FheUint64, FheUint128>,
|
||||
swap_claim_update_dex_balance_no_cmux::<FheUint64>,
|
||||
);
|
||||
|
||||
group.finish();
|
||||
}
|
||||
BenchmarkType::Throughput => {
|
||||
let mut group = c.benchmark_group(bench_name);
|
||||
bench_swap_request_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_request::whitepaper",
|
||||
Dex::SwapRequest(DexFlavor::Whitepaper),
|
||||
swap_request_update_dex_balance_whitepaper::<FheUint64>,
|
||||
swap_request_finalize::<FheUint64>,
|
||||
);
|
||||
bench_swap_request_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_request::no_cmux",
|
||||
Dex::SwapRequest(DexFlavor::NoCmux),
|
||||
swap_request_update_dex_balance_no_cmux::<FheUint64>,
|
||||
swap_request_finalize::<FheUint64>,
|
||||
);
|
||||
bench_swap_claim_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_claim::whitepaper",
|
||||
Dex::SwapClaim(DexFlavor::Whitepaper),
|
||||
swap_claim_prepare::<FheUint64, FheUint128>,
|
||||
swap_claim_update_dex_balance_whitepaper::<FheUint64>,
|
||||
);
|
||||
bench_swap_claim_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_claim::no_cmux",
|
||||
Dex::SwapClaim(DexFlavor::NoCmux),
|
||||
swap_claim_prepare::<FheUint64, FheUint128>,
|
||||
swap_claim_update_dex_balance_no_cmux::<FheUint64>,
|
||||
);
|
||||
group.finish();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1449,8 +1460,6 @@ fn main() {
|
||||
|
||||
let mut c = Criterion::default().sample_size(10).configure_from_args();
|
||||
|
||||
let bench_name = "hlapi::cuda::dex";
|
||||
|
||||
// FheUint64 PBS counts
|
||||
// We don't run multiple times since every input is encrypted
|
||||
// PBS count is always the same
|
||||
@@ -1459,121 +1468,110 @@ fn main() {
|
||||
print_swap_request_update_dex_balance_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"whitepaper",
|
||||
Dex::SwapRequest(DexFlavor::Whitepaper),
|
||||
swap_request_update_dex_balance_whitepaper::<FheUint64>,
|
||||
);
|
||||
print_swap_request_update_dex_balance_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"no_cmux",
|
||||
Dex::SwapRequest(DexFlavor::NoCmux),
|
||||
swap_request_update_dex_balance_no_cmux::<FheUint64>,
|
||||
);
|
||||
print_swap_request_finalize_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
Dex::SwapRequest(DexFlavor::Finalize),
|
||||
swap_request_finalize::<FheUint64>,
|
||||
);
|
||||
print_swap_claim_prepare_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
Dex::SwapClaim(DexFlavor::Prepare),
|
||||
swap_claim_prepare::<FheUint64, FheUint128>,
|
||||
);
|
||||
print_swap_claim_update_dex_balance_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"whitepaper",
|
||||
Dex::SwapClaim(DexFlavor::Whitepaper),
|
||||
swap_claim_update_dex_balance_whitepaper::<FheUint64>,
|
||||
);
|
||||
print_swap_claim_update_dex_balance_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"no_cmux",
|
||||
Dex::SwapClaim(DexFlavor::NoCmux),
|
||||
swap_claim_update_dex_balance_no_cmux::<FheUint64>,
|
||||
);
|
||||
}
|
||||
|
||||
match get_bench_type() {
|
||||
BenchmarkType::Latency => {
|
||||
let mut group = c.benchmark_group(bench_name);
|
||||
bench_swap_request_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_request::whitepaper",
|
||||
Dex::SwapRequest(DexFlavor::Whitepaper),
|
||||
swap_request_update_dex_balance_whitepaper::<FheUint64>,
|
||||
swap_request_finalize::<FheUint64>,
|
||||
);
|
||||
bench_swap_request_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_request::no_cmux",
|
||||
Dex::SwapRequest(DexFlavor::NoCmux),
|
||||
swap_request_update_dex_balance_no_cmux::<FheUint64>,
|
||||
swap_request_finalize::<FheUint64>,
|
||||
);
|
||||
bench_swap_claim_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_claim::whitepaper",
|
||||
Dex::SwapClaim(DexFlavor::Whitepaper),
|
||||
swap_claim_prepare::<FheUint64, FheUint128>,
|
||||
swap_claim_update_dex_balance_whitepaper::<FheUint64>,
|
||||
);
|
||||
bench_swap_claim_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_claim::no_cmux",
|
||||
Dex::SwapClaim(DexFlavor::NoCmux),
|
||||
swap_claim_prepare::<FheUint64, FheUint128>,
|
||||
swap_claim_update_dex_balance_no_cmux::<FheUint64>,
|
||||
);
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
BenchmarkType::Throughput => {
|
||||
let mut group = c.benchmark_group(bench_name);
|
||||
cuda_bench_swap_request_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_request::whitepaper",
|
||||
Dex::SwapRequest(DexFlavor::Whitepaper),
|
||||
swap_request_update_dex_balance_whitepaper::<FheUint64>,
|
||||
swap_request_finalize::<FheUint64>,
|
||||
);
|
||||
cuda_bench_swap_request_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_request::no_cmux",
|
||||
Dex::SwapRequest(DexFlavor::NoCmux),
|
||||
swap_request_update_dex_balance_no_cmux::<FheUint64>,
|
||||
swap_request_finalize::<FheUint64>,
|
||||
);
|
||||
cuda_bench_swap_claim_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_claim::whitepaper",
|
||||
Dex::SwapClaim(DexFlavor::Whitepaper),
|
||||
swap_claim_prepare::<FheUint64, FheUint128>,
|
||||
swap_claim_update_dex_balance_whitepaper::<FheUint64>,
|
||||
);
|
||||
cuda_bench_swap_claim_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"swap_claim::no_cmux",
|
||||
Dex::SwapClaim(DexFlavor::NoCmux),
|
||||
swap_claim_prepare::<FheUint64, FheUint128>,
|
||||
swap_claim_update_dex_balance_no_cmux::<FheUint64>,
|
||||
);
|
||||
group.finish();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use benchmark::utilities::{bench_backend_from_cfg, write_to_json, OperatorType};
|
||||
#[cfg(feature = "gpu")]
|
||||
use benchmark::utilities::{configure_gpu, get_param_type, ParamType};
|
||||
use benchmark::utilities::{write_to_json_unchecked, OperatorType};
|
||||
use benchmark_spec::{get_bench_type, BenchmarkType};
|
||||
use criterion::measurement::WallTime;
|
||||
use criterion::{BenchmarkGroup, Criterion, Throughput};
|
||||
use benchmark_spec::tfhe::hlapi::erc7984::{Erc7984, TransferFlavor};
|
||||
use benchmark_spec::{get_bench_type, BenchmarkMetric, BenchmarkSpec, BenchmarkType, OperandType};
|
||||
use criterion::{Criterion, Throughput};
|
||||
use rand::prelude::*;
|
||||
use rand::thread_rng;
|
||||
#[cfg(not(feature = "hpu"))]
|
||||
@@ -286,21 +286,14 @@ where
|
||||
|
||||
#[cfg(all(feature = "pbs-stats", not(feature = "hpu")))]
|
||||
mod pbs_stats {
|
||||
use super::*;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use benchmark_spec::TestResult;
|
||||
|
||||
fn write_result(file: &mut File, name: &str, value: usize) {
|
||||
let line = format!("{name},{value}\n");
|
||||
let error_message = format!("cannot write {name} result into file");
|
||||
file.write_all(line.as_bytes()).expect(&error_message);
|
||||
}
|
||||
use super::*;
|
||||
|
||||
pub fn print_transfer_pbs_counts<FheType, F>(
|
||||
client_key: &ClientKey,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Erc7984,
|
||||
transfer_func: F,
|
||||
) where
|
||||
FheType: FheEncrypt<u64, ClientKey>,
|
||||
@@ -324,27 +317,23 @@ mod pbs_stats {
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let test_name = if cfg!(feature = "gpu") {
|
||||
format!("hlapi::cuda::erc7984::pbs_count::{fn_name}::{params_name}::{type_name}")
|
||||
} else {
|
||||
format!("hlapi::erc7984::pbs_count::{fn_name}::{params_name}::{type_name}")
|
||||
};
|
||||
let test_name = BenchmarkSpec::new_hlapi_erc7984(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::PbsCount,
|
||||
bench_backend_from_cfg(),
|
||||
None,
|
||||
);
|
||||
|
||||
let results_file = Path::new("erc7984_pbs_count.csv");
|
||||
if !results_file.exists() {
|
||||
File::create(results_file).expect("create results file failed");
|
||||
}
|
||||
let mut file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open results file");
|
||||
let mut benchmark_test_result = TestResult::new("erc7984_pbs_count.csv");
|
||||
|
||||
write_result(&mut file, &test_name, count as usize);
|
||||
benchmark_test_result.write_result(&test_name.to_string(), count as usize);
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
write_to_json::<u64, _>(
|
||||
&test_name,
|
||||
params,
|
||||
params_name,
|
||||
"pbs-count",
|
||||
&OperatorType::Atomic,
|
||||
0,
|
||||
@@ -354,11 +343,10 @@ mod pbs_stats {
|
||||
}
|
||||
|
||||
fn bench_transfer_latency<FheType, F>(
|
||||
c: &mut BenchmarkGroup<'_, WallTime>,
|
||||
c: &mut Criterion,
|
||||
client_key: &ClientKey,
|
||||
bench_name: &str,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Erc7984,
|
||||
transfer_func: F,
|
||||
) where
|
||||
FheType: FheEncrypt<u64, ClientKey>,
|
||||
@@ -371,7 +359,18 @@ fn bench_transfer_latency<FheType, F>(
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let bench_id = format!("{bench_name}::{fn_name}::{params_name}::{type_name}");
|
||||
let mut c = c.benchmark_group(type_name);
|
||||
|
||||
let bench_spec = BenchmarkSpec::new_hlapi_erc7984(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::Latency,
|
||||
bench_backend_from_cfg(),
|
||||
None,
|
||||
);
|
||||
let bench_id = bench_spec.to_string();
|
||||
c.bench_function(&bench_id, |b| {
|
||||
let mut rng = thread_rng();
|
||||
|
||||
@@ -388,10 +387,9 @@ fn bench_transfer_latency<FheType, F>(
|
||||
})
|
||||
});
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&bench_id,
|
||||
write_to_json::<u64, _>(
|
||||
&bench_spec,
|
||||
params,
|
||||
params_name,
|
||||
"erc7984-transfer",
|
||||
&OperatorType::Atomic,
|
||||
64,
|
||||
@@ -401,11 +399,10 @@ fn bench_transfer_latency<FheType, F>(
|
||||
|
||||
#[cfg(feature = "hpu")]
|
||||
fn bench_transfer_latency_simd<FheType, F>(
|
||||
c: &mut BenchmarkGroup<'_, WallTime>,
|
||||
c: &mut Criterion,
|
||||
client_key: &ClientKey,
|
||||
bench_name: &str,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Erc7984,
|
||||
transfer_func: F,
|
||||
) where
|
||||
FheType: FheEncrypt<u64, ClientKey>,
|
||||
@@ -423,9 +420,18 @@ fn bench_transfer_latency_simd<FheType, F>(
|
||||
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
let mut c = c.benchmark_group(type_name);
|
||||
|
||||
let bench_id = format!("{bench_name}::{fn_name}::{params_name}::{type_name}");
|
||||
c.bench_function(&bench_id, |b| {
|
||||
let bench_spec = BenchmarkSpec::new_hlapi_erc7984(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::Throughput,
|
||||
bench_backend_from_cfg(),
|
||||
None,
|
||||
);
|
||||
c.bench_function(bench_spec.to_string(), |b| {
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let mut from_amounts: Vec<FheType> = vec![];
|
||||
@@ -449,10 +455,9 @@ fn bench_transfer_latency_simd<FheType, F>(
|
||||
})
|
||||
});
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&bench_id,
|
||||
write_to_json::<u64, _>(
|
||||
&bench_spec,
|
||||
params,
|
||||
params_name,
|
||||
"erc7984-simd-transfer",
|
||||
&OperatorType::Atomic,
|
||||
64,
|
||||
@@ -462,11 +467,10 @@ fn bench_transfer_latency_simd<FheType, F>(
|
||||
|
||||
#[cfg(not(any(feature = "gpu", feature = "hpu")))]
|
||||
fn bench_transfer_throughput<FheType, F>(
|
||||
group: &mut BenchmarkGroup<'_, WallTime>,
|
||||
c: &mut Criterion,
|
||||
client_key: &ClientKey,
|
||||
bench_name: &str,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Erc7984,
|
||||
transfer_func: F,
|
||||
) where
|
||||
FheType: FheEncrypt<u64, ClientKey> + Send + Sync,
|
||||
@@ -477,11 +481,20 @@ fn bench_transfer_throughput<FheType, F>(
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let mut group = c.benchmark_group(type_name);
|
||||
|
||||
for num_elems in [10, 100, 500] {
|
||||
group.throughput(Throughput::Elements(num_elems));
|
||||
let bench_id = format!(
|
||||
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
|
||||
let bench_spec = BenchmarkSpec::new_hlapi_erc7984(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::Throughput,
|
||||
bench_backend_from_cfg(),
|
||||
Some(num_elems.try_into().unwrap()),
|
||||
);
|
||||
let bench_id = bench_spec.to_string();
|
||||
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
|
||||
let from_amounts = (0..num_elems)
|
||||
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
|
||||
@@ -503,10 +516,9 @@ fn bench_transfer_throughput<FheType, F>(
|
||||
})
|
||||
});
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&bench_id,
|
||||
write_to_json::<u64, _>(
|
||||
&bench_spec,
|
||||
params,
|
||||
¶ms_name,
|
||||
"erc7984-transfer",
|
||||
&OperatorType::Atomic,
|
||||
64,
|
||||
@@ -517,11 +529,10 @@ fn bench_transfer_throughput<FheType, F>(
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
fn cuda_bench_transfer_throughput<FheType, F>(
|
||||
group: &mut BenchmarkGroup<'_, WallTime>,
|
||||
c: &mut Criterion,
|
||||
client_key: &ClientKey,
|
||||
bench_name: &str,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Erc7984,
|
||||
transfer_func: F,
|
||||
) where
|
||||
FheType: FheEncrypt<u64, ClientKey> + Send + Sync,
|
||||
@@ -542,11 +553,19 @@ fn cuda_bench_transfer_throughput<FheType, F>(
|
||||
// and is a multiple of the number of streams per GPU to avoid a bigger batch on one stream
|
||||
let num_elems = 300 * num_gpus;
|
||||
|
||||
let mut group = c.benchmark_group(type_name);
|
||||
group.throughput(Throughput::Elements(num_elems));
|
||||
let bench_id = format!(
|
||||
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
|
||||
|
||||
let bench_spec = BenchmarkSpec::new_hlapi_erc7984(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::Throughput,
|
||||
bench_backend_from_cfg(),
|
||||
Some(num_elems.try_into().unwrap()),
|
||||
);
|
||||
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
|
||||
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
|
||||
let from_amounts = (0..num_elems)
|
||||
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
|
||||
.collect::<Vec<_>>();
|
||||
@@ -593,10 +612,9 @@ fn cuda_bench_transfer_throughput<FheType, F>(
|
||||
});
|
||||
});
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&bench_id,
|
||||
write_to_json::<u64, _>(
|
||||
&bench_spec,
|
||||
params,
|
||||
¶ms_name,
|
||||
"erc7984-transfer",
|
||||
&OperatorType::Atomic,
|
||||
64,
|
||||
@@ -606,11 +624,10 @@ fn cuda_bench_transfer_throughput<FheType, F>(
|
||||
|
||||
#[cfg(feature = "hpu")]
|
||||
fn hpu_bench_transfer_throughput<FheType, F>(
|
||||
group: &mut BenchmarkGroup<'_, WallTime>,
|
||||
group: &mut Criterion,
|
||||
client_key: &ClientKey,
|
||||
bench_name: &str,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Erc7984,
|
||||
transfer_func: F,
|
||||
) where
|
||||
FheType: FheEncrypt<u64, ClientKey> + Send + Sync,
|
||||
@@ -622,12 +639,19 @@ fn hpu_bench_transfer_throughput<FheType, F>(
|
||||
let params = client_key.computation_parameters();
|
||||
let params_name = params.name();
|
||||
|
||||
let mut group = group.benchmark_group(type_name);
|
||||
for num_elems in [10, 100] {
|
||||
group.throughput(Throughput::Elements(num_elems));
|
||||
let bench_id = format!(
|
||||
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
|
||||
let bench_spec = BenchmarkSpec::new_hlapi_erc7984(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::Throughput,
|
||||
bench_backend_from_cfg(),
|
||||
Some(num_elems.try_into().unwrap()),
|
||||
);
|
||||
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
|
||||
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
|
||||
let from_amounts = (0..num_elems)
|
||||
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
|
||||
.collect::<Vec<_>>();
|
||||
@@ -657,10 +681,9 @@ fn hpu_bench_transfer_throughput<FheType, F>(
|
||||
});
|
||||
});
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&bench_id,
|
||||
write_to_json::<u64, _>(
|
||||
&bench_spec,
|
||||
params,
|
||||
¶ms_name,
|
||||
"erc7984-transfer",
|
||||
&OperatorType::Atomic,
|
||||
64,
|
||||
@@ -671,11 +694,10 @@ fn hpu_bench_transfer_throughput<FheType, F>(
|
||||
|
||||
#[cfg(feature = "hpu")]
|
||||
fn hpu_bench_transfer_throughput_simd<FheType, F>(
|
||||
group: &mut BenchmarkGroup<'_, WallTime>,
|
||||
group: &mut Criterion,
|
||||
client_key: &ClientKey,
|
||||
bench_name: &str,
|
||||
type_name: &str,
|
||||
fn_name: &str,
|
||||
fn_name: Erc7984,
|
||||
transfer_func: F,
|
||||
) where
|
||||
FheType: FheEncrypt<u64, ClientKey> + Send + Sync,
|
||||
@@ -698,9 +720,16 @@ fn hpu_bench_transfer_throughput_simd<FheType, F>(
|
||||
for num_elems in [2, 8] {
|
||||
let real_num_elems = num_elems * (hpu_simd_n as u64);
|
||||
group.throughput(Throughput::Elements(real_num_elems));
|
||||
let bench_id =
|
||||
format!("{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{real_num_elems}_elems");
|
||||
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
|
||||
let bench_spec = BenchmarkSpec::new_hlapi_erc7984(
|
||||
fn_name,
|
||||
¶ms_name,
|
||||
&OperandType::CipherText,
|
||||
Some(type_name),
|
||||
BenchmarkMetric::Throughput,
|
||||
bench_backend_from_cfg(),
|
||||
Some(real_num_elems.try_into().unwrap()),
|
||||
);
|
||||
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
|
||||
let from_amounts = (0..num_elems)
|
||||
.map(|_| {
|
||||
(0..hpu_simd_n)
|
||||
@@ -742,11 +771,10 @@ fn hpu_bench_transfer_throughput_simd<FheType, F>(
|
||||
});
|
||||
});
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&bench_id,
|
||||
write_to_json::<u64, _>(
|
||||
&bench_spec,
|
||||
params,
|
||||
¶ms_name,
|
||||
"erc7984-simd-ransfer",
|
||||
"erc7984-simd-transfer",
|
||||
&OperatorType::Atomic,
|
||||
64,
|
||||
vec![],
|
||||
@@ -769,8 +797,6 @@ fn main() {
|
||||
|
||||
let mut c = Criterion::default().sample_size(10).configure_from_args();
|
||||
|
||||
let bench_name = "hlapi::erc7984";
|
||||
|
||||
// FheUint64 PBS counts
|
||||
// We don't run multiple times since every input is encrypted
|
||||
// PBS count is always the same
|
||||
@@ -780,99 +806,90 @@ fn main() {
|
||||
print_transfer_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"transfer::whitepaper",
|
||||
Erc7984::Transfer(TransferFlavor::Whitepaper),
|
||||
par_transfer_whitepaper::<FheUint64>,
|
||||
);
|
||||
print_transfer_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"no_cmux",
|
||||
Erc7984::Transfer(TransferFlavor::NoCmux),
|
||||
par_transfer_no_cmux::<FheUint64>,
|
||||
);
|
||||
print_transfer_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"transfer::overflow",
|
||||
Erc7984::Transfer(TransferFlavor::Overflow),
|
||||
par_transfer_overflow::<FheUint64>,
|
||||
);
|
||||
print_transfer_pbs_counts(&cks, "FheUint64", "safe", par_transfer_safe::<FheUint64>);
|
||||
print_transfer_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
Erc7984::Transfer(TransferFlavor::Safe),
|
||||
par_transfer_safe::<FheUint64>,
|
||||
);
|
||||
}
|
||||
|
||||
match get_bench_type() {
|
||||
BenchmarkType::Latency => {
|
||||
let mut group = c.benchmark_group(bench_name);
|
||||
bench_transfer_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::whitepaper",
|
||||
Erc7984::Transfer(TransferFlavor::Whitepaper),
|
||||
par_transfer_whitepaper::<FheUint64>,
|
||||
);
|
||||
bench_transfer_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::no_cmux",
|
||||
Erc7984::Transfer(TransferFlavor::NoCmux),
|
||||
par_transfer_no_cmux::<FheUint64>,
|
||||
);
|
||||
bench_transfer_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::overflow",
|
||||
Erc7984::Transfer(TransferFlavor::Overflow),
|
||||
par_transfer_overflow::<FheUint64>,
|
||||
);
|
||||
bench_transfer_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::safe",
|
||||
Erc7984::Transfer(TransferFlavor::Safe),
|
||||
par_transfer_safe::<FheUint64>,
|
||||
);
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
BenchmarkType::Throughput => {
|
||||
let mut group = c.benchmark_group(bench_name);
|
||||
bench_transfer_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::whitepaper",
|
||||
Erc7984::Transfer(TransferFlavor::Whitepaper),
|
||||
par_transfer_whitepaper::<FheUint64>,
|
||||
);
|
||||
bench_transfer_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::no_cmux",
|
||||
Erc7984::Transfer(TransferFlavor::NoCmux),
|
||||
par_transfer_no_cmux::<FheUint64>,
|
||||
);
|
||||
bench_transfer_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::overflow",
|
||||
Erc7984::Transfer(TransferFlavor::Overflow),
|
||||
par_transfer_overflow::<FheUint64>,
|
||||
);
|
||||
bench_transfer_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::safe",
|
||||
Erc7984::Transfer(TransferFlavor::Safe),
|
||||
par_transfer_safe::<FheUint64>,
|
||||
);
|
||||
|
||||
group.finish();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -896,8 +913,6 @@ fn main() {
|
||||
|
||||
let mut c = Criterion::default().sample_size(10).configure_from_args();
|
||||
|
||||
let bench_name = "hlapi::cuda::erc7984";
|
||||
|
||||
// FheUint64 PBS counts
|
||||
// We don't run multiple times since every input is encrypted
|
||||
// PBS count is always the same
|
||||
@@ -907,98 +922,90 @@ fn main() {
|
||||
print_transfer_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"transfer::whitepaper",
|
||||
Erc7984::Transfer(TransferFlavor::Whitepaper),
|
||||
par_transfer_whitepaper::<FheUint64>,
|
||||
);
|
||||
print_transfer_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"no_cmux",
|
||||
Erc7984::Transfer(TransferFlavor::NoCmux),
|
||||
par_transfer_no_cmux::<FheUint64>,
|
||||
);
|
||||
print_transfer_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
"transfer::overflow",
|
||||
Erc7984::Transfer(TransferFlavor::Overflow),
|
||||
par_transfer_overflow::<FheUint64>,
|
||||
);
|
||||
print_transfer_pbs_counts(&cks, "FheUint64", "safe", par_transfer_safe::<FheUint64>);
|
||||
print_transfer_pbs_counts(
|
||||
&cks,
|
||||
"FheUint64",
|
||||
Erc7984::Transfer(TransferFlavor::Safe),
|
||||
par_transfer_safe::<FheUint64>,
|
||||
);
|
||||
}
|
||||
|
||||
match get_bench_type() {
|
||||
BenchmarkType::Latency => {
|
||||
let mut group = c.benchmark_group(bench_name);
|
||||
bench_transfer_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::whitepaper",
|
||||
Erc7984::Transfer(TransferFlavor::Whitepaper),
|
||||
par_transfer_whitepaper::<FheUint64>,
|
||||
);
|
||||
bench_transfer_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::no_cmux",
|
||||
Erc7984::Transfer(TransferFlavor::NoCmux),
|
||||
par_transfer_no_cmux::<FheUint64>,
|
||||
);
|
||||
bench_transfer_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::overflow",
|
||||
Erc7984::Transfer(TransferFlavor::Overflow),
|
||||
par_transfer_overflow::<FheUint64>,
|
||||
);
|
||||
bench_transfer_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::safe",
|
||||
Erc7984::Transfer(TransferFlavor::Safe),
|
||||
par_transfer_safe::<FheUint64>,
|
||||
);
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
BenchmarkType::Throughput => {
|
||||
let mut group = c.benchmark_group(bench_name);
|
||||
cuda_bench_transfer_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::whitepaper",
|
||||
Erc7984::Transfer(TransferFlavor::Whitepaper),
|
||||
transfer_whitepaper::<FheUint64>,
|
||||
);
|
||||
cuda_bench_transfer_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::no_cmux",
|
||||
Erc7984::Transfer(TransferFlavor::NoCmux),
|
||||
transfer_no_cmux::<FheUint64>,
|
||||
);
|
||||
cuda_bench_transfer_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::overflow",
|
||||
Erc7984::Transfer(TransferFlavor::Overflow),
|
||||
transfer_overflow::<FheUint64>,
|
||||
);
|
||||
cuda_bench_transfer_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::safe",
|
||||
Erc7984::Transfer(TransferFlavor::Safe),
|
||||
transfer_safe::<FheUint64>,
|
||||
);
|
||||
group.finish();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1027,69 +1034,57 @@ fn main() {
|
||||
|
||||
let mut c = Criterion::default().sample_size(10).configure_from_args();
|
||||
|
||||
let bench_name = "hlapi::hpu::erc7984";
|
||||
|
||||
match get_bench_type() {
|
||||
BenchmarkType::Latency => {
|
||||
let mut group = c.benchmark_group(bench_name);
|
||||
bench_transfer_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::whitepaper",
|
||||
Erc7984::Transfer(TransferFlavor::Whitepaper),
|
||||
transfer_whitepaper::<FheUint64>,
|
||||
);
|
||||
// Erc7984 optimized instruction only available on Hpu
|
||||
bench_transfer_latency(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::hpu_optim",
|
||||
Erc7984::Transfer(TransferFlavor::HpuOptim),
|
||||
transfer_hpu::<FheUint64>,
|
||||
);
|
||||
// Erc7984 SIMD instruction only available on Hpu
|
||||
bench_transfer_latency_simd(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::hpu_simd",
|
||||
Erc7984::Transfer(TransferFlavor::HpuSimd),
|
||||
transfer_hpu_simd::<FheUint64>,
|
||||
);
|
||||
group.finish();
|
||||
}
|
||||
|
||||
BenchmarkType::Throughput => {
|
||||
let mut group = c.benchmark_group(bench_name);
|
||||
hpu_bench_transfer_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::whitepaper",
|
||||
Erc7984::Transfer(TransferFlavor::Whitepaper),
|
||||
transfer_whitepaper::<FheUint64>,
|
||||
);
|
||||
// Erc7984 optimized instruction only available on Hpu
|
||||
hpu_bench_transfer_throughput(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::hpu_optim",
|
||||
Erc7984::Transfer(TransferFlavor::HpuOptim),
|
||||
transfer_hpu::<FheUint64>,
|
||||
);
|
||||
// Erc7984 SIMD instruction only available on Hpu
|
||||
hpu_bench_transfer_throughput_simd(
|
||||
&mut group,
|
||||
&mut c,
|
||||
&cks,
|
||||
bench_name,
|
||||
"FheUint64",
|
||||
"transfer::hpu_simd",
|
||||
Erc7984::Transfer(TransferFlavor::HpuSimd),
|
||||
transfer_hpu_simd::<FheUint64>,
|
||||
);
|
||||
group.finish();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use benchmark::params_aliases::*;
|
||||
use benchmark::utilities::{throughput_num_threads, write_to_json_unchecked, OperatorType};
|
||||
use benchmark_spec::{get_bench_type, BenchmarkType};
|
||||
use benchmark_spec::{get_bench_type, BenchmarkType, TestResult};
|
||||
use criterion::{criterion_group, Criterion, Throughput};
|
||||
use rand::prelude::*;
|
||||
use rayon::prelude::*;
|
||||
use std::env;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use tfhe::core_crypto::prelude::LweCiphertextCount;
|
||||
use tfhe::integer::key_switching_key::KeySwitchingKey;
|
||||
@@ -61,12 +59,6 @@ fn compute_load_config() -> Vec<ZkComputeLoad> {
|
||||
conf
|
||||
}
|
||||
|
||||
fn write_result(file: &mut File, name: &str, value: usize) {
|
||||
let line = format!("{name},{value}\n");
|
||||
let error_message = format!("cannot write {name} result into file");
|
||||
file.write_all(line.as_bytes()).expect(&error_message);
|
||||
}
|
||||
|
||||
fn zk_throughput_num_elements() -> u64 {
|
||||
// Zk verify uses pools of 32 threads for a single verification
|
||||
let pool_size = 32;
|
||||
@@ -217,11 +209,7 @@ fn cpu_pke_zk_verify(c: &mut Criterion, results_file: &Path) {
|
||||
.sample_size(15)
|
||||
.measurement_time(std::time::Duration::from_secs(60));
|
||||
|
||||
File::create(results_file).expect("create results file failed");
|
||||
let mut file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open results file");
|
||||
let mut benchmark_test_result = TestResult::from_path(results_file);
|
||||
|
||||
for (param_pke, param_casting, param_fhe) in [(
|
||||
BENCH_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
@@ -271,7 +259,8 @@ fn cpu_pke_zk_verify(c: &mut Criterion, results_file: &Path) {
|
||||
let test_name =
|
||||
format!("zk::crs_sizes::{param_name}::{bits}_bits_packed_ZK{zk_vers:?}");
|
||||
|
||||
write_result(&mut file, &test_name, crs_data.len());
|
||||
benchmark_test_result.write_result(&test_name, crs_data.len());
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
shortint_params,
|
||||
@@ -321,11 +310,9 @@ fn cpu_pke_zk_verify(c: &mut Criterion, results_file: &Path) {
|
||||
"zk::proven_list_size::{param_name}::{bits}_bits_packed_{crs_size}_bits_crs_{zk_load}_ZK{zk_vers:?}"
|
||||
);
|
||||
|
||||
write_result(
|
||||
&mut file,
|
||||
&test_name,
|
||||
proven_ciphertext_list_serialized.len(),
|
||||
);
|
||||
benchmark_test_result
|
||||
.write_result(&test_name, proven_ciphertext_list_serialized.len());
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
shortint_params,
|
||||
@@ -342,7 +329,8 @@ fn cpu_pke_zk_verify(c: &mut Criterion, results_file: &Path) {
|
||||
let test_name =
|
||||
format!("zk::proof_sizes::{param_name}::{bits}_bits_packed_{crs_size}_bits_crs_{zk_load}_ZK{zk_vers:?}");
|
||||
|
||||
write_result(&mut file, &test_name, proof_size);
|
||||
benchmark_test_result.write_result(&test_name, proof_size);
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
shortint_params,
|
||||
@@ -522,11 +510,7 @@ mod cuda {
|
||||
.sample_size(15)
|
||||
.measurement_time(std::time::Duration::from_secs(60));
|
||||
|
||||
File::create(results_file).expect("create results file failed");
|
||||
let mut file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open results file");
|
||||
let mut benchmark_test_result = TestResult::from_path(results_file);
|
||||
|
||||
let (param_pke, param_ksk, param_fhe): (
|
||||
CompactPublicKeyEncryptionParameters,
|
||||
@@ -590,7 +574,7 @@ mod cuda {
|
||||
let test_name =
|
||||
format!("zk::crs_sizes::{param_name}::{bits}_bits_packed_ZK{zk_vers:?}");
|
||||
|
||||
write_result(&mut file, &test_name, crs_data.len());
|
||||
benchmark_test_result.write_result(&test_name, crs_data.len());
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
param_fhe,
|
||||
@@ -660,11 +644,8 @@ mod cuda {
|
||||
"zk::proven_list_size::{param_name}::{bits}_bits_packed_{crs_size}_bits_crs_{zk_load}_ZK{zk_vers:?}"
|
||||
);
|
||||
|
||||
write_result(
|
||||
&mut file,
|
||||
&test_name,
|
||||
proven_ciphertext_list_serialized.len(),
|
||||
);
|
||||
benchmark_test_result
|
||||
.write_result(&test_name, proven_ciphertext_list_serialized.len());
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
param_fhe,
|
||||
@@ -681,7 +662,7 @@ mod cuda {
|
||||
let test_name =
|
||||
format!("zk::proof_sizes::{param_name}::{bits}_bits_packed_{crs_size}_bits_crs_{zk_load}_ZK{zk_vers:?}");
|
||||
|
||||
write_result(&mut file, &test_name, proof_size);
|
||||
benchmark_test_result.write_result(&test_name, proof_size);
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
param_fhe,
|
||||
|
||||
@@ -1,26 +1,16 @@
|
||||
use benchmark::utilities::{write_to_json_unchecked, OperatorType};
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::Write;
|
||||
use benchmark_spec::TestResult;
|
||||
use std::path::Path;
|
||||
use tfhe::boolean::parameters::{DEFAULT_PARAMETERS, PARAMETERS_ERROR_PROB_2_POW_MINUS_165};
|
||||
use tfhe::boolean::{client_key, server_key};
|
||||
|
||||
fn write_result(file: &mut File, name: &str, value: usize) {
|
||||
let line = format!("{name},{value}\n");
|
||||
let error_message = format!("cannot write {name} result into file");
|
||||
file.write_all(line.as_bytes()).expect(&error_message);
|
||||
}
|
||||
|
||||
fn client_server_key_sizes(results_file: &Path) {
|
||||
let boolean_params_vec = [
|
||||
(DEFAULT_PARAMETERS, "DEFAULT_PARAMETERS"),
|
||||
(PARAMETERS_ERROR_PROB_2_POW_MINUS_165, "TFHE_LIB_PARAMETERS"),
|
||||
];
|
||||
File::create(results_file).expect("create results file failed");
|
||||
let mut file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open results file");
|
||||
|
||||
let mut benchmark_test_result = TestResult::from_path(results_file);
|
||||
|
||||
let operator = OperatorType::Atomic;
|
||||
|
||||
@@ -38,7 +28,7 @@ fn client_server_key_sizes(results_file: &Path) {
|
||||
let ksk_size = sks.key_switching_key_size_bytes();
|
||||
let test_name = format!("boolean_key_sizes_{params_name}_ksk");
|
||||
|
||||
write_result(&mut file, &test_name, ksk_size);
|
||||
benchmark_test_result.write_result(&test_name, ksk_size);
|
||||
write_to_json_unchecked::<u32, _>(
|
||||
&test_name,
|
||||
*params,
|
||||
@@ -58,7 +48,7 @@ fn client_server_key_sizes(results_file: &Path) {
|
||||
let bsk_size = sks.bootstrapping_key_size_bytes();
|
||||
let test_name = format!("boolean_key_sizes_{params_name}_bsk");
|
||||
|
||||
write_result(&mut file, &test_name, bsk_size);
|
||||
benchmark_test_result.write_result(&test_name, bsk_size);
|
||||
write_to_json_unchecked::<u32, _>(
|
||||
&test_name,
|
||||
*params,
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use benchmark::params::{get_classical_tuniform_groups, get_multi_bit_tuniform_groups};
|
||||
use benchmark::params_aliases::*;
|
||||
use benchmark::utilities::{write_to_json_unchecked, OperatorType};
|
||||
use benchmark_spec::TestResult;
|
||||
use rand::Rng;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use tfhe::integer::U256;
|
||||
use tfhe::keycache::NamedParam;
|
||||
@@ -15,22 +14,10 @@ use tfhe::{
|
||||
CompressedSquashedNoiseCiphertextList, ConfigBuilder, FheUint64,
|
||||
};
|
||||
|
||||
fn write_result(file: &mut File, name: &str, value: usize) {
|
||||
let line = format!("{name},{value}\n");
|
||||
let error_message = format!("cannot write {name} result into file");
|
||||
file.write_all(line.as_bytes()).expect(&error_message);
|
||||
}
|
||||
|
||||
pub fn ct_sizes(results_file: &Path) {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
File::create(results_file).expect("create results file failed");
|
||||
let mut file = OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open results file");
|
||||
let mut benchmark_test_result = TestResult::from_path(results_file);
|
||||
|
||||
let operator = OperatorType::Atomic;
|
||||
|
||||
@@ -87,7 +74,7 @@ pub fn ct_sizes(results_file: &Path) {
|
||||
let params_record = param_fhe;
|
||||
|
||||
let mut write_and_record_result = |res: usize, test_name: &str, display_name: &str| {
|
||||
write_result(&mut file, test_name, res);
|
||||
benchmark_test_result.write_result(test_name, res);
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
test_name,
|
||||
params_record,
|
||||
@@ -174,13 +161,7 @@ pub fn cpk_and_cctl_sizes(results_file: &Path) {
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
File::create(results_file).expect("create results file failed");
|
||||
let mut file = OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open results file");
|
||||
let mut benchmark_test_result = TestResult::from_path(results_file);
|
||||
|
||||
let operator = OperatorType::Atomic;
|
||||
|
||||
@@ -205,7 +186,7 @@ pub fn cpk_and_cctl_sizes(results_file: &Path) {
|
||||
let cpk_size = bincode::serialize(&public_key).unwrap().len();
|
||||
|
||||
println!("PK size: {cpk_size} bytes");
|
||||
write_result(&mut file, &test_name, cpk_size);
|
||||
benchmark_test_result.write_result(&test_name, cpk_size);
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
params,
|
||||
@@ -227,7 +208,7 @@ pub fn cpk_and_cctl_sizes(results_file: &Path) {
|
||||
|
||||
println!("Compact CT list for {NB_CTXT} CTs: {cctl_size} bytes");
|
||||
|
||||
write_result(&mut file, &test_name, cctl_size);
|
||||
benchmark_test_result.write_result(&test_name, cctl_size);
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
params,
|
||||
@@ -273,7 +254,7 @@ pub fn cpk_and_cctl_sizes(results_file: &Path) {
|
||||
|
||||
println!("Compact CT list for {NB_CTXT} CTs: {cctl_size} bytes");
|
||||
|
||||
write_result(&mut file, &test_name, cctl_size);
|
||||
benchmark_test_result.write_result(&test_name, cctl_size);
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
params,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use benchmark::params::get_classical_tuniform_groups;
|
||||
use benchmark::params_aliases::*;
|
||||
use benchmark::utilities::{write_to_json_unchecked, CryptoParametersRecord, OperatorType};
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::Write;
|
||||
use benchmark_spec::TestResult;
|
||||
use std::path::Path;
|
||||
use tfhe::keycache::NamedParam;
|
||||
use tfhe::shortint::atomic_pattern::compressed::CompressedAtomicPatternServerKey;
|
||||
@@ -18,12 +17,6 @@ use tfhe::shortint::{
|
||||
CompressedServerKey, PBSParameters, ServerKey,
|
||||
};
|
||||
|
||||
fn write_result(file: &mut File, name: &str, value: usize) {
|
||||
let line = format!("{name},{value}\n");
|
||||
let error_message = format!("cannot write {name} result into file");
|
||||
file.write_all(line.as_bytes()).expect(&error_message);
|
||||
}
|
||||
|
||||
fn client_server_key_sizes(results_file: &Path) {
|
||||
let shortint_params_vec: Vec<PBSParameters> = vec![
|
||||
BENCH_PARAM_MESSAGE_1_CARRY_1_KS_PBS_TUNIFORM_2M128.into(),
|
||||
@@ -59,11 +52,8 @@ fn client_server_key_sizes(results_file: &Path) {
|
||||
BENCH_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_3_CARRY_3_KS_PBS_TUNIFORM_2M128.into(),
|
||||
BENCH_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_4_CARRY_4_KS_PBS_TUNIFORM_2M128.into(),
|
||||
];
|
||||
File::create(results_file).expect("create results file failed");
|
||||
let mut file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open results file");
|
||||
|
||||
let mut benchmark_test_result = TestResult::from_path(results_file);
|
||||
|
||||
let operator = OperatorType::Atomic;
|
||||
|
||||
@@ -83,7 +73,8 @@ fn client_server_key_sizes(results_file: &Path) {
|
||||
let ksk_size = sks.key_switching_key_size_bytes();
|
||||
let test_name = format!("shortint_key_sizes_{}_ksk", params.name());
|
||||
|
||||
write_result(&mut file, &test_name, ksk_size);
|
||||
benchmark_test_result.write_result(&test_name, ksk_size);
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
params,
|
||||
@@ -103,7 +94,8 @@ fn client_server_key_sizes(results_file: &Path) {
|
||||
let bsk_size = sks.bootstrapping_key_size_bytes();
|
||||
let test_name = format!("shortint_key_sizes_{}_bsk", params.name());
|
||||
|
||||
write_result(&mut file, &test_name, bsk_size);
|
||||
benchmark_test_result.write_result(&test_name, bsk_size);
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
params,
|
||||
@@ -124,7 +116,8 @@ fn client_server_key_sizes(results_file: &Path) {
|
||||
let bsk_compressed_size = sks_compressed.bootstrapping_key_size_bytes();
|
||||
let test_name = format!("shortint_key_sizes_{}_bsk_compressed", params.name());
|
||||
|
||||
write_result(&mut file, &test_name, bsk_compressed_size);
|
||||
benchmark_test_result.write_result(&test_name, bsk_compressed_size);
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
params,
|
||||
@@ -152,12 +145,12 @@ fn measure_serialized_size<T: serde::Serialize, P: Into<CryptoParametersRecord<u
|
||||
param_name: &str,
|
||||
test_name_suffix: &str,
|
||||
display_name: &str,
|
||||
file: &mut File,
|
||||
file: &mut TestResult,
|
||||
) {
|
||||
let serialized = bincode::serialize(to_serialize).unwrap();
|
||||
let size = serialized.len();
|
||||
let test_name = format!("shortint_key_sizes_{param_name}_{test_name_suffix}");
|
||||
write_result(file, &test_name, size);
|
||||
file.write_result(&test_name, size);
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
&test_name,
|
||||
param.clone(),
|
||||
@@ -172,11 +165,7 @@ fn measure_serialized_size<T: serde::Serialize, P: Into<CryptoParametersRecord<u
|
||||
}
|
||||
|
||||
fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
File::create(results_file).expect("create results file failed");
|
||||
let mut file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open results file");
|
||||
let mut benchmark_test_result = TestResult::from_path(results_file);
|
||||
|
||||
println!("Measuring shortint key sizes:");
|
||||
|
||||
@@ -200,7 +189,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_fhe_name,
|
||||
"ksk",
|
||||
"KSK",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
measure_serialized_size(
|
||||
&ap.bootstrapping_key,
|
||||
@@ -208,7 +197,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_fhe_name,
|
||||
"bsk",
|
||||
"BSK",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
}
|
||||
AtomicPatternServerKey::KeySwitch32(ap) => {
|
||||
@@ -218,7 +207,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_fhe_name,
|
||||
"ksk",
|
||||
"KSK",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
measure_serialized_size(
|
||||
&ap.bootstrapping_key,
|
||||
@@ -226,7 +215,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_fhe_name,
|
||||
"bsk",
|
||||
"BSK",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
}
|
||||
AtomicPatternServerKey::Dynamic(_) => panic!("Dynamic atomic pattern not supported"),
|
||||
@@ -240,7 +229,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_fhe_name,
|
||||
"ksk_compressed",
|
||||
"KSK",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
measure_serialized_size(
|
||||
&comp_ap.bootstrapping_key(),
|
||||
@@ -248,7 +237,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_fhe_name,
|
||||
"bsk_compressed",
|
||||
"BSK",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
}
|
||||
CompressedAtomicPatternServerKey::KeySwitch32(comp_ap) => {
|
||||
@@ -258,7 +247,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_fhe_name,
|
||||
"ksk_compressed",
|
||||
"KSK",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
measure_serialized_size(
|
||||
&comp_ap.bootstrapping_key(),
|
||||
@@ -266,7 +255,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_fhe_name,
|
||||
"bsk_compressed",
|
||||
"BSK",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -278,14 +267,21 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
let compressed_pk = CompressedCompactPublicKey::new(&compact_private_key);
|
||||
let pk = compressed_pk.decompress();
|
||||
|
||||
measure_serialized_size(&pk, pke_param, ¶m_pke_name, "cpk", "CPK", &mut file);
|
||||
measure_serialized_size(
|
||||
&pk,
|
||||
pke_param,
|
||||
¶m_pke_name,
|
||||
"cpk",
|
||||
"CPK",
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
measure_serialized_size(
|
||||
&compressed_pk,
|
||||
pke_param,
|
||||
¶m_pke_name,
|
||||
"cpk_compressed",
|
||||
"CPK",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
|
||||
let casting_param = dedicated_pke_params.ksk_params;
|
||||
@@ -303,7 +299,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_casting_name,
|
||||
"casting_key",
|
||||
"CastKey",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
measure_serialized_size(
|
||||
&compressed_casting_key.into_raw_parts().0,
|
||||
@@ -311,7 +307,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_casting_name,
|
||||
"casting_key_compressed",
|
||||
"CastKey",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -329,7 +325,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_compression_name,
|
||||
"compression_key",
|
||||
"CompressionKey",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
measure_serialized_size(
|
||||
&decompression_key,
|
||||
@@ -337,7 +333,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_compression_name,
|
||||
"decompression_key",
|
||||
"CompressionKey",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
|
||||
let (compressed_compression_key, compressed_decompression_key) =
|
||||
@@ -349,7 +345,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_compression_name,
|
||||
"compressed_compression_key",
|
||||
"CompressedCompressionKey",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
measure_serialized_size(
|
||||
&compressed_decompression_key,
|
||||
@@ -357,7 +353,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
¶m_compression_name,
|
||||
"compressed_decompression_key",
|
||||
"CompressedCompressionKey",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -373,7 +369,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
&noise_squashing_param.name(),
|
||||
"noise_squashing_key",
|
||||
"NoiseSquashingKey",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
if let Some(noise_squashing_comp_param) =
|
||||
meta_noise_squashing_param.compression_parameters
|
||||
@@ -392,7 +388,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
|
||||
&noise_squashing_comp_param.name(),
|
||||
"noise_squashing_compression_key",
|
||||
"NoiseSquashingCompressionKey",
|
||||
&mut file,
|
||||
&mut benchmark_test_result,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use benchmark::utilities::{write_to_json_unchecked, OperatorType};
|
||||
use benchmark_spec::TestResult;
|
||||
use clap::Parser;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use tfhe::keycache::NamedParam;
|
||||
use tfhe::shortint::keycache::get_shortint_parameter_set_from_name;
|
||||
@@ -29,18 +28,8 @@ fn params_from_name(name: &str) -> ClassicPBSParameters {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_result(file: &mut File, name: &str, value: usize) {
|
||||
let line = format!("{name},{value}\n");
|
||||
let error_message = format!("cannot write {name} result into file");
|
||||
file.write_all(line.as_bytes()).expect(&error_message);
|
||||
}
|
||||
|
||||
pub fn parse_wasm_benchmarks(results_file: &Path, raw_results_file: &Path) {
|
||||
File::create(results_file).expect("create results file failed");
|
||||
let mut file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(results_file)
|
||||
.expect("cannot open parsed results file");
|
||||
let mut benchmark_test_result = TestResult::from_path(results_file);
|
||||
|
||||
let operator = OperatorType::Atomic;
|
||||
|
||||
@@ -60,10 +49,10 @@ pub fn parse_wasm_benchmarks(results_file: &Path, raw_results_file: &Path) {
|
||||
let params: PBSParameters = params_from_name(name_parts[1]).into();
|
||||
println!("{name_parts:?}");
|
||||
if full_name.contains("_size") {
|
||||
write_result(&mut file, &prefixed_full_name, *val as usize);
|
||||
benchmark_test_result.write_result(&prefixed_full_name, *val as usize);
|
||||
} else {
|
||||
let value_in_ns = (val * 1_000_000_f32) as usize;
|
||||
write_result(&mut file, &prefixed_full_name, value_in_ns);
|
||||
benchmark_test_result.write_result(&prefixed_full_name, value_in_ns);
|
||||
}
|
||||
|
||||
write_to_json_unchecked::<u64, _>(
|
||||
|
||||
@@ -342,28 +342,6 @@ impl<G: Curve> Proof<G> {
|
||||
None => ComputeLoad::Verify,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_le_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = Vec::new();
|
||||
|
||||
let Self {
|
||||
c_hat,
|
||||
c_y,
|
||||
pi,
|
||||
compute_load_proof_fields,
|
||||
} = self;
|
||||
|
||||
bytes.extend_from_slice(c_hat.to_le_bytes().as_ref());
|
||||
bytes.extend_from_slice(c_y.to_le_bytes().as_ref());
|
||||
bytes.extend_from_slice(pi.to_le_bytes().as_ref());
|
||||
let (c_hat_t_bytes, c_h_bytes, pi_kzg_bytes) =
|
||||
ComputeLoadProofFields::to_le_bytes(compute_load_proof_fields);
|
||||
bytes.extend_from_slice(&c_hat_t_bytes);
|
||||
bytes.extend_from_slice(&c_h_bytes);
|
||||
bytes.extend_from_slice(&pi_kzg_bytes);
|
||||
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Curve> ParameterSetConformant for Proof<G> {
|
||||
@@ -426,26 +404,6 @@ pub(crate) struct ComputeLoadProofFields<G: Curve> {
|
||||
pub(crate) pi_kzg: G::G1,
|
||||
}
|
||||
|
||||
impl<G: Curve> ComputeLoadProofFields<G> {
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn to_le_bytes(fields: &Option<Self>) -> (Box<[u8]>, Box<[u8]>, Box<[u8]>) {
|
||||
if let Some(ComputeLoadProofFields {
|
||||
c_hat_t,
|
||||
c_h,
|
||||
pi_kzg,
|
||||
}) = fields.as_ref()
|
||||
{
|
||||
(
|
||||
Box::from(G::G2::to_le_bytes(*c_hat_t).as_ref()),
|
||||
Box::from(G::G1::to_le_bytes(*c_h).as_ref()),
|
||||
Box::from(G::G1::to_le_bytes(*pi_kzg).as_ref()),
|
||||
)
|
||||
} else {
|
||||
(Box::from([]), Box::from([]), Box::from([]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type CompressedG2<G> = <<G as Curve>::G2 as Compressible>::Compressed;
|
||||
type CompressedG1<G> = <<G as Curve>::G1 as Compressible>::Compressed;
|
||||
|
||||
|
||||
@@ -440,44 +440,6 @@ impl<G: Curve> Proof<G> {
|
||||
pub fn hash_config(&self) -> PkeV2SupportedHashConfig {
|
||||
self.hash_config
|
||||
}
|
||||
|
||||
pub fn to_le_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = Vec::new();
|
||||
|
||||
let Self {
|
||||
C_hat_e,
|
||||
C_e,
|
||||
C_r_tilde,
|
||||
C_R,
|
||||
C_hat_bin,
|
||||
C_y,
|
||||
C_h1,
|
||||
C_h2,
|
||||
C_hat_t,
|
||||
pi,
|
||||
pi_kzg,
|
||||
compute_load_proof_fields,
|
||||
hash_config: _,
|
||||
} = self;
|
||||
|
||||
bytes.extend_from_slice(C_hat_e.to_le_bytes().as_ref());
|
||||
bytes.extend_from_slice(C_e.to_le_bytes().as_ref());
|
||||
bytes.extend_from_slice(C_r_tilde.to_le_bytes().as_ref());
|
||||
bytes.extend_from_slice(C_R.to_le_bytes().as_ref());
|
||||
bytes.extend_from_slice(C_hat_bin.to_le_bytes().as_ref());
|
||||
bytes.extend_from_slice(C_y.to_le_bytes().as_ref());
|
||||
bytes.extend_from_slice(C_h1.to_le_bytes().as_ref());
|
||||
bytes.extend_from_slice(C_h2.to_le_bytes().as_ref());
|
||||
bytes.extend_from_slice(C_hat_t.to_le_bytes().as_ref());
|
||||
bytes.extend_from_slice(pi.to_le_bytes().as_ref());
|
||||
bytes.extend_from_slice(pi_kzg.to_le_bytes().as_ref());
|
||||
let (C_hat_h3_bytes, C_hat_w_bytes) =
|
||||
ComputeLoadProofFields::to_le_bytes(compute_load_proof_fields);
|
||||
bytes.extend_from_slice(&C_hat_h3_bytes);
|
||||
bytes.extend_from_slice(&C_hat_w_bytes);
|
||||
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
/// These fields can be pre-computed on the prover side in the faster Verifier scheme. If that's the
|
||||
|
||||
@@ -99,7 +99,7 @@ serde-wasm-bindgen = { workspace = true, optional = true }
|
||||
getrandom = { workspace = true, optional = true }
|
||||
bytemuck = { workspace = true }
|
||||
|
||||
tfhe-hpu-backend = { version = "0.5", path = "../backends/tfhe-hpu-backend", optional = true }
|
||||
tfhe-hpu-backend = { version = "0.4", path = "../backends/tfhe-hpu-backend", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["avx512"]
|
||||
|
||||
@@ -8,23 +8,23 @@
|
||||
<rect x="0" y="40" width="300" height="520" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="520" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">Negation (-)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">77.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">71.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">9.08 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">8.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">Add / Sub (+,-)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">91.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">93.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">9.07 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">8.35 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">Mul (x)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">357 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">352 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">32.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">122 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">Equal / Not Equal (eq, ne)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="180.0">72.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="180.0">70.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">7.03 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="180.0">6.77 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="220.0">Comparisons (ge, gt, le, lt)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="220.0">89.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="220.0">87.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">10.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="220.0">6.81 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="260.0">Max / Min (max, min)</text>
|
||||
@@ -32,31 +32,31 @@
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">15.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="260.0">11.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="300.0">Bitwise operations (&, |, ^)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="300.0">19.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="300.0">19.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">1.99 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="300.0">2.95 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="340.0">Div / Rem (/, %)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="340.0">4.88 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="340.0">5.04 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">514 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="340.0">912 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="380.0">Left / Right Shifts (<<, >>)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="380.0">121 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="380.0">119 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">18.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="380.0">25.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="420.0">Left / Right Rotations (left_rotate, right_rotate)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="420.0">121 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="420.0">119 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">18.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="420.0">27.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="460.0">Leading / Trailing zeros/ones</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="460.0">222 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="460.0">223 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">20.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="460.0">14.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="500.0">Log2</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="500.0">246 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="500.0">244 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="500.0">21.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="500.0">14.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="540.0">Select</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="540.0">40.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="540.0">39.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="540.0">4.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="540.0">5.53 ms</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@@ -7,13 +7,13 @@
|
||||
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">whitepaper</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="405.0" y="60.0">253 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="615.0" y="60.0">25.2 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="405.0" y="60.0">276 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="615.0" y="60.0">23.0 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">no_cmux</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="405.0" y="100.0">256 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="615.0" y="100.0">25.2 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="405.0" y="100.0">238 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="615.0" y="100.0">24.0 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">overflow</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="405.0" y="140.0">238 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="405.0" y="140.0">225 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="615.0" y="140.0">21.3 ops/s</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
@@ -15,83 +15,83 @@
|
||||
<rect x="0" y="40" width="300" height="520" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="520" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">Negation (-)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">50.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">55.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">57.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">77.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">96.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">52.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">55.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">54.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">76.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">96.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">Add / Sub (+,-)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">50.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">55.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">74.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">91.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">150 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">50.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">55.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">75.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">96.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">145 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">Mul (x)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">89.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">89.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">131 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">195 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">357 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">1.02 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">363 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">1.01 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">Equal / Not Equal (eq, ne)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">33.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">52.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">52.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">72.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">72.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">33.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">50.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">51.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">71.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">72.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="220.0">Comparisons (ge, gt, le, lt)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">32.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">52.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">70.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">89.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">34.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">50.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">70.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">88.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">128 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="260.0">Max / Min (max, min)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">69.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">88.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">70.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">88.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">109 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">128 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">173 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">131 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">168 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="300.0">Bitwise operations (&, |, ^)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">17.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">18.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">19.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">19.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">19.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">17.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">18.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">18.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">18.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">20.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="340.0">Div / Rem (/, %)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">460 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">1.01 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">2.22 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">4.88 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">12.6 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">457 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">1.0 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">2.2 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">4.99 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">12.5 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="380.0">Left / Right Shifts (<<, >>)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">53.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">74.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">97.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">121 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">158 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">54.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">75.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">97.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">122 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">150 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="420.0">Left / Right Rotations (left_rotate, right_rotate)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">54.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">75.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">94.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">121 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">165 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">53.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">75.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">96.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">116 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">164 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="460.0">Leading / Trailing zeros/ones</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="460.0">88.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="460.0">148 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">169 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="460.0">222 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="460.0">275 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="460.0">86.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="460.0">140 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">164 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="460.0">220 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="460.0">264 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="500.0">Log2</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="500.0">110 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="500.0">163 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="500.0">186 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="500.0">246 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="500.0">290 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="500.0">103 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="500.0">159 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="500.0">183 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="500.0">236 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="500.0">279 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="540.0">Select</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="540.0">36.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="540.0">36.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="540.0">38.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="540.0">40.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="540.0">43.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="540.0">35.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="540.0">37.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="540.0">36.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="540.0">39.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="540.0">42.0 ms</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@@ -15,65 +15,65 @@
|
||||
<rect x="0" y="40" width="300" height="400" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="400" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">Add / Sub (+,-)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">53.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">55.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">57.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">78.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">99.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">50.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">54.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">54.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">76.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">95.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">Mul (x)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">71.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">70.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">115 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">155 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">207 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">422 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">156 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">208 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">412 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">Equal / Not Equal (eq, ne)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">34.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">33.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">52.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">52.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">72.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">33.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">33.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">52.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">53.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">71.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">Comparisons (ge, gt, le, lt)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">38.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">34.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">54.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">31.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">34.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">51.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">70.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">90.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">90.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="220.0">Max / Min (max, min)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">54.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">53.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">71.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">91.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">110 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">52.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">52.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">71.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">91.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">108 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="260.0">Bitwise operations (&, |, ^)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">17.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">17.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">18.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">19.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">19.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">19.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">19.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">20.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="300.0">Div (/)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">136 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">172 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">245 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">437 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">792 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">126 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">182 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">234 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">427 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">799 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="340.0">Rem (%)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">235 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">337 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">468 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">690 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">1.27 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">244 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">334 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">462 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">657 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">1.19 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="380.0">Left / Right Shifts (<<, >>)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">17.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">18.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">19.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">19.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">21.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">17.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">18.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">19.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">19.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">19.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="420.0">Left / Right Rotations (left_rotate, right_rotate)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">18.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">18.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">19.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">19.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">20.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">17.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">18.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">18.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">20.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">21.0 ms</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
@@ -15,83 +15,83 @@
|
||||
<rect x="0" y="40" width="300" height="520" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="520" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">Negation (-)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">804 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">372 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">181 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">86.3 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">42.1 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">824 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">388 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">184 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">88.7 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">42.8 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">Add / Sub (+,-)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">733 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">356 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">167 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">82.6 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">40.0 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">752 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">368 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">172 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">82.1 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">39.5 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">Mul (x)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">293 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">71.9 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">18.2 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">4.58 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">1.19 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">283 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">65.7 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">17.7 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">4.68 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">1.17 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">Equal / Not Equal (eq, ne)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">1.6 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">740 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">392 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">200 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">101 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">1.65 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">748 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">391 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">195 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">102 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="220.0">Comparisons (ge, gt, le, lt)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">1.58 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">733 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">354 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">171 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">64.7 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">1.62 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">745 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">355 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">170 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">65.2 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="260.0">Max / Min (max, min)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">493 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">236 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">116 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">58.3 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">25.7 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">488 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">239 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">117 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">57.3 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">25.2 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="300.0">Bitwise operations (&, |, ^)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">2.1 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">981 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">490 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">262 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">130 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">2.14 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">1.06 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">537 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">270 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">136 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="340.0">Div / Rem (/, %)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">45.2 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">12.9 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">3.56 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">0.893 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">0.223 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">42.2 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">12.7 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">3.51 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">0.914 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">0.143 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="380.0">Left / Right Shifts (<<, >>)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">464 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">183 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">76.1 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">32.4 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">14.3 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">469 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">182 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">74.5 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">32.3 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">14.1 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="420.0">Left / Right Rotations (left_rotate, right_rotate)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">391 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">397 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">170 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">74.0 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">32.5 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">72.2 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">32.1 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">14.0 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="460.0">Leading / Trailing zeros/ones</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="460.0">625 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="460.0">247 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">108 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="460.0">44.1 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="460.0">19.0 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="460.0">621 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="460.0">235 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">104 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="460.0">41.8 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="460.0">17.8 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="500.0">Log2</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="500.0">542 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="500.0">220 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="500.0">102 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="500.0">42.0 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="500.0">18.6 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="500.0">536 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="500.0">207 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="500.0">96.4 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="500.0">40.4 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="500.0">17.3 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="540.0">Select</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="540.0">676 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="540.0">350 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="540.0">176 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="540.0">84.2 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="540.0">42.6 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="540.0">699 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="540.0">351 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="540.0">175 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="540.0">87.3 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="540.0">43.4 ops/s</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@@ -15,65 +15,65 @@
|
||||
<rect x="0" y="40" width="300" height="400" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="400" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">Add / Sub (+,-)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">810 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">379 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">178 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">86.0 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">41.7 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">836 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">383 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">184 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">87.9 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">42.5 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">Mul (x)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">658 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">185 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">57.2 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">17.6 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">4.83 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">659 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">182 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">52.8 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">16.5 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">4.79 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">Equal / Not Equal (eq, ne)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">2.69 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">1.57 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">723 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">378 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">192 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">2.73 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">1.68 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">757 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">399 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">198 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">Comparisons (ge, gt, le, lt)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">2.61 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">1.63 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">717 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">348 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">172 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">2.82 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">1.64 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">747 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">356 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">173 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="220.0">Max / Min (max, min)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">1.15 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">621 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">302 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">148 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">73.6 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">1.18 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">645 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">305 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">150 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">73.2 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="260.0">Bitwise operations (&, |, ^)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">2.11 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">1.04 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">516 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">260 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">128 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">2.31 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">1.12 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">555 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">276 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">139 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="300.0">Div (/)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">203 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">73.3 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">24.8 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">7.38 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">2.16 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">196 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">69.6 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">23.7 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">7.63 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">2.13 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="340.0">Rem (%)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">130 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">49.1 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">17.1 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">5.65 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">1.75 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">114 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">44.5 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">16.6 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">5.78 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">1.66 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="380.0">Left / Right Shifts (<<, >>)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">2.01 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">1.02 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">510 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">247 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">124 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">2.13 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">1.07 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">546 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">270 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">138 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="420.0">Left / Right Rotations (left_rotate, right_rotate)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">2.01 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">992 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">517 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">254 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">124 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">2.14 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">1.07 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">541 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">270 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">137 ops/s</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
@@ -9,25 +9,25 @@
|
||||
<rect x="0" y="40" width="300" height="160" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="160" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">PBS</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="60.0">9.57 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="60.0">12.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="60.0">112 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="60.0">1.58 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="60.0">9.54 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="60.0">12.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="60.0">111 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="60.0">1.39 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">MB-PBS</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="100.0">4.42 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="100.0">4.71 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="100.0">30.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="100.0">257 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="100.0">4.02 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="100.0">4.55 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="100.0">30.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="100.0">244 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">KS - PBS</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="140.0">11.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="140.0">15.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="140.0">126 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="140.0">1.58 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="140.0">10.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="140.0">15.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="140.0">125 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="140.0">1.51 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">KS - MB-PBS</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="180.0">6.67 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="180.0">8.49 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="180.0">46.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="180.0">388 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="180.0">5.56 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="180.0">7.29 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="180.0">61.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="180.0">418 ms</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
@@ -9,25 +9,25 @@
|
||||
<rect x="0" y="40" width="300" height="160" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="160" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">PBS</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="60.0">8.93 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="60.0">8.94 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="60.0">11.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="60.0">102 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="60.0">654 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="60.0">104 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="60.0">670 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">MB-PBS</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="100.0">4.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="100.0">4.58 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="100.0">28.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="100.0">214 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="100.0">4.87 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="100.0">4.53 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="100.0">30.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="100.0">185 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">KS - PBS</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="140.0">10.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="140.0">14.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="140.0">119 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="140.0">865 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="140.0">10.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="140.0">15.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="140.0">120 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="140.0">871 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">KS - MB-PBS</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="180.0">6.96 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="180.0">7.59 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="180.0">47.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="180.0">247 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="180.0">6.83 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="180.0">7.13 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="180.0">44.7 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="180.0">228 ms</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
@@ -6,11 +6,11 @@
|
||||
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">1xFheUint64 (64 bits)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">1.53 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">1.66 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">4xFheUint64 (256 bits) </text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">1.55 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">1.66 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">32xFheUint64 (2048 bits)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">1.76 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">1.8 s</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
@@ -8,17 +8,17 @@
|
||||
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">1xFheUint64 (64 bits)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">209 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">43.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">67.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">276 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">44.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">66.0 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">4xFheUint64 (256 bits) </text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">211 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">277 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">44.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">72.9 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">70.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">32xFheUint64 (2048 bits)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">219 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">293 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">49.1 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">185 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">184 ms</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
@@ -8,17 +8,17 @@
|
||||
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">1xFheUint64 (64 bits)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">8.3 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">265 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">129 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">7.9 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">274 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">131 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">4xFheUint64 (256 bits) </text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">8.36 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">259 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">50.8 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">7.9 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">277 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">51.3 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">32xFheUint64 (2048 bits)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">8.3 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">236 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">8.38 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">7.73 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">242 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">8.62 ops/s</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
@@ -6,11 +6,11 @@
|
||||
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">1xFheUint64 (64 bits)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">1.71 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">1.94 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">4xFheUint64 (256 bits) </text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">1.72 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">1.96 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">32xFheUint64 (2048 bits)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">1.93 s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">2.13 s</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
@@ -8,17 +8,17 @@
|
||||
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">1xFheUint64 (64 bits)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">214 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">31.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">52.5 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">292 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">31.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">51.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">4xFheUint64 (256 bits) </text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">217 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">31.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">57.3 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">294 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">31.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">56.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">32xFheUint64 (2048 bits)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">225 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">33.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">170 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">317 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">33.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">167 ms</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
@@ -8,17 +8,17 @@
|
||||
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
|
||||
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">1xFheUint64 (64 bits)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">7.78 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">877 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">200 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">7.3 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">988 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">201 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">4xFheUint64 (256 bits) </text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">7.79 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">931 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">58.9 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">7.23 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">987 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">59.5 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">32xFheUint64 (2048 bits)</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">7.77 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">993 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">8.59 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">7.1 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">1.11 k.ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">8.85 ops/s</text>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
|
||||
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
@@ -97,76 +97,6 @@ pub fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
## Example: Re-randomization of a `ProvenCompactCiphertextList`
|
||||
|
||||
Untrusted user inputs received in a `ProvenCompactCiphertextList` should also be re-randomized.
|
||||
Here is how to do it:
|
||||
|
||||
```rust
|
||||
use tfhe::prelude::*;
|
||||
use tfhe::shortint::parameters::v1_6::meta::cpu::V1_6_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_SMALL_ZKV2_TUNIFORM_2M128;
|
||||
use tfhe::zk::{CompactPkeCrs, ZkComputeLoad};
|
||||
use tfhe::{
|
||||
CompactPublicKey, Config, FheBool, FheInt8, FheUint64, ProvenCompactCiphertextList,
|
||||
ReRandomizationContext, generate_keys, set_server_key,
|
||||
};
|
||||
|
||||
pub fn main() {
|
||||
let config = Config::from(V1_6_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_SMALL_ZKV2_TUNIFORM_2M128);
|
||||
let (cks, sks) = generate_keys(config);
|
||||
let cpk = CompactPublicKey::new(&cks);
|
||||
|
||||
let compact_public_encryption_domain_separator = *b"TFHE_Enc";
|
||||
let rerand_domain_separator = *b"TFHE_Rrd";
|
||||
|
||||
let crs = CompactPkeCrs::from_config(config, 2048).unwrap();
|
||||
let metadata = [b'r', b'e', b'r', b'a', b'n', b'd'];
|
||||
|
||||
set_server_key(sks);
|
||||
|
||||
// Generate a list of ciphertexts
|
||||
let clear_a = rand::random::<u64>();
|
||||
let clear_b = rand::random::<i8>();
|
||||
|
||||
let compact_list = ProvenCompactCiphertextList::builder(&cpk)
|
||||
.push(clear_a)
|
||||
.push(clear_b)
|
||||
.push(false)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
// Simulate a 256 bits nonce
|
||||
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rand::random());
|
||||
|
||||
let mut re_rand_context = ReRandomizationContext::new(
|
||||
rerand_domain_separator,
|
||||
[b"expand".as_slice(), nonce.as_slice()],
|
||||
compact_public_encryption_domain_separator,
|
||||
);
|
||||
|
||||
// Add the compact list to the context
|
||||
re_rand_context.add_ciphertext(&compact_list);
|
||||
|
||||
let mut seed_gen = re_rand_context.finalize();
|
||||
|
||||
// Verify, re_randomize and expand
|
||||
let expander = compact_list
|
||||
.verify_re_randomize_and_expand(&crs, &cpk, &metadata, seed_gen.next_seed().unwrap())
|
||||
.unwrap();
|
||||
|
||||
let a: FheUint64 = expander.get(0).unwrap().unwrap();
|
||||
let b: FheInt8 = expander.get(1).unwrap().unwrap();
|
||||
let c: FheBool = expander.get(2).unwrap().unwrap();
|
||||
|
||||
let dec_a: u64 = a.decrypt(&cks);
|
||||
assert_eq!(dec_a, clear_a);
|
||||
let dec_b: i8 = b.decrypt(&cks);
|
||||
assert_eq!(dec_b, clear_b);
|
||||
let dec_c: bool = c.decrypt(&cks);
|
||||
assert!(!dec_c);
|
||||
}
|
||||
```
|
||||
|
||||
## Managing legacy Re-Randomization API
|
||||
|
||||
Because of an API change in version 1.6 you may find yourself needing to manage older keys using the old API, the following example shows how it can be done:
|
||||
|
||||
@@ -92,7 +92,6 @@ pub fn glwe_ciphertext_add_assign<Scalar, LhsCont, RhsCont>(
|
||||
lhs.ciphertext_modulus(),
|
||||
rhs.ciphertext_modulus()
|
||||
);
|
||||
assert!(lhs.ciphertext_modulus().is_power_of_two());
|
||||
|
||||
slice_wrapping_add_assign(lhs.as_mut(), rhs.as_ref());
|
||||
}
|
||||
@@ -197,7 +196,6 @@ pub fn glwe_ciphertext_add<Scalar, OutputCont, LhsCont, RhsCont>(
|
||||
output.ciphertext_modulus(),
|
||||
rhs.ciphertext_modulus()
|
||||
);
|
||||
assert!(lhs.ciphertext_modulus().is_power_of_two());
|
||||
|
||||
slice_wrapping_add(output.as_mut(), lhs.as_ref(), rhs.as_ref());
|
||||
}
|
||||
@@ -642,7 +640,6 @@ where
|
||||
Scalar: UnsignedInteger,
|
||||
InCont: ContainerMut<Element = Scalar>,
|
||||
{
|
||||
assert!(ct.ciphertext_modulus().is_power_of_two());
|
||||
slice_wrapping_opposite_assign(ct.as_mut());
|
||||
}
|
||||
|
||||
@@ -726,8 +723,6 @@ pub fn glwe_ciphertext_cleartext_mul_assign<Scalar, InCont>(
|
||||
Scalar: UnsignedInteger,
|
||||
InCont: ContainerMut<Element = Scalar>,
|
||||
{
|
||||
assert!(lhs.ciphertext_modulus().is_power_of_two());
|
||||
|
||||
slice_wrapping_scalar_mul_assign(lhs.as_mut(), rhs.0);
|
||||
}
|
||||
|
||||
@@ -913,7 +908,6 @@ pub fn glwe_ciphertext_sub_assign<Scalar, LhsCont, RhsCont>(
|
||||
lhs.ciphertext_modulus(),
|
||||
rhs.ciphertext_modulus()
|
||||
);
|
||||
assert!(lhs.ciphertext_modulus().is_power_of_two());
|
||||
|
||||
slice_wrapping_sub_assign(lhs.as_mut(), rhs.as_ref());
|
||||
}
|
||||
|
||||
@@ -816,111 +816,6 @@ pub fn lwe_ciphertext_sub<Scalar, OutputCont, LhsCont, RhsCont>(
|
||||
lwe_ciphertext_sub_assign(output, rhs);
|
||||
}
|
||||
|
||||
/// Add the right-hand side [`LWE compact ciphertext list`](`LweCompactCiphertextList`) to the
|
||||
/// left-hand side [`LWE compact ciphertext list`](`LweCompactCiphertextList`) updating it in-place.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use tfhe::core_crypto::prelude::*;
|
||||
///
|
||||
/// // DISCLAIMER: these toy example parameters are not guaranteed to be secure or yield correct
|
||||
/// // computations
|
||||
/// // Define parameters for LweCompactCiphertextList creation
|
||||
/// let lwe_dimension = LweDimension(2048);
|
||||
/// let lwe_ciphertext_count = LweCiphertextCount(3);
|
||||
/// let noise_distribution =
|
||||
/// Gaussian::from_dispersion_parameter(StandardDev(0.00000000000000029403601535432533), 0.0);
|
||||
/// let ciphertext_modulus = CiphertextModulus::new_native();
|
||||
///
|
||||
/// // Create the PRNG
|
||||
/// let mut seeder = new_seeder();
|
||||
/// let seeder = seeder.as_mut();
|
||||
/// let mut secret_generator = SecretRandomGenerator::<DefaultRandomGenerator>::new(seeder.seed());
|
||||
/// let mut encryption_generator =
|
||||
/// EncryptionRandomGenerator::<DefaultRandomGenerator>::new(seeder.seed(), seeder);
|
||||
///
|
||||
/// // Create the LweSecretKey
|
||||
/// let lwe_secret_key =
|
||||
/// allocate_and_generate_new_binary_lwe_secret_key(lwe_dimension, &mut secret_generator);
|
||||
///
|
||||
/// let lwe_compact_public_key = allocate_and_generate_new_lwe_compact_public_key(
|
||||
/// &lwe_secret_key,
|
||||
/// noise_distribution,
|
||||
/// ciphertext_modulus,
|
||||
/// &mut encryption_generator,
|
||||
/// );
|
||||
///
|
||||
/// // Create the plaintext
|
||||
/// let msg = 3u64;
|
||||
/// let encoded_msg = msg << 60;
|
||||
/// let input_plaintext_list =
|
||||
/// PlaintextList::new(encoded_msg, PlaintextCount(lwe_ciphertext_count.0));
|
||||
///
|
||||
/// // Create and encrypt a new LweCompactCiphertextList
|
||||
/// let mut lwe_compact_ct_list = LweCompactCiphertextList::new(
|
||||
/// 0u64,
|
||||
/// lwe_dimension.to_lwe_size(),
|
||||
/// lwe_ciphertext_count,
|
||||
/// ciphertext_modulus,
|
||||
/// );
|
||||
/// encrypt_lwe_compact_ciphertext_list_with_compact_public_key(
|
||||
/// &lwe_compact_public_key,
|
||||
/// &mut lwe_compact_ct_list,
|
||||
/// &input_plaintext_list,
|
||||
/// noise_distribution,
|
||||
/// noise_distribution,
|
||||
/// encryption_generator.noise_generator_mut(),
|
||||
/// );
|
||||
///
|
||||
/// let rhs = lwe_compact_ct_list.clone();
|
||||
///
|
||||
/// lwe_compact_ciphertext_list_add_assign(&mut lwe_compact_ct_list, &rhs);
|
||||
///
|
||||
/// // Expand and decrypt
|
||||
/// let lwe_ciphertext_list = lwe_compact_ct_list.expand_into_lwe_ciphertext_list();
|
||||
///
|
||||
/// let mut output_plaintext_list =
|
||||
/// PlaintextList::new(0u64, PlaintextCount(lwe_ciphertext_count.0));
|
||||
///
|
||||
/// decrypt_lwe_ciphertext_list(
|
||||
/// &lwe_secret_key,
|
||||
/// &lwe_ciphertext_list,
|
||||
/// &mut output_plaintext_list,
|
||||
/// );
|
||||
///
|
||||
/// // Round and remove encoding
|
||||
/// // First create a decomposer working on the high 4 bits corresponding to our encoding.
|
||||
/// let decomposer = SignedDecomposer::new(DecompositionBaseLog(4), DecompositionLevelCount(1));
|
||||
///
|
||||
/// // Round and remove encoding in the output plaintext list
|
||||
/// output_plaintext_list
|
||||
/// .iter_mut()
|
||||
/// .for_each(|x| *x.0 = decomposer.closest_representable(*x.0) >> 60);
|
||||
///
|
||||
/// // Check we recovered the expected result
|
||||
/// assert!(output_plaintext_list.iter().all(|x| *x.0 == msg + msg));
|
||||
/// ```
|
||||
pub fn lwe_compact_ciphertext_list_add_assign<Scalar, LhsCont, RhsCont>(
|
||||
lhs: &mut LweCompactCiphertextList<LhsCont>,
|
||||
rhs: &LweCompactCiphertextList<RhsCont>,
|
||||
) where
|
||||
Scalar: UnsignedInteger,
|
||||
LhsCont: ContainerMut<Element = Scalar>,
|
||||
RhsCont: Container<Element = Scalar>,
|
||||
{
|
||||
assert_eq!(
|
||||
lhs.ciphertext_modulus(),
|
||||
rhs.ciphertext_modulus(),
|
||||
"Mismatched moduli between lhs ({:?}) and rhs ({:?}) LweCompactCiphertextList",
|
||||
lhs.ciphertext_modulus(),
|
||||
rhs.ciphertext_modulus()
|
||||
);
|
||||
assert!(lhs.ciphertext_modulus().is_power_of_two());
|
||||
|
||||
slice_wrapping_add_assign(lhs.as_mut(), rhs.as_ref());
|
||||
}
|
||||
|
||||
// ============== Noise measurement trait implementations ============== //
|
||||
use crate::core_crypto::commons::noise_formulas::noise_simulation::traits::{
|
||||
LweUncorrelatedAdd, LweUncorrelatedSub, ScalarMul, ScalarMulAssign,
|
||||
|
||||
@@ -13,7 +13,7 @@ pub(in crate::high_level_api) mod traits;
|
||||
use crate::array::traits::TensorSlice;
|
||||
use crate::high_level_api::array::traits::HasClear;
|
||||
use crate::high_level_api::global_state;
|
||||
use crate::high_level_api::integers::{FheIntId, FheIntegerType, FheUintId};
|
||||
use crate::high_level_api::integers::{FheIntId, FheUintId};
|
||||
use crate::high_level_api::keys::InternalServerKey;
|
||||
use crate::high_level_api::re_randomization::ReRandomizationMetadata;
|
||||
use crate::{FheBool, FheId, FheInt, FheUint, Tag};
|
||||
@@ -24,8 +24,6 @@ pub use traits::{IOwnedArray, Slicing, SlicingMut};
|
||||
use crate::array::stride::DynDimensions;
|
||||
use crate::core_crypto::prelude::{Numeric, OverflowingAdd, SignedNumeric, UnsignedNumeric};
|
||||
use crate::integer::block_decomposition::DecomposableInto;
|
||||
#[cfg(feature = "gpu")]
|
||||
use crate::integer::gpu::ciphertext::CudaIntegerRadixCiphertext;
|
||||
use crate::integer::RadixCiphertext;
|
||||
use crate::prelude::{CastFrom, CastInto};
|
||||
pub use cpu::{
|
||||
@@ -452,55 +450,6 @@ pub fn fhe_uint_array_contains_sub_slice<Id: FheUintId>(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn fhe_array_contains<T>(data: &[T], value: &T) -> FheBool
|
||||
where
|
||||
T: FheIntegerType,
|
||||
{
|
||||
global_state::with_internal_keys(|sks| match sks {
|
||||
InternalServerKey::Cpu(cpu_key) => {
|
||||
let tmp_data = data
|
||||
.iter()
|
||||
.map(|element| element.on_cpu().into_owned())
|
||||
.collect::<Vec<_>>();
|
||||
let tmp_value = value.on_cpu();
|
||||
|
||||
let result = cpu_key
|
||||
.pbs_key()
|
||||
.contains_parallelized(&tmp_data, &*tmp_value);
|
||||
FheBool::new(
|
||||
result,
|
||||
cpu_key.tag.clone(),
|
||||
ReRandomizationMetadata::default(),
|
||||
)
|
||||
}
|
||||
#[cfg(feature = "gpu")]
|
||||
InternalServerKey::Cuda(gpu_key) => {
|
||||
use crate::high_level_api::details::MaybeCloned;
|
||||
|
||||
let streams = &gpu_key.streams;
|
||||
let tmp_data = data
|
||||
.iter()
|
||||
.map(|element| match element.on_gpu(streams) {
|
||||
MaybeCloned::Borrowed(ct) => ct.duplicate(streams),
|
||||
MaybeCloned::Cloned(ct) => ct,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let tmp_value = value.on_gpu(streams);
|
||||
|
||||
let result = gpu_key.pbs_key().contains(&tmp_data, &*tmp_value, streams);
|
||||
FheBool::new(
|
||||
result,
|
||||
gpu_key.tag.clone(),
|
||||
ReRandomizationMetadata::default(),
|
||||
)
|
||||
}
|
||||
#[cfg(feature = "hpu")]
|
||||
InternalServerKey::Hpu(_) => {
|
||||
panic!("HPU does not support contains() on FheIntegerType yet")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Small helper to reduce code
|
||||
///
|
||||
/// * num_bits: num bits of the FheType
|
||||
|
||||
@@ -2,8 +2,6 @@ mod booleans;
|
||||
mod signed;
|
||||
mod unsigned;
|
||||
|
||||
use crate::high_level_api::array::fhe_array_contains;
|
||||
use crate::high_level_api::integers::FheIntegerType;
|
||||
use crate::{generate_keys, set_server_key, ClientKey, ConfigBuilder, FheId};
|
||||
use rand::distributions::{Distribution, Standard};
|
||||
use rand::random;
|
||||
@@ -12,7 +10,7 @@ use std::fmt::Debug;
|
||||
use crate::array::traits::IOwnedArray;
|
||||
use crate::array::ClearArray;
|
||||
use crate::high_level_api::array::{FheBackendArray, FheBackendArraySlice};
|
||||
use crate::prelude::{FheDecrypt, FheEncrypt, FheTryEncrypt};
|
||||
use crate::prelude::{FheDecrypt, FheTryEncrypt};
|
||||
use std::ops::{BitAnd, BitOr, BitXor};
|
||||
|
||||
fn draw_random_values<T>(num_values: usize) -> Vec<T>
|
||||
@@ -276,42 +274,3 @@ where
|
||||
assert_eq!(result, expected_result);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_case_contains<T, Clear>(ck: &ClientKey)
|
||||
where
|
||||
T: FheIntegerType + FheEncrypt<Clear, ClientKey>,
|
||||
Standard: Distribution<Clear>,
|
||||
Clear: Copy + Eq,
|
||||
{
|
||||
let values = draw_random_values::<Clear>(5);
|
||||
|
||||
// Pick one element that is guaranteed to be in the slice
|
||||
let present_value = values[random::<usize>() % values.len()];
|
||||
|
||||
// Generate an absent value that is not in the slice
|
||||
let absent_value = loop {
|
||||
let candidate: Clear = random();
|
||||
if !values.contains(&candidate) {
|
||||
break candidate;
|
||||
}
|
||||
};
|
||||
|
||||
let data: Vec<T> = values.iter().map(|&v| T::encrypt(v, ck)).collect();
|
||||
|
||||
let present = T::encrypt(present_value, ck);
|
||||
let result: bool = fhe_array_contains(&data, &present).decrypt(ck);
|
||||
assert!(result);
|
||||
|
||||
let absent = T::encrypt(absent_value, ck);
|
||||
let result: bool = fhe_array_contains(&data, &absent).decrypt(ck);
|
||||
assert!(!result);
|
||||
|
||||
// Test with a duplicated value in the slice
|
||||
let mut values_with_dup = values.clone();
|
||||
values_with_dup.push(values[0]);
|
||||
let data_with_dup: Vec<T> = values_with_dup.iter().map(|&v| T::encrypt(v, ck)).collect();
|
||||
|
||||
let present_dup = T::encrypt(values[0], ck);
|
||||
let result: bool = fhe_array_contains(&data_with_dup, &present_dup).decrypt(ck);
|
||||
assert!(result);
|
||||
}
|
||||
|
||||
@@ -101,21 +101,6 @@ fn test_cpu_dyn_bitand_scalar_slice() {
|
||||
super::bitand_scalar_slice_test_case::<crate::FheUint32Array, u32>(&ck);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contains() {
|
||||
let ck = super::setup_default_cpu();
|
||||
super::test_case_contains::<crate::FheUint8, u8>(&ck);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "gpu")]
|
||||
fn test_contains_gpu() {
|
||||
for setup_fn in crate::high_level_api::integers::unsigned::tests::gpu::GPU_SETUP_FN {
|
||||
let ck = setup_fn();
|
||||
super::test_case_contains::<crate::FheUint8, u8>(&ck);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_single_dimension() {
|
||||
let config = ConfigBuilder::default().build();
|
||||
|
||||
@@ -462,10 +462,7 @@ mod zk {
|
||||
use crate::conformance::ParameterSetConformant;
|
||||
use crate::high_level_api::global_state::device_of_internal_keys;
|
||||
use crate::high_level_api::keys::InternalServerKey;
|
||||
use crate::high_level_api::re_randomization::ReRandContextAdd;
|
||||
use crate::integer::ciphertext::{
|
||||
IntegerProvenCompactCiphertextListConformanceParams, ReRandomizationSeed,
|
||||
};
|
||||
use crate::integer::ciphertext::IntegerProvenCompactCiphertextListConformanceParams;
|
||||
#[cfg(feature = "gpu")]
|
||||
use crate::integer::gpu::zk::CudaProvenCompactCiphertextList;
|
||||
use serde::Serializer;
|
||||
@@ -623,13 +620,6 @@ mod zk {
|
||||
const NAME: &'static str = "high_level_api::ProvenCompactCiphertextList";
|
||||
}
|
||||
|
||||
impl ReRandContextAdd for ProvenCompactCiphertextList {
|
||||
fn add_to_re_randomization_context(&self, context: &mut crate::ReRandomizationContext) {
|
||||
let on_cpu = self.inner.on_cpu();
|
||||
context.inner.add_proven_ciphertext_list(on_cpu)
|
||||
}
|
||||
}
|
||||
|
||||
impl ProvenCompactCiphertextList {
|
||||
pub fn builder(pk: &CompactPublicKey) -> CompactCiphertextListBuilder {
|
||||
CompactCiphertextListBuilder::new(pk)
|
||||
@@ -665,7 +655,7 @@ mod zk {
|
||||
pk: &CompactPublicKey,
|
||||
metadata: &[u8],
|
||||
) -> crate::Result<CompactCiphertextListExpander> {
|
||||
self.maybe_verify_maybe_re_randomize_and_expand(Some((crs, pk, metadata)), None)
|
||||
self.maybe_verify_and_expand(Some((crs, pk, metadata)))
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
@@ -673,68 +663,27 @@ mod zk {
|
||||
///
|
||||
/// If you are here you were probably looking for it: use at your own risks.
|
||||
pub fn expand_without_verification(&self) -> crate::Result<CompactCiphertextListExpander> {
|
||||
self.maybe_verify_maybe_re_randomize_and_expand(None, None)
|
||||
self.maybe_verify_and_expand(None)
|
||||
}
|
||||
|
||||
pub fn verify_re_randomize_and_expand(
|
||||
&self,
|
||||
crs: &CompactPkeCrs,
|
||||
pk: &CompactPublicKey,
|
||||
metadata: &[u8],
|
||||
seed: ReRandomizationSeed,
|
||||
) -> crate::Result<CompactCiphertextListExpander> {
|
||||
self.maybe_verify_maybe_re_randomize_and_expand(
|
||||
Some((crs, pk, metadata)),
|
||||
Some((pk, seed)),
|
||||
)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
/// This function allows to re_randomize and expand a ciphertext without verifying the
|
||||
/// associated proof.
|
||||
///
|
||||
/// If you are here you were probably looking for it: use at your own risks.
|
||||
pub fn re_randomize_and_expand_without_verification(
|
||||
&self,
|
||||
pk: &CompactPublicKey,
|
||||
seed: ReRandomizationSeed,
|
||||
) -> crate::Result<CompactCiphertextListExpander> {
|
||||
self.maybe_verify_maybe_re_randomize_and_expand(None, Some((pk, seed)))
|
||||
}
|
||||
|
||||
/// Internal helper that does expansion, and optionally verification and re_randomization if
|
||||
/// the required materials are provided
|
||||
fn maybe_verify_maybe_re_randomize_and_expand(
|
||||
/// Internal helper that does expansion, and verification only if crs, public key and
|
||||
/// metadata are provided
|
||||
fn maybe_verify_and_expand(
|
||||
&self,
|
||||
verification_materials: Option<(&CompactPkeCrs, &CompactPublicKey, &[u8])>,
|
||||
re_randomization_materials: Option<(&CompactPublicKey, ReRandomizationSeed)>,
|
||||
) -> crate::Result<CompactCiphertextListExpander> {
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
if let InnerProvenCompactCiphertextList::Cpu(inner) = &self.inner {
|
||||
// For WASM
|
||||
if !inner.is_packed() && !inner.needs_casting() {
|
||||
let expander = match (verification_materials, re_randomization_materials) {
|
||||
(Some((crs, pk, metadata)), Some((_, seed))) => inner
|
||||
.verify_re_randomize_and_expand(
|
||||
crs,
|
||||
&pk.key.key,
|
||||
metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::NoCastingAndNoUnpacking,
|
||||
seed,
|
||||
),
|
||||
(None, Some((pk, seed))) => inner
|
||||
.re_randomize_and_expand_without_verification(
|
||||
IntegerCompactCiphertextListExpansionMode::NoCastingAndNoUnpacking,
|
||||
&pk.key.key,
|
||||
seed,
|
||||
),
|
||||
(Some((crs, pk, metadata)), None) => inner.verify_and_expand(
|
||||
let expander = match verification_materials {
|
||||
Some((crs, pk, metadata)) => inner.verify_and_expand(
|
||||
crs,
|
||||
&pk.key.key,
|
||||
metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::NoCastingAndNoUnpacking,
|
||||
),
|
||||
(None, None) => inner.expand_without_verification(
|
||||
None => inner.expand_without_verification(
|
||||
IntegerCompactCiphertextListExpansionMode::NoCastingAndNoUnpacking,
|
||||
),
|
||||
}?;
|
||||
@@ -756,28 +705,14 @@ mod zk {
|
||||
InnerProvenCompactCiphertextList::Cuda(inner) => &inner.h_proved_lists,
|
||||
};
|
||||
|
||||
let expander = match (verification_materials, re_randomization_materials) {
|
||||
(Some((crs, pk, metadata)), Some((_, seed))) => proven_ct
|
||||
.verify_re_randomize_and_expand(
|
||||
crs,
|
||||
&pk.key.key,
|
||||
metadata,
|
||||
cpu_key.integer_compact_ciphertext_list_expansion_mode(),
|
||||
seed,
|
||||
),
|
||||
(Some((crs, pk, metadata)), None) => proven_ct.verify_and_expand(
|
||||
let expander = match verification_materials {
|
||||
Some((crs, pk, metadata)) => proven_ct.verify_and_expand(
|
||||
crs,
|
||||
&pk.key.key,
|
||||
metadata,
|
||||
cpu_key.integer_compact_ciphertext_list_expansion_mode(),
|
||||
),
|
||||
(None, Some((pk, seed))) => proven_ct
|
||||
.re_randomize_and_expand_without_verification(
|
||||
cpu_key.integer_compact_ciphertext_list_expansion_mode(),
|
||||
&pk.key.key,
|
||||
seed,
|
||||
),
|
||||
(None, None) => proven_ct.expand_without_verification(
|
||||
None => proven_ct.expand_without_verification(
|
||||
cpu_key.integer_compact_ciphertext_list_expansion_mode(),
|
||||
),
|
||||
}?;
|
||||
@@ -799,28 +734,11 @@ mod zk {
|
||||
};
|
||||
|
||||
let ksk = gpu_key.cpk_key_switching_key();
|
||||
let expander = match (verification_materials, re_randomization_materials) {
|
||||
(Some((crs, pk, metadata)), Some((_, seed))) => proven_ct
|
||||
.verify_re_randomize_and_expand(
|
||||
crs,
|
||||
&pk.key.key,
|
||||
metadata,
|
||||
&ksk,
|
||||
seed,
|
||||
streams,
|
||||
),
|
||||
(Some((crs, pk, metadata)), None) => {
|
||||
let expander = match verification_materials {
|
||||
Some((crs, pk, metadata)) => {
|
||||
proven_ct.verify_and_expand(crs, &pk.key.key, metadata, &ksk, streams)
|
||||
}
|
||||
|
||||
(None, Some((pk, seed))) => proven_ct
|
||||
.re_randomize_and_expand_without_verification(
|
||||
&ksk,
|
||||
&pk.key.key,
|
||||
seed,
|
||||
streams,
|
||||
),
|
||||
(None, None) => proven_ct.expand_without_verification(&ksk, streams),
|
||||
None => proven_ct.expand_without_verification(&ksk, streams),
|
||||
}?;
|
||||
|
||||
Ok(CompactCiphertextListExpander {
|
||||
|
||||
@@ -58,9 +58,6 @@ pub(super) mod unsigned;
|
||||
pub trait IntegerId: FheId + 'static {
|
||||
type InnerCpu: crate::integer::IntegerRadixCiphertext;
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
type InnerGpu: crate::integer::gpu::ciphertext::CudaIntegerRadixCiphertext;
|
||||
#[cfg(not(feature = "gpu"))]
|
||||
type InnerGpu;
|
||||
|
||||
type InnerHpu;
|
||||
@@ -92,23 +89,4 @@ pub trait FheIntegerType: Tagged + private::Sealed {
|
||||
tag: Tag,
|
||||
re_randomization_metadata: ReRandomizationMetadata,
|
||||
) -> Self;
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
fn on_gpu(
|
||||
&self,
|
||||
streams: &crate::core_crypto::gpu::CudaStreams,
|
||||
) -> MaybeCloned<'_, <Self::Id as IntegerId>::InnerGpu>;
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
fn into_gpu(
|
||||
self,
|
||||
streams: &crate::core_crypto::gpu::CudaStreams,
|
||||
) -> <Self::Id as IntegerId>::InnerGpu;
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
fn from_gpu(
|
||||
inner: <Self::Id as IntegerId>::InnerGpu,
|
||||
tag: Tag,
|
||||
re_randomization_metadata: ReRandomizationMetadata,
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
@@ -137,31 +137,6 @@ where
|
||||
) -> Self {
|
||||
Self::new(inner, tag, re_randomization_metadata)
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
fn on_gpu(
|
||||
&self,
|
||||
streams: &crate::core_crypto::gpu::CudaStreams,
|
||||
) -> MaybeCloned<'_, <Self::Id as IntegerId>::InnerGpu> {
|
||||
self.ciphertext.on_gpu(streams)
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
fn into_gpu(
|
||||
self,
|
||||
streams: &crate::core_crypto::gpu::CudaStreams,
|
||||
) -> <Self::Id as IntegerId>::InnerGpu {
|
||||
self.ciphertext.into_gpu(streams)
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
fn from_gpu(
|
||||
inner: <Self::Id as IntegerId>::InnerGpu,
|
||||
tag: Tag,
|
||||
re_randomization_metadata: ReRandomizationMetadata,
|
||||
) -> Self {
|
||||
Self::new(inner, tag, re_randomization_metadata)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id> FheInt<Id>
|
||||
@@ -235,30 +210,6 @@ where
|
||||
self.ciphertext.current_device()
|
||||
}
|
||||
|
||||
/// Returns an encrypted `true` if `value` is found in `cts`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use tfhe::prelude::*;
|
||||
/// use tfhe::{generate_keys, set_server_key, ConfigBuilder, FheInt16};
|
||||
///
|
||||
/// let (client_key, server_key) = generate_keys(ConfigBuilder::default());
|
||||
/// set_server_key(server_key);
|
||||
///
|
||||
/// let a = FheInt16::encrypt(1i16, &client_key);
|
||||
/// let b = FheInt16::encrypt(-2i16, &client_key);
|
||||
/// let c = FheInt16::encrypt(3i16, &client_key);
|
||||
/// let value = FheInt16::encrypt(-2i16, &client_key);
|
||||
///
|
||||
/// let result = FheInt16::contains(&[a, b, c], &value);
|
||||
/// let decrypted = result.decrypt(&client_key);
|
||||
/// assert!(decrypted);
|
||||
/// ```
|
||||
pub fn contains(cts: &[Self], value: &Self) -> FheBool {
|
||||
crate::high_level_api::array::fhe_array_contains(cts, value)
|
||||
}
|
||||
|
||||
/// Returns the absolute value
|
||||
///
|
||||
/// # Example
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
use crate::high_level_api::integers::unsigned::fused_ops::impl_fused_mul_divs;
|
||||
use crate::integer::bigint::{I1024, I2048, I256, I512};
|
||||
|
||||
// Standard types (always available)
|
||||
//
|
||||
// (NarrowFhe, WideFhe, NarrowScalar, WideScalar)
|
||||
//
|
||||
// Types without at least double-width FheInt (FheInt2048) are not supported.
|
||||
impl_fused_mul_divs!(
|
||||
(super::FheInt2, super::FheInt4, i8, i8),
|
||||
(super::FheInt4, super::FheInt8, i8, i8),
|
||||
(super::FheInt6, super::FheInt12, i8, i16),
|
||||
(super::FheInt8, super::FheInt16, i8, i16),
|
||||
(super::FheInt10, super::FheInt32, i16, i32),
|
||||
(super::FheInt12, super::FheInt32, i16, i32),
|
||||
(super::FheInt14, super::FheInt32, i16, i32),
|
||||
(super::FheInt16, super::FheInt32, i16, i32),
|
||||
(super::FheInt32, super::FheInt64, i32, i64),
|
||||
(super::FheInt64, super::FheInt128, i64, i128),
|
||||
(super::FheInt128, super::FheInt256, i128, I256),
|
||||
(super::FheInt160, super::FheInt512, I256, I512),
|
||||
(super::FheInt256, super::FheInt512, I256, I512),
|
||||
(super::FheInt512, super::FheInt1024, I512, I1024),
|
||||
(super::FheInt1024, super::FheInt2048, I1024, I2048),
|
||||
);
|
||||
|
||||
#[cfg(feature = "extended-types")]
|
||||
impl_fused_mul_divs!(
|
||||
(super::FheInt24, super::FheInt48, i32, i64),
|
||||
(super::FheInt40, super::FheInt80, i64, i128),
|
||||
(super::FheInt48, super::FheInt96, i64, i128),
|
||||
(super::FheInt56, super::FheInt112, i64, i128),
|
||||
(super::FheInt72, super::FheInt144, i128, I256),
|
||||
(super::FheInt80, super::FheInt160, i128, I256),
|
||||
(super::FheInt88, super::FheInt176, i128, I256),
|
||||
(super::FheInt96, super::FheInt192, i128, I256),
|
||||
(super::FheInt104, super::FheInt208, i128, I256),
|
||||
(super::FheInt112, super::FheInt224, i128, I256),
|
||||
(super::FheInt120, super::FheInt240, i128, I256),
|
||||
(super::FheInt136, super::FheInt512, I256, I512),
|
||||
(super::FheInt144, super::FheInt512, I256, I512),
|
||||
(super::FheInt152, super::FheInt512, I256, I512),
|
||||
(super::FheInt168, super::FheInt512, I256, I512),
|
||||
(super::FheInt176, super::FheInt512, I256, I512),
|
||||
(super::FheInt184, super::FheInt512, I256, I512),
|
||||
(super::FheInt192, super::FheInt512, I256, I512),
|
||||
(super::FheInt200, super::FheInt512, I256, I512),
|
||||
(super::FheInt208, super::FheInt512, I256, I512),
|
||||
(super::FheInt216, super::FheInt512, I256, I512),
|
||||
(super::FheInt224, super::FheInt512, I256, I512),
|
||||
(super::FheInt232, super::FheInt512, I256, I512),
|
||||
(super::FheInt240, super::FheInt512, I256, I512),
|
||||
(super::FheInt248, super::FheInt512, I256, I512),
|
||||
);
|
||||
@@ -3,7 +3,6 @@ mod compressed;
|
||||
mod squashed_noise;
|
||||
|
||||
mod encrypt;
|
||||
mod fused_ops;
|
||||
mod inner;
|
||||
mod ops;
|
||||
mod overflowing_ops;
|
||||
|
||||
@@ -253,9 +253,3 @@ fn test_safe_deserialize_conformant_compressed_fhe_int32() {
|
||||
let decrypted: i32 = deserialized_a.decompress().decrypt(&client_key);
|
||||
assert_eq!(decrypted, clear_a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_int16_fused_mul_div() {
|
||||
let client_key = setup_default_cpu();
|
||||
super::test_case_int16_fused_mul_div(&client_key);
|
||||
}
|
||||
|
||||
@@ -373,11 +373,3 @@ fn test_gpu_get_div_size_on_gpu() {
|
||||
check_valid_cuda_malloc_assert_oom(scalar_div_rem_tmp_buffer_size, GpuIndex::new(0));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_int16_fused_mul_div_gpu() {
|
||||
for setup_fn in crate::high_level_api::integers::unsigned::tests::gpu::GPU_SETUP_FN {
|
||||
let client_key = setup_fn();
|
||||
super::test_case_int16_fused_mul_div(&client_key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,71 +519,3 @@ fn test_case_min_max(cks: &ClientKey) {
|
||||
assert_eq!(decrypted_min, a_val.min(b_val));
|
||||
assert_eq!(decrypted_max, a_val.max(b_val));
|
||||
}
|
||||
|
||||
fn test_case_int16_fused_mul_div(cks: &ClientKey) {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
// Widening prevents incorrect result with signed values:
|
||||
// (-200) * 200 = -40_000 which overflows i16 (min -32_768),
|
||||
// but with widening: -40_000 / 100 = -400, correct.
|
||||
{
|
||||
let input = -200i16;
|
||||
let mul = 200i16;
|
||||
let div = 100i16;
|
||||
let expected = -400i16;
|
||||
|
||||
let a = FheInt16::try_encrypt(input, cks).unwrap();
|
||||
let b = FheInt16::try_encrypt(mul, cks).unwrap();
|
||||
|
||||
let result = (&a).fused_mul_scalar_div(&b, div);
|
||||
let decrypted: i16 = result.decrypt(cks);
|
||||
assert_eq!(decrypted, expected);
|
||||
|
||||
let result = (&a).fused_scalar_mul_scalar_div(mul, div);
|
||||
let decrypted: i16 = result.decrypt(cks);
|
||||
assert_eq!(decrypted, expected);
|
||||
}
|
||||
|
||||
for _ in 0..5 {
|
||||
let clear_a: i16 = rng.gen();
|
||||
let clear_b: i16 = rng.gen();
|
||||
let clear_c: i16 = loop {
|
||||
let v: i16 = rng.gen();
|
||||
if v != 0 {
|
||||
break v;
|
||||
}
|
||||
};
|
||||
|
||||
let a = FheInt16::try_encrypt(clear_a, cks).unwrap();
|
||||
let b = FheInt16::try_encrypt(clear_b, cks).unwrap();
|
||||
|
||||
let expected = (i32::from(clear_a) * i32::from(clear_b) / i32::from(clear_c)) as i16;
|
||||
|
||||
// encrypted * encrypted / scalar
|
||||
{
|
||||
let result = (&a).fused_mul_scalar_div(&b, clear_c);
|
||||
let decrypted: i16 = result.decrypt(cks);
|
||||
assert_eq!(decrypted, expected);
|
||||
}
|
||||
|
||||
// encrypted * scalar / scalar
|
||||
{
|
||||
let result = (&a).fused_scalar_mul_scalar_div(clear_b, clear_c);
|
||||
let decrypted: i16 = result.decrypt(cks);
|
||||
assert_eq!(decrypted, expected);
|
||||
}
|
||||
|
||||
// Owned variants
|
||||
{
|
||||
let result = a.fused_mul_scalar_div(b, clear_c);
|
||||
let decrypted: i16 = result.decrypt(cks);
|
||||
assert_eq!(decrypted, expected);
|
||||
|
||||
// Need to encrypt again since "a" was consumed above
|
||||
let a = FheInt16::try_encrypt(clear_a, cks).unwrap();
|
||||
let result = a.fused_scalar_mul_scalar_div(clear_b, clear_c);
|
||||
let decrypted: i16 = result.decrypt(cks);
|
||||
assert_eq!(decrypted, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,31 +174,6 @@ where
|
||||
) -> Self {
|
||||
Self::new(inner, tag, re_randomization_metadata)
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
fn on_gpu(
|
||||
&self,
|
||||
streams: &crate::core_crypto::gpu::CudaStreams,
|
||||
) -> MaybeCloned<'_, <Self::Id as IntegerId>::InnerGpu> {
|
||||
self.ciphertext.on_gpu(streams)
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
fn into_gpu(
|
||||
self,
|
||||
streams: &crate::core_crypto::gpu::CudaStreams,
|
||||
) -> <Self::Id as IntegerId>::InnerGpu {
|
||||
self.ciphertext.into_gpu(streams)
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
fn from_gpu(
|
||||
inner: <Self::Id as IntegerId>::InnerGpu,
|
||||
tag: Tag,
|
||||
re_randomization_metadata: ReRandomizationMetadata,
|
||||
) -> Self {
|
||||
Self::new(inner, tag, re_randomization_metadata)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id> Tagged for FheUint<Id>
|
||||
@@ -562,30 +537,6 @@ where
|
||||
collection.as_ref().iter().copied().sum()
|
||||
}
|
||||
|
||||
/// Returns an encrypted `true` if `value` is found in `cts`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use tfhe::prelude::*;
|
||||
/// use tfhe::{generate_keys, set_server_key, ConfigBuilder, FheUint16};
|
||||
///
|
||||
/// let (client_key, server_key) = generate_keys(ConfigBuilder::default());
|
||||
/// set_server_key(server_key);
|
||||
///
|
||||
/// let a = FheUint16::encrypt(1u16, &client_key);
|
||||
/// let b = FheUint16::encrypt(2u16, &client_key);
|
||||
/// let c = FheUint16::encrypt(3u16, &client_key);
|
||||
/// let value = FheUint16::encrypt(2u16, &client_key);
|
||||
///
|
||||
/// let result = FheUint16::contains(&[a, b, c], &value);
|
||||
/// let decrypted = result.decrypt(&client_key);
|
||||
/// assert!(decrypted);
|
||||
/// ```
|
||||
pub fn contains(cts: &[Self], value: &Self) -> FheBool {
|
||||
crate::high_level_api::array::fhe_array_contains(cts, value)
|
||||
}
|
||||
|
||||
/// Returns the number of leading zeros in the binary representation of self.
|
||||
///
|
||||
/// # Example
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
use crate::integer::bigint::{U1024, U2048, U256, U512};
|
||||
|
||||
/// Generates `FusedMulScalarDiv` impls for (encrypted * encrypted) / scalar.
|
||||
///
|
||||
/// Input tuple is of the form (NarrowFhe, WideFhe, NarrowScalar, WideScalar)`
|
||||
/// Inputs are `NarrowFhe` and `NarrowScalar`, and get widened to `WideFhe` and `WideScalar`, mul
|
||||
/// and div are computed on the widened values and result is truncated back down to `NarrowFhe`
|
||||
macro_rules! impl_fused_mul_scalar_div {
|
||||
($(
|
||||
($fhe_narrow:ty, $fhe_wide:ty, $scalar_narrow:ty, $scalar_wide:ty)
|
||||
),* $(,)?) => {
|
||||
$(
|
||||
// (&enc * &enc) / scalar (ref, ref, main impl)
|
||||
impl crate::high_level_api::traits::FusedMulScalarDiv<&$fhe_narrow, $scalar_narrow> for &$fhe_narrow {
|
||||
type Output = $fhe_narrow;
|
||||
|
||||
fn fused_mul_scalar_div(
|
||||
self,
|
||||
mul: &$fhe_narrow,
|
||||
div_scalar: $scalar_narrow,
|
||||
) -> Self::Output {
|
||||
use crate::core_crypto::prelude::CastFrom;
|
||||
let wide_self = <$fhe_wide>::cast_from(self.clone());
|
||||
let wide_mul = <$fhe_wide>::cast_from(mul.clone());
|
||||
let wide_product = &wide_self * &wide_mul;
|
||||
let wide_result = wide_product / <$scalar_wide>::cast_from(div_scalar);
|
||||
<$fhe_narrow>::cast_from(wide_result)
|
||||
}
|
||||
}
|
||||
|
||||
// (enc * enc) / scalar (owned, owned)
|
||||
impl crate::high_level_api::traits::FusedMulScalarDiv<$fhe_narrow, $scalar_narrow> for $fhe_narrow {
|
||||
type Output = $fhe_narrow;
|
||||
|
||||
fn fused_mul_scalar_div(
|
||||
self,
|
||||
mul: $fhe_narrow,
|
||||
div_scalar: $scalar_narrow,
|
||||
) -> Self::Output {
|
||||
use crate::high_level_api::traits::FusedMulScalarDiv;
|
||||
<&Self as FusedMulScalarDiv<&$fhe_narrow, $scalar_narrow>>::fused_mul_scalar_div(&self, &mul, div_scalar)
|
||||
}
|
||||
}
|
||||
|
||||
// (&enc * enc) / scalar (ref, owned)
|
||||
impl crate::high_level_api::traits::FusedMulScalarDiv<$fhe_narrow, $scalar_narrow> for &$fhe_narrow {
|
||||
type Output = $fhe_narrow;
|
||||
|
||||
fn fused_mul_scalar_div(
|
||||
self,
|
||||
mul: $fhe_narrow,
|
||||
div_scalar: $scalar_narrow,
|
||||
) -> Self::Output {
|
||||
use crate::high_level_api::traits::FusedMulScalarDiv;
|
||||
<Self as FusedMulScalarDiv<&$fhe_narrow, $scalar_narrow>>::fused_mul_scalar_div(self, &mul, div_scalar)
|
||||
}
|
||||
}
|
||||
|
||||
// (enc * &enc) / scalar (owned, ref)
|
||||
impl crate::high_level_api::traits::FusedMulScalarDiv<&$fhe_narrow, $scalar_narrow> for $fhe_narrow {
|
||||
type Output = $fhe_narrow;
|
||||
|
||||
fn fused_mul_scalar_div(
|
||||
self,
|
||||
mul: &$fhe_narrow,
|
||||
div_scalar: $scalar_narrow,
|
||||
) -> Self::Output {
|
||||
use crate::high_level_api::traits::FusedMulScalarDiv;
|
||||
<&Self as FusedMulScalarDiv<&$fhe_narrow, $scalar_narrow>>::fused_mul_scalar_div(&self, mul, div_scalar)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
pub(crate) use impl_fused_mul_scalar_div;
|
||||
|
||||
/// Generates `FusedScalarMulScalarDiv` impls for (encrypted * scalar) / scalar.
|
||||
///
|
||||
/// Input tuple is of the form (NarrowFhe, WideFhe, NarrowScalar, WideScalar)`
|
||||
/// Inputs are `NarrowFhe` and `NarrowScalar`, and get widened to `WideFhe` and `WideScalar`, mul
|
||||
/// and div are computed on the widened values and result is truncated back down to `NarrowFhe`
|
||||
macro_rules! impl_fused_scalar_mul_scalar_div {
|
||||
($(
|
||||
($fhe_narrow:ty, $fhe_wide:ty, $scalar_narrow:ty, $scalar_wide:ty)
|
||||
),* $(,)?) => {
|
||||
$(
|
||||
// (&enc * scalar) / scalar (ref, main impl)
|
||||
impl crate::high_level_api::traits::FusedScalarMulScalarDiv<$scalar_narrow> for &$fhe_narrow {
|
||||
type Output = $fhe_narrow;
|
||||
|
||||
fn fused_scalar_mul_scalar_div(
|
||||
self,
|
||||
mul_scalar: $scalar_narrow,
|
||||
div_scalar: $scalar_narrow,
|
||||
) -> Self::Output {
|
||||
use crate::core_crypto::prelude::CastFrom;
|
||||
let wide_self = <$fhe_wide>::cast_from(self.clone());
|
||||
let wide_product = wide_self * <$scalar_wide>::cast_from(mul_scalar);
|
||||
let wide_result = wide_product / <$scalar_wide>::cast_from(div_scalar);
|
||||
<$fhe_narrow>::cast_from(wide_result)
|
||||
}
|
||||
}
|
||||
|
||||
// (enc * scalar) / scalar (owned)
|
||||
impl crate::high_level_api::traits::FusedScalarMulScalarDiv<$scalar_narrow> for $fhe_narrow {
|
||||
type Output = $fhe_narrow;
|
||||
|
||||
fn fused_scalar_mul_scalar_div(
|
||||
self,
|
||||
mul_scalar: $scalar_narrow,
|
||||
div_scalar: $scalar_narrow,
|
||||
) -> Self::Output {
|
||||
use crate::high_level_api::traits::FusedScalarMulScalarDiv;
|
||||
<&Self as FusedScalarMulScalarDiv<$scalar_narrow>>::fused_scalar_mul_scalar_div(&self, mul_scalar, div_scalar)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
pub(crate) use impl_fused_scalar_mul_scalar_div;
|
||||
|
||||
macro_rules! impl_fused_mul_divs {
|
||||
($(
|
||||
($fhe_narrow:ty, $fhe_wide:ty, $scalar_narrow:ty, $scalar_wide:ty)
|
||||
),* $(,)?) => {
|
||||
crate::high_level_api::integers::unsigned::fused_ops::impl_fused_mul_scalar_div!($(
|
||||
($fhe_narrow, $fhe_wide, $scalar_narrow, $scalar_wide),
|
||||
)*);
|
||||
crate::high_level_api::integers::unsigned::fused_ops::impl_fused_scalar_mul_scalar_div!($(
|
||||
($fhe_narrow, $fhe_wide, $scalar_narrow, $scalar_wide),
|
||||
)*);
|
||||
}
|
||||
}
|
||||
pub(crate) use impl_fused_mul_divs;
|
||||
|
||||
// Standard types (always available)
|
||||
//
|
||||
// (NarrowFhe, WideFhe, NarrowScalar, WideScalar)
|
||||
//
|
||||
// Types without at least double-width FheUint (FheUint2048) are not supported.
|
||||
impl_fused_mul_divs!(
|
||||
(super::FheUint2, super::FheUint4, u8, u8),
|
||||
(super::FheUint4, super::FheUint8, u8, u8),
|
||||
(super::FheUint6, super::FheUint12, u8, u16),
|
||||
(super::FheUint8, super::FheUint16, u8, u16),
|
||||
(super::FheUint10, super::FheUint32, u16, u32),
|
||||
(super::FheUint12, super::FheUint32, u16, u32),
|
||||
(super::FheUint14, super::FheUint32, u16, u32),
|
||||
(super::FheUint16, super::FheUint32, u16, u32),
|
||||
(super::FheUint32, super::FheUint64, u32, u64),
|
||||
(super::FheUint64, super::FheUint128, u64, u128),
|
||||
(super::FheUint128, super::FheUint256, u128, U256),
|
||||
(super::FheUint160, super::FheUint512, U256, U512),
|
||||
(super::FheUint256, super::FheUint512, U256, U512),
|
||||
(super::FheUint512, super::FheUint1024, U512, U1024),
|
||||
(super::FheUint1024, super::FheUint2048, U1024, U2048),
|
||||
);
|
||||
|
||||
#[cfg(feature = "extended-types")]
|
||||
impl_fused_mul_divs!(
|
||||
(super::FheUint24, super::FheUint48, u32, u64),
|
||||
(super::FheUint40, super::FheUint80, u64, u128),
|
||||
(super::FheUint48, super::FheUint96, u64, u128),
|
||||
(super::FheUint56, super::FheUint112, u64, u128),
|
||||
(super::FheUint72, super::FheUint144, u128, U256),
|
||||
(super::FheUint80, super::FheUint160, u128, U256),
|
||||
(super::FheUint88, super::FheUint176, u128, U256),
|
||||
(super::FheUint96, super::FheUint192, u128, U256),
|
||||
(super::FheUint104, super::FheUint208, u128, U256),
|
||||
(super::FheUint112, super::FheUint224, u128, U256),
|
||||
(super::FheUint120, super::FheUint240, u128, U256),
|
||||
(super::FheUint136, super::FheUint512, U256, U512),
|
||||
(super::FheUint144, super::FheUint512, U256, U512),
|
||||
(super::FheUint152, super::FheUint512, U256, U512),
|
||||
(super::FheUint168, super::FheUint512, U256, U512),
|
||||
(super::FheUint176, super::FheUint512, U256, U512),
|
||||
(super::FheUint184, super::FheUint512, U256, U512),
|
||||
(super::FheUint192, super::FheUint512, U256, U512),
|
||||
(super::FheUint200, super::FheUint512, U256, U512),
|
||||
(super::FheUint208, super::FheUint512, U256, U512),
|
||||
(super::FheUint216, super::FheUint512, U256, U512),
|
||||
(super::FheUint224, super::FheUint512, U256, U512),
|
||||
(super::FheUint232, super::FheUint512, U256, U512),
|
||||
(super::FheUint240, super::FheUint512, U256, U512),
|
||||
(super::FheUint248, super::FheUint512, U256, U512),
|
||||
);
|
||||
@@ -32,7 +32,6 @@ mod squashed_noise;
|
||||
mod static_;
|
||||
|
||||
mod encrypt;
|
||||
pub(in crate::high_level_api) mod fused_ops;
|
||||
mod inner;
|
||||
mod ops;
|
||||
mod overflowing_ops;
|
||||
|
||||
@@ -703,9 +703,3 @@ fn test_match_value_or() {
|
||||
let client_key = setup_default_cpu();
|
||||
super::test_case_match_value_or(&client_key);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_uint16_fused_mul_div() {
|
||||
let client_key = setup_default_cpu();
|
||||
super::test_case_uint16_fused_mul_div(&client_key);
|
||||
}
|
||||
|
||||
@@ -1004,11 +1004,3 @@ fn test_gpu_get_match_value_or_size_on_gpu() {
|
||||
assert!(memory_size > 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_uint16_fused_mul_div_gpu() {
|
||||
for setup_fn in GPU_SETUP_FN {
|
||||
let client_key = setup_fn();
|
||||
super::test_case_uint16_fused_mul_div(&client_key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use crate::high_level_api::traits::BitSlice;
|
||||
use crate::integer::U256;
|
||||
use crate::prelude::*;
|
||||
use crate::{
|
||||
ClientKey, FheBool, FheUint16, FheUint256, FheUint32, FheUint64, FheUint8, MatchValues,
|
||||
};
|
||||
use crate::{ClientKey, FheBool, FheUint256, FheUint32, FheUint64, FheUint8, MatchValues};
|
||||
use rand::{thread_rng, Rng};
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -912,66 +910,3 @@ fn test_case_match_value_or(cks: &ClientKey) {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_case_uint16_fused_mul_div(cks: &ClientKey) {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
// Widening prevents incorrect result:
|
||||
// 300 * 300 = 90_000 which overflows u16 (max 65_535),
|
||||
// but with widening: 90_000 / 100 = 900, correct.
|
||||
{
|
||||
let input = 300u16;
|
||||
let mul = 300u16;
|
||||
let div = 100u16;
|
||||
let expected = 900u16;
|
||||
|
||||
let a = FheUint16::try_encrypt(input, cks).unwrap();
|
||||
let b = FheUint16::try_encrypt(mul, cks).unwrap();
|
||||
|
||||
let result = (&a).fused_mul_scalar_div(&b, div);
|
||||
let decrypted: u16 = result.decrypt(cks);
|
||||
assert_eq!(decrypted, expected);
|
||||
|
||||
let result = (&a).fused_scalar_mul_scalar_div(mul, div);
|
||||
let decrypted: u16 = result.decrypt(cks);
|
||||
assert_eq!(decrypted, expected);
|
||||
}
|
||||
|
||||
for _ in 0..5 {
|
||||
let clear_a: u16 = rng.gen();
|
||||
let clear_b: u16 = rng.gen();
|
||||
let clear_c: u16 = rng.gen_range(1..=u16::MAX);
|
||||
|
||||
let a = FheUint16::try_encrypt(clear_a, cks).unwrap();
|
||||
let b = FheUint16::try_encrypt(clear_b, cks).unwrap();
|
||||
|
||||
let expected = (u32::from(clear_a) * u32::from(clear_b) / u32::from(clear_c)) as u16;
|
||||
|
||||
// encrypted * encrypted / scalar
|
||||
{
|
||||
let result = (&a).fused_mul_scalar_div(&b, clear_c);
|
||||
let decrypted: u16 = result.decrypt(cks);
|
||||
assert_eq!(decrypted, expected);
|
||||
}
|
||||
|
||||
// encrypted * scalar / scalar
|
||||
{
|
||||
let result = (&a).fused_scalar_mul_scalar_div(clear_b, clear_c);
|
||||
let decrypted: u16 = result.decrypt(cks);
|
||||
assert_eq!(decrypted, expected);
|
||||
}
|
||||
|
||||
// Owned variants
|
||||
{
|
||||
let result = a.fused_mul_scalar_div(b, clear_c);
|
||||
let decrypted: u16 = result.decrypt(cks);
|
||||
assert_eq!(decrypted, expected);
|
||||
|
||||
// Need to encrypt again since "a" was consumed above
|
||||
let a = FheUint16::try_encrypt(clear_a, cks).unwrap();
|
||||
let result = a.fused_scalar_mul_scalar_div(clear_b, clear_c);
|
||||
let decrypted: u16 = result.decrypt(cks);
|
||||
assert_eq!(decrypted, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,9 +107,9 @@ expand_pub_use_fhe_type!(
|
||||
};
|
||||
);
|
||||
pub use array::{
|
||||
fhe_array_contains, ClearArray, CpuFheIntArray, CpuFheIntSlice, CpuFheIntSliceMut,
|
||||
CpuFheUintArray, CpuFheUintSlice, CpuFheUintSliceMut, FheBoolId, FheIntArray, FheIntSlice,
|
||||
FheIntSliceMut, FheUintArray, FheUintSlice, FheUintSliceMut,
|
||||
ClearArray, CpuFheIntArray, CpuFheIntSlice, CpuFheIntSliceMut, CpuFheUintArray,
|
||||
CpuFheUintSlice, CpuFheUintSliceMut, FheBoolId, FheIntArray, FheIntSlice, FheIntSliceMut,
|
||||
FheUintArray, FheUintSlice, FheUintSliceMut,
|
||||
};
|
||||
export_concrete_array_types!(
|
||||
pub use array{
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
//! ```
|
||||
pub use crate::high_level_api::traits::{
|
||||
BitSlice, CiphertextList, DivRem, FheDecrypt, FheEncrypt, FheEq, FheKeyswitch, FheMax, FheMin,
|
||||
FheOrd, FheTrivialEncrypt, FheTryEncrypt, FheTryTrivialEncrypt, FheWait, Flip,
|
||||
FusedMulScalarDiv, FusedScalarMulScalarDiv, IfThenElse, IfThenZero, OverflowingAdd,
|
||||
OverflowingMul, OverflowingNeg, OverflowingSub, ReRandomize, RotateLeft, RotateLeftAssign,
|
||||
RotateRight, RotateRightAssign, ScalarIfThenElse, SquashNoise, Tagged,
|
||||
FheOrd, FheTrivialEncrypt, FheTryEncrypt, FheTryTrivialEncrypt, FheWait, Flip, IfThenElse,
|
||||
IfThenZero, OverflowingAdd, OverflowingMul, OverflowingNeg, OverflowingSub, ReRandomize,
|
||||
RotateLeft, RotateLeftAssign, RotateRight, RotateRightAssign, ScalarIfThenElse, SquashNoise,
|
||||
Tagged,
|
||||
};
|
||||
#[cfg(feature = "hpu")]
|
||||
pub use crate::high_level_api::traits::{FheHpu, HpuHandle};
|
||||
|
||||
@@ -325,121 +325,6 @@ fn execute_re_rand_test(cks: &ClientKey, cpk: &CompactPublicKey) {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "zk-pok")]
|
||||
mod zk {
|
||||
use super::*;
|
||||
use crate::high_level_api::{FheInt64, FheUint32};
|
||||
use crate::zk::{CompactPkeCrs, ZkComputeLoad};
|
||||
use crate::{Config, ProvenCompactCiphertextList};
|
||||
|
||||
#[test]
|
||||
fn test_compact_list_re_rand() {
|
||||
use crate::shortint::parameters::test_params::TEST_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_SMALL_ZKV2_TUNIFORM_2M128;
|
||||
|
||||
let params = TEST_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_SMALL_ZKV2_TUNIFORM_2M128;
|
||||
let (cks, sks, cpk) = setup_re_rand_test(params);
|
||||
set_server_key(sks.decompress());
|
||||
|
||||
let config = Config::from(params);
|
||||
|
||||
let compact_public_encryption_domain_separator = *b"TFHE_Enc";
|
||||
let rerand_domain_separator = *b"TFHE_Rrd";
|
||||
|
||||
// Intentionally low so that we test when multiple lists and proofs are needed
|
||||
let crs = CompactPkeCrs::from_config(config, 32).unwrap();
|
||||
let metadata = [b'r', b'e', b'r', b'a', b'n', b'd'];
|
||||
|
||||
// Case where we want to re-randomize a CompactCiphertextList containing
|
||||
// FheUint64, FheInt8, and FheBool
|
||||
{
|
||||
let clear_a = rand::random::<u64>();
|
||||
let clear_b = rand::random::<i8>();
|
||||
|
||||
let compact_list = ProvenCompactCiphertextList::builder(&cpk)
|
||||
.push(clear_a)
|
||||
.push(clear_b)
|
||||
.push(false)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
// Simulate a 256 bits nonce
|
||||
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rand::random());
|
||||
|
||||
let mut re_rand_context = ReRandomizationContext::new(
|
||||
rerand_domain_separator,
|
||||
[b"expand".as_slice(), nonce.as_slice()],
|
||||
compact_public_encryption_domain_separator,
|
||||
);
|
||||
|
||||
// Add the compact list to the context
|
||||
re_rand_context.add_ciphertext(&compact_list);
|
||||
|
||||
let mut seed_gen = re_rand_context.finalize();
|
||||
|
||||
// Verify, re_randomize and expand
|
||||
let expander = compact_list
|
||||
.verify_re_randomize_and_expand(
|
||||
&crs,
|
||||
&cpk,
|
||||
&metadata,
|
||||
seed_gen.next_seed().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let a: FheUint64 = expander.get(0).unwrap().unwrap();
|
||||
let b: FheInt8 = expander.get(1).unwrap().unwrap();
|
||||
let c: FheBool = expander.get(2).unwrap().unwrap();
|
||||
|
||||
let dec_a: u64 = a.decrypt(&cks);
|
||||
assert_eq!(dec_a, clear_a);
|
||||
let dec_b: i8 = b.decrypt(&cks);
|
||||
assert_eq!(dec_b, clear_b);
|
||||
let dec_c: bool = c.decrypt(&cks);
|
||||
assert!(!dec_c);
|
||||
}
|
||||
|
||||
// Also test expand_and_re_randomize_without_verification
|
||||
{
|
||||
let clear_a = rand::random::<u32>();
|
||||
let clear_b = rand::random::<i64>();
|
||||
|
||||
let compact_list = ProvenCompactCiphertextList::builder(&cpk)
|
||||
.push(clear_a)
|
||||
.push(clear_b)
|
||||
.push(false)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rand::random());
|
||||
|
||||
let mut re_rand_context = ReRandomizationContext::new(
|
||||
rerand_domain_separator,
|
||||
[b"expand".as_slice(), nonce.as_slice()],
|
||||
compact_public_encryption_domain_separator,
|
||||
);
|
||||
|
||||
re_rand_context.add_ciphertext(&compact_list);
|
||||
|
||||
let mut seed_gen = re_rand_context.finalize();
|
||||
|
||||
let expander = compact_list
|
||||
.re_randomize_and_expand_without_verification(&cpk, seed_gen.next_seed().unwrap())
|
||||
.unwrap();
|
||||
|
||||
let a: FheUint32 = expander.get(0).unwrap().unwrap();
|
||||
let b: FheInt64 = expander.get(1).unwrap().unwrap();
|
||||
let c: FheBool = expander.get(2).unwrap().unwrap();
|
||||
|
||||
let dec_a: u32 = a.decrypt(&cks);
|
||||
assert_eq!(dec_a, clear_a);
|
||||
let dec_b: i64 = b.decrypt(&cks);
|
||||
assert_eq!(dec_b, clear_b);
|
||||
let dec_c: bool = c.decrypt(&cks);
|
||||
assert!(!dec_c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_re_rand_test(
|
||||
mut params: MetaParameters,
|
||||
) -> (crate::ClientKey, CompressedServerKey, CompactPublicKey) {
|
||||
|
||||
@@ -139,30 +139,6 @@ pub trait DivRem<Rhs = Self> {
|
||||
fn div_rem(self, amount: Rhs) -> Self::Output;
|
||||
}
|
||||
|
||||
/// Computes `(self * mul) / div_scalar` where `self` and `mul` are encrypted and `div_scaalr` is a
|
||||
/// plaintext divisor.
|
||||
///
|
||||
/// The intermediate multiplication is performed to have the exact result without overflowing.
|
||||
/// The final result is truncated back to the original width, which may wrap if the full precision
|
||||
/// division result does not fit in the original type.
|
||||
pub trait FusedMulScalarDiv<Mul, DivScalar> {
|
||||
type Output;
|
||||
|
||||
fn fused_mul_scalar_div(self, mul: Mul, div_scalar: DivScalar) -> Self::Output;
|
||||
}
|
||||
|
||||
/// Computes `(self * mul_scalar) / div_scalar` where `self` is encrypted and both scalars are
|
||||
/// plaintext.
|
||||
///
|
||||
/// The intermediate multiplication is performed to have the exact result without overflowing.
|
||||
/// The final result is truncated back to the original width, which may wrap if the full precision
|
||||
/// division result does not fit in the original type.
|
||||
pub trait FusedScalarMulScalarDiv<Scalar> {
|
||||
type Output;
|
||||
|
||||
fn fused_scalar_mul_scalar_div(self, mul_scalar: Scalar, div_scalar: Scalar) -> Self::Output;
|
||||
}
|
||||
|
||||
pub trait IfThenElse<Ciphertext> {
|
||||
fn if_then_else(&self, ct_then: &Ciphertext, ct_else: &Ciphertext) -> Ciphertext;
|
||||
fn select(&self, ct_when_true: &Ciphertext, ct_when_false: &Ciphertext) -> Ciphertext {
|
||||
|
||||
@@ -421,28 +421,10 @@ impl<const N: usize> From<(u64, u64, u64, u64)> for StaticSignedBigInt<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N_IN: usize, const N_OUT: usize> CastFrom<StaticSignedBigInt<N_IN>>
|
||||
for StaticSignedBigInt<N_OUT>
|
||||
{
|
||||
fn cast_from(input: StaticSignedBigInt<N_IN>) -> Self {
|
||||
// Get rid of special case, will be removed at compile time, no runtime impact
|
||||
if N_IN == 0 {
|
||||
return Self::ZERO;
|
||||
}
|
||||
|
||||
// Safe to unwrap, N_IN > 0
|
||||
let sign = input.0.last().unwrap() >> 63;
|
||||
// If sign == 1, i.e. top bit was set, then the BigInt was negative, taking the wrapping_neg
|
||||
// yields u64::MAX == -1 == 0xffffffffffffffff, if sign == 0, wrapping_neg does nothing and
|
||||
// we get 0, this is a branchless way of getting the fill u64 for sign extension
|
||||
let fill = sign.wrapping_neg();
|
||||
|
||||
let smallest = N_IN.min(N_OUT);
|
||||
// init data with fill will naturally sign extend as required, since the low bits will be
|
||||
// copied and the high bits will be 1s or 0s depending on sign
|
||||
let mut data = [fill; N_OUT];
|
||||
data[..smallest].copy_from_slice(&input.0[..smallest]);
|
||||
Self(data)
|
||||
impl<const N: usize> CastFrom<Self> for StaticSignedBigInt<N> {
|
||||
#[inline(always)]
|
||||
fn cast_from(input: Self) -> Self {
|
||||
input
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,36 +477,6 @@ impl<const N: usize> CastFrom<u128> for StaticSignedBigInt<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> CastFrom<i8> for StaticSignedBigInt<N> {
|
||||
fn cast_from(input: i8) -> Self {
|
||||
Self::from(input as i128)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> CastFrom<i16> for StaticSignedBigInt<N> {
|
||||
fn cast_from(input: i16) -> Self {
|
||||
Self::from(input as i128)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> CastFrom<i32> for StaticSignedBigInt<N> {
|
||||
fn cast_from(input: i32) -> Self {
|
||||
Self::from(input as i128)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> CastFrom<i64> for StaticSignedBigInt<N> {
|
||||
fn cast_from(input: i64) -> Self {
|
||||
Self::from(input as i128)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> CastFrom<i128> for StaticSignedBigInt<N> {
|
||||
fn cast_from(input: i128) -> Self {
|
||||
Self::from(input)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> CastFrom<StaticSignedBigInt<N>> for u8 {
|
||||
fn cast_from(input: StaticSignedBigInt<N>) -> Self {
|
||||
input.0[0] as Self
|
||||
@@ -588,31 +540,12 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_i128_cast() {
|
||||
{
|
||||
let a = 1_i128 << 64;
|
||||
let a = 1_i128 << 64;
|
||||
|
||||
let b: StaticSignedBigInt<4> = a.into();
|
||||
let b: StaticSignedBigInt<4> = a.into();
|
||||
|
||||
let c = i128::cast_from(b);
|
||||
let c = i128::cast_from(b);
|
||||
|
||||
assert_eq!(a, c);
|
||||
}
|
||||
|
||||
{
|
||||
let a = -1_i128 << 64;
|
||||
|
||||
let b: StaticSignedBigInt<4> = a.into();
|
||||
|
||||
let c = i128::cast_from(b);
|
||||
|
||||
assert_eq!(a, c);
|
||||
assert_eq!(b, StaticSignedBigInt::<4>::ONE.wrapping_neg() << 64u32);
|
||||
|
||||
let d = StaticSignedBigInt::<5>::cast_from(b);
|
||||
let e = i128::cast_from(d);
|
||||
|
||||
assert_eq!(a, e);
|
||||
assert_eq!(d, StaticSignedBigInt::<5>::ONE.wrapping_neg() << 64u32);
|
||||
}
|
||||
assert_eq!(a, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#[cfg(feature = "zk-pok")]
|
||||
use super::ReRandomizationSeed;
|
||||
use super::{DataKind, Expandable};
|
||||
use crate::conformance::{ListSizeConstraint, ParameterSetConformant};
|
||||
use crate::core_crypto::prelude::{LweCiphertextListConformanceParams, Numeric};
|
||||
@@ -1111,32 +1109,6 @@ impl ProvenCompactCiphertextList {
|
||||
self.expand_without_verification(expansion_mode)
|
||||
}
|
||||
|
||||
pub fn verify_re_randomize_and_expand(
|
||||
&self,
|
||||
crs: &CompactPkeCrs,
|
||||
public_key: &CompactPublicKey,
|
||||
metadata: &[u8],
|
||||
expansion_mode: IntegerCompactCiphertextListExpansionMode<'_>,
|
||||
seed: ReRandomizationSeed,
|
||||
) -> crate::Result<CompactCiphertextListExpander> {
|
||||
if self.verify(crs, public_key, metadata) == ZkVerificationOutcome::Invalid {
|
||||
return Err(crate::ErrorKind::InvalidZkProof.into());
|
||||
}
|
||||
|
||||
self.re_randomize_and_expand_without_verification(expansion_mode, public_key, seed)
|
||||
}
|
||||
|
||||
pub fn re_randomize(
|
||||
&mut self,
|
||||
public_key: &CompactPublicKey,
|
||||
seed: ReRandomizationSeed,
|
||||
) -> crate::Result<()> {
|
||||
public_key.key.re_randomize_compact_ciphertext_lists(
|
||||
self.ct_list.proved_lists.iter_mut().map(|(list, _)| list),
|
||||
seed,
|
||||
)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
/// This function allows to expand a ciphertext without verifying the associated proof.
|
||||
///
|
||||
@@ -1170,23 +1142,6 @@ is not"
|
||||
))
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
/// This function allows to re_randomize and expand a ciphertext without verifying the
|
||||
/// associated proof.
|
||||
///
|
||||
/// If you are here you were probably looking for it: use at your own risks.
|
||||
pub fn re_randomize_and_expand_without_verification(
|
||||
&self,
|
||||
expansion_mode: IntegerCompactCiphertextListExpansionMode<'_>,
|
||||
public_key: &CompactPublicKey,
|
||||
seed: ReRandomizationSeed,
|
||||
) -> crate::Result<CompactCiphertextListExpander> {
|
||||
let mut rerandomized = self.clone();
|
||||
rerandomized.re_randomize(public_key, seed)?;
|
||||
|
||||
rerandomized.expand_without_verification(expansion_mode)
|
||||
}
|
||||
|
||||
pub fn is_packed(&self) -> bool {
|
||||
if self.is_empty() {
|
||||
return false;
|
||||
|
||||
@@ -8,9 +8,6 @@ pub use crate::shortint::ciphertext::{ReRandomizationSeed, ReRandomizationSeedHa
|
||||
use crate::shortint::Ciphertext;
|
||||
use crate::Result;
|
||||
|
||||
#[cfg(feature = "zk-pok")]
|
||||
use super::ProvenCompactCiphertextList;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum ReRandomizationKey<'key> {
|
||||
LegacyDedicatedCPK {
|
||||
@@ -109,26 +106,6 @@ impl ReRandomizationContext {
|
||||
self.ct_count += 1;
|
||||
}
|
||||
|
||||
#[cfg(feature = "zk-pok")]
|
||||
pub fn add_proven_ciphertext_list(&mut self, list: &ProvenCompactCiphertextList) {
|
||||
self.ct_coeffs_buffer.extend(
|
||||
list.ct_list
|
||||
.proved_lists
|
||||
.iter()
|
||||
.flat_map(|list| list.0.ct_list.as_ref()),
|
||||
);
|
||||
|
||||
self.meta_buffer.extend(
|
||||
list.ct_list
|
||||
.proved_lists
|
||||
.iter()
|
||||
.flat_map(|list| list.1.to_le_bytes()),
|
||||
);
|
||||
|
||||
// We draw only one seed for the full list
|
||||
self.ct_count += 1;
|
||||
}
|
||||
|
||||
/// Add a metadata buffer to the context.
|
||||
///
|
||||
/// These bytes will be added to a temporary buffer and will only be hashed during the
|
||||
|
||||
@@ -219,258 +219,3 @@ fn test_ciphertext_re_randomization_after_compression_impl(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "zk-pok")]
|
||||
mod zk {
|
||||
use crate::core_crypto::prelude::LweCiphertextCount;
|
||||
use crate::integer::ciphertext::{ProvenCompactCiphertextList, ReRandomizationContext};
|
||||
use crate::integer::key_switching_key::KeySwitchingKey;
|
||||
use crate::integer::parameters::IntegerCompactCiphertextListExpansionMode;
|
||||
use crate::integer::{
|
||||
BooleanBlock, ClientKey, CompactPrivateKey, CompactPublicKey, RadixCiphertext, ServerKey,
|
||||
SignedRadixCiphertext,
|
||||
};
|
||||
use crate::shortint::parameters::test_params::{
|
||||
TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
TEST_PARAM_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2,
|
||||
};
|
||||
use crate::zk::{CompactPkeCrs, ZkComputeLoad};
|
||||
use rand::Rng;
|
||||
|
||||
#[test]
|
||||
fn test_proven_compact_ciphertext_list_re_randomization() {
|
||||
let pke_params = TEST_PARAM_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
|
||||
let ksk_params = TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let fhe_params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let num_blocks = 4usize;
|
||||
let metadata = [b't', b'e', b's', b't'];
|
||||
let rerand_domain_separator = *b"TFHE_Rrd";
|
||||
let compact_public_encryption_domain_separator = *b"TFHE_Enc";
|
||||
|
||||
let cks = ClientKey::new(fhe_params);
|
||||
let sks = ServerKey::new_radix_server_key(&cks);
|
||||
let compact_private_key = CompactPrivateKey::new(pke_params);
|
||||
let ksk = KeySwitchingKey::new((&compact_private_key, None), (&cks, &sks), ksk_params);
|
||||
let pk = CompactPublicKey::new(&compact_private_key);
|
||||
|
||||
let crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(512)).unwrap();
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let message_modulus = pke_params.message_modulus.0 as u128;
|
||||
|
||||
// Unsigned
|
||||
{
|
||||
let modulus = message_modulus.pow(num_blocks as u32);
|
||||
let message = rng.gen::<u128>() % modulus;
|
||||
|
||||
let mut builder = ProvenCompactCiphertextList::builder(&pk);
|
||||
builder.push_with_num_blocks(message, num_blocks);
|
||||
|
||||
let proven_ct = builder
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let mut re_rand_context = ReRandomizationContext::new(
|
||||
rerand_domain_separator,
|
||||
[metadata.as_slice()],
|
||||
compact_public_encryption_domain_separator,
|
||||
);
|
||||
|
||||
re_rand_context.add_proven_ciphertext_list(&proven_ct);
|
||||
|
||||
let mut seed_gen = re_rand_context.finalize();
|
||||
|
||||
let mut re_randomized = proven_ct.clone();
|
||||
re_randomized
|
||||
.re_randomize(&pk, seed_gen.next_seed().unwrap())
|
||||
.unwrap();
|
||||
|
||||
assert!(proven_ct != re_randomized);
|
||||
|
||||
let expander = re_randomized
|
||||
.expand_without_verification(
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(
|
||||
ksk.as_view(),
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let expanded: RadixCiphertext = expander.get(0).unwrap().unwrap();
|
||||
let decrypted: u128 = cks.decrypt_radix(&expanded);
|
||||
assert_eq!(decrypted, message);
|
||||
}
|
||||
|
||||
// Signed
|
||||
{
|
||||
let modulus = message_modulus.pow((num_blocks - 1) as u32) as i128;
|
||||
let message = rng.gen::<i128>() % modulus;
|
||||
|
||||
let mut builder = ProvenCompactCiphertextList::builder(&pk);
|
||||
builder.push_with_num_blocks(message, num_blocks);
|
||||
|
||||
let proven_ct = builder
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let mut re_rand_context = ReRandomizationContext::new(
|
||||
rerand_domain_separator,
|
||||
[metadata.as_slice()],
|
||||
compact_public_encryption_domain_separator,
|
||||
);
|
||||
|
||||
re_rand_context.add_proven_ciphertext_list(&proven_ct);
|
||||
|
||||
let mut seed_gen = re_rand_context.finalize();
|
||||
|
||||
let mut re_randomized = proven_ct.clone();
|
||||
re_randomized
|
||||
.re_randomize(&pk, seed_gen.next_seed().unwrap())
|
||||
.unwrap();
|
||||
|
||||
assert!(proven_ct != re_randomized);
|
||||
|
||||
let expander = re_randomized
|
||||
.expand_without_verification(
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(
|
||||
ksk.as_view(),
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let expanded: SignedRadixCiphertext = expander.get(0).unwrap().unwrap();
|
||||
let decrypted: i128 = cks.decrypt_signed_radix(&expanded);
|
||||
assert_eq!(decrypted, message);
|
||||
}
|
||||
|
||||
// Boolean
|
||||
{
|
||||
for message in [false, true] {
|
||||
let mut builder = ProvenCompactCiphertextList::builder(&pk);
|
||||
builder.push(message);
|
||||
|
||||
let proven_ct = builder
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let mut re_rand_context = ReRandomizationContext::new(
|
||||
rerand_domain_separator,
|
||||
[metadata.as_slice()],
|
||||
compact_public_encryption_domain_separator,
|
||||
);
|
||||
|
||||
re_rand_context.add_proven_ciphertext_list(&proven_ct);
|
||||
|
||||
let mut seed_gen = re_rand_context.finalize();
|
||||
|
||||
let mut re_randomized = proven_ct.clone();
|
||||
re_randomized
|
||||
.re_randomize(&pk, seed_gen.next_seed().unwrap())
|
||||
.unwrap();
|
||||
|
||||
assert!(proven_ct != re_randomized);
|
||||
|
||||
let expander = re_randomized
|
||||
.expand_without_verification(
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(
|
||||
ksk.as_view(),
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let expanded: BooleanBlock = expander.get(0).unwrap().unwrap();
|
||||
let decrypted = cks.decrypt_bool(&expanded);
|
||||
assert_eq!(decrypted, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
#[test]
|
||||
fn test_proven_compact_ciphertext_list_re_rand_cpu_gpu_compatibility() {
|
||||
use crate::core_crypto::gpu::CudaStreams;
|
||||
use crate::integer::gpu::zk::CudaProvenCompactCiphertextList;
|
||||
use crate::shortint::parameters::test_params::TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
|
||||
|
||||
let pke_params = TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
|
||||
|
||||
let compact_private_key = CompactPrivateKey::new(pke_params);
|
||||
let pk = CompactPublicKey::new(&compact_private_key);
|
||||
|
||||
let compact_public_encryption_domain_separator = *b"TFHE_Enc";
|
||||
let rerand_domain_separator = *b"TFHE_Rrd";
|
||||
|
||||
// Intentionally low so that we test when multiple lists and proofs are needed
|
||||
let crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(8)).unwrap();
|
||||
let metadata = [b'r', b'e', b'r', b'a', b'n', b'd'];
|
||||
|
||||
let clear_a = rand::random::<u64>();
|
||||
let clear_b = rand::random::<i8>();
|
||||
|
||||
let proven_ct = ProvenCompactCiphertextList::builder(&pk)
|
||||
.push(clear_a)
|
||||
.push(clear_b)
|
||||
.push(false)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
// Clone the list so both CPU and GPU start from the same state
|
||||
let mut cpu_list = proven_ct.clone();
|
||||
|
||||
// Simulate a 256 bits nonce
|
||||
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rand::random());
|
||||
|
||||
// Create two identical seeds from the same context inputs
|
||||
let cpu_seed = {
|
||||
let mut ctx = ReRandomizationContext::new(
|
||||
rerand_domain_separator,
|
||||
[b"expand".as_slice(), nonce.as_slice()],
|
||||
compact_public_encryption_domain_separator,
|
||||
);
|
||||
ctx.add_proven_ciphertext_list(&proven_ct);
|
||||
ctx.finalize().next_seed().unwrap()
|
||||
};
|
||||
|
||||
let gpu_seed = {
|
||||
let mut ctx = ReRandomizationContext::new(
|
||||
rerand_domain_separator,
|
||||
[b"expand".as_slice(), nonce.as_slice()],
|
||||
compact_public_encryption_domain_separator,
|
||||
);
|
||||
ctx.add_proven_ciphertext_list(&proven_ct);
|
||||
ctx.finalize().next_seed().unwrap()
|
||||
};
|
||||
|
||||
// Re-randomize on CPU
|
||||
cpu_list.re_randomize(&pk, cpu_seed).unwrap();
|
||||
|
||||
// Re-randomize on GPU
|
||||
let streams = CudaStreams::new_multi_gpu();
|
||||
let mut gpu_list = CudaProvenCompactCiphertextList::from_proven_compact_ciphertext_list(
|
||||
&proven_ct, &streams,
|
||||
);
|
||||
gpu_list.re_randomize(&pk, gpu_seed, &streams).unwrap();
|
||||
|
||||
// Read ciphertext data back from GPU and reconstruct an integer proven list
|
||||
let gpu_compact_lists = gpu_list
|
||||
.d_flattened_compact_lists
|
||||
.to_vec_shortint_compact_ciphertext_list(&streams)
|
||||
.unwrap();
|
||||
|
||||
let gpu_proved_lists: Vec<_> = gpu_compact_lists
|
||||
.into_iter()
|
||||
.zip(gpu_list.h_proved_lists.ct_list.proved_lists.iter())
|
||||
.map(|(ct, (_, proof))| (ct, proof.clone()))
|
||||
.collect();
|
||||
|
||||
let gpu_on_cpu = ProvenCompactCiphertextList {
|
||||
ct_list: crate::shortint::ciphertext::ProvenCompactCiphertextList {
|
||||
proved_lists: gpu_proved_lists,
|
||||
},
|
||||
info: gpu_list.h_proved_lists.info.clone(),
|
||||
};
|
||||
|
||||
assert!(cpu_list == gpu_on_cpu);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::core_crypto::algorithms::verify_lwe_compact_ciphertext_list;
|
||||
use crate::core_crypto::gpu::CudaStreams;
|
||||
use crate::core_crypto::prelude::{CiphertextModulus, LweCiphertextCount};
|
||||
use crate::integer::ciphertext::ReRandomizationSeed;
|
||||
use crate::integer::gpu::ciphertext::compact_list::{
|
||||
CudaCompactCiphertextListExpander, CudaFlattenedVecCompactCiphertextList,
|
||||
};
|
||||
@@ -65,42 +64,6 @@ impl CudaProvenCompactCiphertextList {
|
||||
Err(crate::ErrorKind::InvalidZkProof.into())
|
||||
}
|
||||
|
||||
pub fn verify_re_randomize_and_expand(
|
||||
&self,
|
||||
crs: &CompactPkeCrs,
|
||||
public_key: &CompactPublicKey,
|
||||
metadata: &[u8],
|
||||
key: &CudaKeySwitchingKey,
|
||||
seed: ReRandomizationSeed,
|
||||
streams: &CudaStreams,
|
||||
) -> crate::Result<CudaCompactCiphertextListExpander> {
|
||||
let (all_valid, r) = rayon::join(
|
||||
|| {
|
||||
self.h_proved_lists
|
||||
.ct_list
|
||||
.proved_lists
|
||||
.par_iter()
|
||||
.all(|(ct_list, proof)| {
|
||||
verify_lwe_compact_ciphertext_list(
|
||||
&ct_list.ct_list,
|
||||
&public_key.key.key,
|
||||
proof,
|
||||
crs,
|
||||
metadata,
|
||||
)
|
||||
.is_valid()
|
||||
})
|
||||
},
|
||||
|| self.re_randomize_and_expand_without_verification(key, public_key, seed, streams),
|
||||
);
|
||||
|
||||
if all_valid {
|
||||
return r;
|
||||
}
|
||||
|
||||
Err(crate::ErrorKind::InvalidZkProof.into())
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// - [CudaStreams::synchronize] __must__ be called after this function as soon as
|
||||
@@ -114,46 +77,6 @@ impl CudaProvenCompactCiphertextList {
|
||||
.expand(key, super::ZKType::Casting, streams)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// - [CudaStreams::synchronize] __must__ be called after this function as soon as
|
||||
/// synchronization is required
|
||||
pub fn re_randomize_and_expand_without_verification(
|
||||
&self,
|
||||
key: &CudaKeySwitchingKey,
|
||||
public_key: &CompactPublicKey,
|
||||
seed: ReRandomizationSeed,
|
||||
streams: &CudaStreams,
|
||||
) -> crate::Result<CudaCompactCiphertextListExpander> {
|
||||
let mut rerandomized = self.duplicate(streams);
|
||||
rerandomized.re_randomize(public_key, seed, streams)?;
|
||||
|
||||
rerandomized.expand_without_verification(key, streams)
|
||||
}
|
||||
|
||||
pub fn re_randomize(
|
||||
&mut self,
|
||||
public_key: &CompactPublicKey,
|
||||
seed: ReRandomizationSeed,
|
||||
streams: &CudaStreams,
|
||||
) -> crate::Result<()> {
|
||||
self.h_proved_lists.re_randomize(public_key, seed)?;
|
||||
let cpu_lists = self
|
||||
.h_proved_lists
|
||||
.ct_list
|
||||
.proved_lists
|
||||
.iter()
|
||||
.map(|(list, _)| list.clone())
|
||||
.collect();
|
||||
self.d_flattened_compact_lists =
|
||||
CudaFlattenedVecCompactCiphertextList::from_vec_shortint_compact_ciphertext_list(
|
||||
cpu_lists,
|
||||
self.h_proved_lists.info.clone(),
|
||||
streams,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn from_proven_compact_ciphertext_list(
|
||||
h_proved_lists: &ProvenCompactCiphertextList,
|
||||
streams: &CudaStreams,
|
||||
|
||||
@@ -1,712 +0,0 @@
|
||||
use crate::integer::prelude::ServerKeyDefaultCMux;
|
||||
use crate::integer::server_key::radix_parallel::ilog2::{BitValue, Direction};
|
||||
use crate::integer::{BooleanBlock, IntegerCiphertext, RadixCiphertext, ServerKey};
|
||||
use crate::shortint::ciphertext::Degree;
|
||||
use crate::shortint::server_key::LookupTableOwned;
|
||||
use crate::shortint::{CarryModulus, Ciphertext, MessageModulus};
|
||||
use rayon::prelude::*;
|
||||
|
||||
impl ServerKey {
|
||||
pub(crate) fn count_consecutive_bits_2_2_unsigned(
|
||||
&self,
|
||||
in_ct: &RadixCiphertext,
|
||||
direction: Direction,
|
||||
bit_value: BitValue,
|
||||
) -> RadixCiphertext {
|
||||
assert_eq!(self.message_modulus(), MessageModulus(4));
|
||||
assert_eq!(self.carry_modulus(), CarryModulus(4));
|
||||
|
||||
let input_num_bits = 2 * in_ct.blocks.len();
|
||||
|
||||
// output
|
||||
let num_output_bits = (input_num_bits as f64 + 1.).log2().ceil() as usize;
|
||||
|
||||
let num_output_blocks = num_output_bits.div_ceil(2);
|
||||
|
||||
let CountConsecutiveBitsResult { flag, mut digits } =
|
||||
self.unchecked_count_consecutive_bits_2_2_unsigned(in_ct, direction, bit_value);
|
||||
|
||||
digits.resize(num_output_blocks, self.key.create_trivial(0));
|
||||
|
||||
let true_ct = RadixCiphertext::from_blocks(digits);
|
||||
|
||||
let condition = BooleanBlock::new_unchecked(flag);
|
||||
|
||||
self.if_then_else_parallelized(&condition, &true_ct, input_num_bits as u64)
|
||||
}
|
||||
|
||||
// If there is at least one non zero/one bit in the input:
|
||||
// - flag is 1
|
||||
// - digits is the number of trailing/leading zeros/ones of the input
|
||||
// Otherwise, the flag and the digits are equal to 0
|
||||
//
|
||||
// Let's explain how the algorithm works for leading zeros.
|
||||
// Let's suppose we have a 64 bits input and
|
||||
// the input is not 0 (this case works a bit differently).
|
||||
// The result is on 6 bits grouped by 2 (b5_b4, b3_b2, b1_b0)
|
||||
//
|
||||
// b5_b4 is the index of the first (starting from MSB) group of 16 bits
|
||||
// which has (at least) one bit equal to 1.
|
||||
// (example, if b5_b4=0, then leading_zeros < 16 thus (at least) one of the 16 MSB is not 0).
|
||||
// (example, if b5_b4=1, then 16 <= leading_zeros < 32 thus the 16 MSB are
|
||||
// all 0 and (at least) one the one of the 16 next MSB is not 0).
|
||||
//
|
||||
// In this group of 16 bits:
|
||||
// - b3_b2 is is the index of the first (starting from MSB) group of 4 bits which has (at
|
||||
// least) one bit equal to 1
|
||||
// In this group of 4 bits:
|
||||
// - b1_b0 is is the index of the first (starting from MSB) bit equal to 1
|
||||
//
|
||||
// This is the top down view
|
||||
//
|
||||
// In the algorithm, we use the bottom up view.
|
||||
// We compute the "b1_b0" of each group of 4 bits
|
||||
// and a boolean flag to know if (at least) one of the bits are not 0.
|
||||
//
|
||||
// We then group by 16 bits.
|
||||
// We compute the "b3_b2" of each group.
|
||||
// It is the index of the first (starting from MSB) group of 4 with a non zero flag.
|
||||
// We select its "b1_b0" among the 4 computed in the previous step.
|
||||
// We now have "b3_b2_b1_b0" for each group of 16.
|
||||
// We also need a flag to know if (at least) one of the bits are not 0.
|
||||
//
|
||||
// We now have 4 groups of 16.
|
||||
// "b5_b4" is the index of the first (starting from MSB) group of 16 with a non zero flag.
|
||||
// We select its "b3_b2_b1_b0" among the 4 computed in the previous step.
|
||||
// We also compute a flag to know if (at least) one of the bits are not 0.
|
||||
//
|
||||
// We now have the final result
|
||||
pub(crate) fn unchecked_count_consecutive_bits_2_2_unsigned(
|
||||
&self,
|
||||
in_ct: &RadixCiphertext,
|
||||
direction: Direction,
|
||||
bit_value: BitValue,
|
||||
) -> CountConsecutiveBitsResult {
|
||||
assert_eq!(self.message_modulus(), MessageModulus(4));
|
||||
assert_eq!(self.carry_modulus(), CarryModulus(4));
|
||||
|
||||
if in_ct.blocks().is_empty() {
|
||||
return CountConsecutiveBitsResult {
|
||||
flag: self.key.create_trivial(0),
|
||||
digits: Vec::new(),
|
||||
};
|
||||
}
|
||||
|
||||
let num_blocks_after_init = in_ct.blocks().len() as f64 / 2_f64;
|
||||
|
||||
let reductions_depth = num_blocks_after_init.log(4_f64).ceil() as usize;
|
||||
|
||||
let mut up_scale_digits: bool = reductions_depth % 2 == 1;
|
||||
|
||||
let digit_out_scale_init = if up_scale_digits { 2 } else { 0 };
|
||||
|
||||
let mut state: Vec<BlockState> = match direction {
|
||||
Direction::Trailing => in_ct
|
||||
.blocks()
|
||||
.par_chunks(2)
|
||||
.map(|chunk| self.pack_blocks_by_pair(chunk, direction, bit_value))
|
||||
.enumerate()
|
||||
.map(|(index, ct)| {
|
||||
self.initial_state(&ct, index % 4, digit_out_scale_init, direction, bit_value)
|
||||
})
|
||||
.collect(),
|
||||
// par_rchunk(2).enumerate().rev() to:
|
||||
// - get a reverse index without changing the order
|
||||
// - align chunk on the most significant blocks (if the last chunk has only one element)
|
||||
Direction::Leading => in_ct
|
||||
.blocks()
|
||||
.par_rchunks(2)
|
||||
.map(|chunk| self.pack_blocks_by_pair(chunk, direction, bit_value))
|
||||
.enumerate()
|
||||
.rev()
|
||||
.map(|(reverse_index, ct)| {
|
||||
self.initial_state(
|
||||
&ct,
|
||||
reverse_index % 4,
|
||||
digit_out_scale_init,
|
||||
direction,
|
||||
bit_value,
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
|
||||
while state.len() != 1 {
|
||||
up_scale_digits = !up_scale_digits;
|
||||
|
||||
state = match direction {
|
||||
Direction::Trailing => state
|
||||
.par_chunks(4)
|
||||
.enumerate()
|
||||
.map(|(index, chunk)| {
|
||||
self.reduce_blocks(chunk, index % 4, up_scale_digits, direction)
|
||||
})
|
||||
.collect(),
|
||||
// par_rchunk(4).enumerate().rev() to:
|
||||
// - get a reverse index without changing the order
|
||||
// - align chunk on the most significant blocks (if the last chunk does not have 4
|
||||
// elements)
|
||||
Direction::Leading => state
|
||||
.par_rchunks(4)
|
||||
.enumerate()
|
||||
.rev()
|
||||
.map(|(reverse_index, chunk)| {
|
||||
self.reduce_blocks(chunk, reverse_index % 4, up_scale_digits, direction)
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
}
|
||||
|
||||
assert!(!up_scale_digits);
|
||||
|
||||
let BlockState {
|
||||
flag,
|
||||
digits: digits_state,
|
||||
} = state.pop().unwrap();
|
||||
|
||||
CountConsecutiveBitsResult {
|
||||
flag,
|
||||
digits: digits_state.select(self, up_scale_digits, direction),
|
||||
}
|
||||
}
|
||||
|
||||
fn pack_blocks_by_pair(
|
||||
&self,
|
||||
chunk: &[Ciphertext],
|
||||
direction: Direction,
|
||||
bit_value: BitValue,
|
||||
) -> Ciphertext {
|
||||
match chunk {
|
||||
[chunk0, chunk1] => {
|
||||
// chunk 1 is most significant, so we scale it to the carries
|
||||
let mut result = self.key.unchecked_scalar_mul(chunk1, 4);
|
||||
|
||||
self.key.unchecked_add_assign(&mut result, chunk0);
|
||||
|
||||
result
|
||||
}
|
||||
[chunk0] => {
|
||||
// We must pad in case the input has a even number of blocks
|
||||
// The pad must not change the result
|
||||
// This padding value will only have an impact on the final result if all other bits
|
||||
// are equal to the given bit_value In this case, we want to pad
|
||||
// with bits equal to the bit_value so the result is flag = 0,
|
||||
// digits= [0, ..., 0] as specified
|
||||
let padding_value = match bit_value {
|
||||
BitValue::Zero => 0,
|
||||
BitValue::One => 3,
|
||||
};
|
||||
|
||||
match direction {
|
||||
// We put the padding in the MSB
|
||||
Direction::Trailing => self.key.unchecked_scalar_add(chunk0, 4 * padding_value),
|
||||
// We put the padding in the LSB
|
||||
Direction::Leading => {
|
||||
let mut result = self.key.unchecked_scalar_mul(chunk0, 4);
|
||||
self.key
|
||||
.unchecked_scalar_add_assign(&mut result, padding_value);
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn initial_state(
|
||||
&self,
|
||||
ct: &Ciphertext,
|
||||
flag_out_scale: usize,
|
||||
digit_out_scale: usize,
|
||||
direction: Direction,
|
||||
bit_value: BitValue,
|
||||
) -> BlockState {
|
||||
let (flag, new_digit) = rayon::join(
|
||||
|| {
|
||||
let lut_non_full_flag = self.lut_non_full_flag(flag_out_scale, bit_value);
|
||||
|
||||
self.key.apply_lookup_table(ct, &lut_non_full_flag)
|
||||
},
|
||||
|| {
|
||||
let lut_new_digit = self.lut_new_digit_init(digit_out_scale, direction, bit_value);
|
||||
|
||||
self.key.apply_lookup_table(ct, &lut_new_digit)
|
||||
},
|
||||
);
|
||||
|
||||
BlockState {
|
||||
flag,
|
||||
digits: DigitsUnselected {
|
||||
new_digit,
|
||||
old_digits_to_select: Vec::new(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Put blocks of n digits from a slice to groups of 4
|
||||
//
|
||||
// Each group of 4 is reduced to a single block of (n+1) digits as such:
|
||||
// The fist block with a non zero flag is selected.
|
||||
// The new digits are the digits of this block to which we add the index of this selected block
|
||||
fn reduce_blocks(
|
||||
&self,
|
||||
blocks: &[BlockState],
|
||||
out_flag_scale: usize,
|
||||
up_scale_digits: bool,
|
||||
direction: Direction,
|
||||
) -> BlockState {
|
||||
let (in_flags, digits): (Vec<_>, Vec<_>) = blocks
|
||||
.iter()
|
||||
.map(
|
||||
|BlockState {
|
||||
flag,
|
||||
digits: digits_state,
|
||||
}| (flag, digits_state),
|
||||
)
|
||||
.unzip();
|
||||
|
||||
// old digits are one step behind the flag and new_digit
|
||||
// so opposite scaling
|
||||
let up_scale_old_digits = !up_scale_digits;
|
||||
|
||||
let ((flag, new_digit), old_digits_to_select) = rayon::join(
|
||||
|| self.build_new_flag_and_digit(out_flag_scale, up_scale_digits, &in_flags),
|
||||
|| self.reduce_digit_states(&digits, up_scale_old_digits, direction),
|
||||
);
|
||||
|
||||
BlockState {
|
||||
flag,
|
||||
digits: DigitsUnselected {
|
||||
new_digit,
|
||||
old_digits_to_select,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// The input is expected to be (at most) 4 binary flags, scaled by 0, 1, 2, 3 (0_0_0_f, 0_0_f_0,
|
||||
// 0_f_0_0, f_0_0_0) The new flag is 0 if all input flags are 0, 1 otherwise
|
||||
// The new digit is the scaling of the smallest non zero flag, 0 otherwise
|
||||
// The output does not depend on the order of the input flags (as they are all summed)
|
||||
fn build_new_flag_and_digit(
|
||||
&self,
|
||||
out_flag_scale: usize,
|
||||
up_scale_digits: bool,
|
||||
flags: &[&Ciphertext],
|
||||
) -> (Ciphertext, Ciphertext) {
|
||||
let sum_flags = flags.iter().fold(self.key.create_trivial(0), |mut a, b| {
|
||||
self.key.unchecked_add_assign(&mut a, b);
|
||||
a
|
||||
});
|
||||
|
||||
let out_digit_scale = if up_scale_digits { 2 } else { 0 };
|
||||
|
||||
rayon::join(
|
||||
|| {
|
||||
let lut_non_zero_flag = self.lut_non_zero_flag(out_flag_scale);
|
||||
|
||||
self.key.apply_lookup_table(&sum_flags, &lut_non_zero_flag)
|
||||
},
|
||||
|| {
|
||||
let lut_new_digit = self.lut_new_digit_from_sum_flags(out_digit_scale);
|
||||
|
||||
self.key.apply_lookup_table(&sum_flags, &lut_new_digit)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn reduce_digit_states(
|
||||
&self,
|
||||
states: &[&DigitsUnselected],
|
||||
up_scale_digits: bool,
|
||||
direction: Direction,
|
||||
) -> Vec<DigitUnselected> {
|
||||
// we'll want to select one of the lists of digits (Vec<Ciphertext>)
|
||||
// we'll want unselected_list_of_digits[new_digit]
|
||||
let unselected_list_of_digits: Vec<Vec<Ciphertext>> = states
|
||||
.par_iter()
|
||||
.map(|digits_unselected| digits_unselected.select(self, up_scale_digits, direction))
|
||||
.collect();
|
||||
|
||||
// after transpose, each element is an UnselectedDigit (i.e. a list of digits to select
|
||||
// from) we'll want
|
||||
// [
|
||||
// list_of_unselected_digits[0][new_digit],
|
||||
// list_of_unselected_digits[1][new_digit],
|
||||
// ...
|
||||
// ]
|
||||
let list_of_unselected_digits = transpose(unselected_list_of_digits);
|
||||
|
||||
list_of_unselected_digits
|
||||
.into_iter()
|
||||
.map(|digits_to_select_from| DigitUnselected {
|
||||
digits_to_select_from,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn select_old_digit_lut(
|
||||
&self,
|
||||
up_scale_digits: bool,
|
||||
selector: usize,
|
||||
) -> crate::shortint::server_key::LookupTable<Vec<u64>> {
|
||||
self.key.generate_lookup_table(|x: u64| {
|
||||
let in_carries = x >> 2;
|
||||
let in_message = x & 3;
|
||||
|
||||
// The input of the resulting LUT is supposed to have the old/new digits in
|
||||
// carry/message depending on up_scale_digits
|
||||
let (old_digit, new_digit) = if up_scale_digits {
|
||||
(in_message, in_carries)
|
||||
} else {
|
||||
(in_carries, in_message)
|
||||
};
|
||||
|
||||
if new_digit == selector as u64 {
|
||||
if up_scale_digits {
|
||||
old_digit << 2
|
||||
} else {
|
||||
old_digit
|
||||
}
|
||||
} else {
|
||||
0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// build a lut which returns
|
||||
// `0` if the 4 bits input is full of the bit_value (0000 for Zero or 1111 for One)
|
||||
// `1 << out_scale` otherwise
|
||||
fn lut_non_full_flag(&self, out_scale: usize, bit_value: BitValue) -> LookupTableOwned {
|
||||
let full_value = match bit_value {
|
||||
BitValue::Zero => 0,
|
||||
BitValue::One => 15,
|
||||
};
|
||||
|
||||
self.key
|
||||
.generate_lookup_table(|x| u64::from(x != full_value) << out_scale)
|
||||
}
|
||||
|
||||
fn lut_non_zero_flag(&self, out_scale: usize) -> LookupTableOwned {
|
||||
self.key
|
||||
.generate_lookup_table(|x| u64::from(x != 0) << out_scale)
|
||||
}
|
||||
|
||||
// build a lut which
|
||||
// return `0` if the input is full of the bit_value (0000 for Zero or 1111 for One)
|
||||
// otherwise, return the trailing/leading zeros/ones of the 4 bits input, scaled by `out_scale`
|
||||
fn lut_new_digit_init(
|
||||
&self,
|
||||
out_scale: usize,
|
||||
direction: Direction,
|
||||
bit_value: BitValue,
|
||||
) -> LookupTableOwned {
|
||||
self.key.generate_lookup_table(|x: u64| {
|
||||
let full_value = match bit_value {
|
||||
BitValue::Zero => 0,
|
||||
BitValue::One => 15,
|
||||
};
|
||||
|
||||
let input_precision = 4;
|
||||
|
||||
let leading_bits_to_ignore = u64::BITS - input_precision;
|
||||
|
||||
let new_digit = if x == full_value {
|
||||
0
|
||||
} else {
|
||||
match (direction, bit_value) {
|
||||
(Direction::Trailing, BitValue::Zero) => x.trailing_zeros(),
|
||||
(Direction::Trailing, BitValue::One) => x.trailing_ones(),
|
||||
(Direction::Leading, BitValue::Zero) => {
|
||||
(x << leading_bits_to_ignore).leading_zeros()
|
||||
}
|
||||
(Direction::Leading, BitValue::One) => {
|
||||
(x << leading_bits_to_ignore).leading_ones()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
(new_digit as u64) << out_scale
|
||||
})
|
||||
}
|
||||
|
||||
// build a lut
|
||||
// the input is expected to the sum of 4 binary flags, scaled by 0, 1, 2, 3 (0_0_0_f0 + 0_0_f1_0
|
||||
// + 0_f2_0_0 + f3_0_0_0 = f3_f2_f1_f0) if all the flags are 0, the result if 0
|
||||
// otherwise, the result is the index of the first of these flag which is not 0, starting by f0.
|
||||
// this function is used in all cases (trailing/leading zeros/ones) in all steps expect the
|
||||
// first one
|
||||
fn lut_new_digit_from_sum_flags(&self, out_scale: usize) -> LookupTableOwned {
|
||||
self.key.generate_lookup_table(|x: u64| {
|
||||
let new_digit = if x == 0 { 0 } else { x.trailing_zeros() as u64 };
|
||||
|
||||
new_digit << out_scale
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn transpose<T>(v: Vec<Vec<T>>) -> Vec<Vec<T>> {
|
||||
if v.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
let num_cols = v[0].len();
|
||||
let mut row_iterators: Vec<_> = v.into_iter().map(|row| row.into_iter()).collect();
|
||||
(0..num_cols)
|
||||
.map(|_| {
|
||||
row_iterators
|
||||
.iter_mut()
|
||||
.map(|row_iterator| row_iterator.next().unwrap())
|
||||
.collect::<Vec<T>>()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
struct BlockState {
|
||||
flag: Ciphertext,
|
||||
digits: DigitsUnselected,
|
||||
}
|
||||
|
||||
// When doing the reduction, we want to use the new_digit to select each unselected_digit
|
||||
// We then add the new digit to the end of the list
|
||||
struct DigitsUnselected {
|
||||
new_digit: Ciphertext,
|
||||
old_digits_to_select: Vec<DigitUnselected>,
|
||||
}
|
||||
|
||||
impl DigitsUnselected {
|
||||
fn select(
|
||||
&self,
|
||||
sk: &ServerKey,
|
||||
up_scale_digits: bool,
|
||||
direction: Direction,
|
||||
) -> Vec<Ciphertext> {
|
||||
let Self {
|
||||
new_digit,
|
||||
old_digits_to_select,
|
||||
} = self;
|
||||
|
||||
let mut result: Vec<_> = old_digits_to_select
|
||||
.par_iter()
|
||||
.map(|digit| digit.select(new_digit, sk, up_scale_digits, direction))
|
||||
.collect();
|
||||
|
||||
result.push(new_digit.clone());
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
// Stores a list of (at most) 4 ciphertexts each storing a digit in carries or messages
|
||||
// This type is meant to be reduced to a single selected digit
|
||||
struct DigitUnselected {
|
||||
digits_to_select_from: Vec<Ciphertext>,
|
||||
}
|
||||
|
||||
impl DigitUnselected {
|
||||
fn select(
|
||||
&self,
|
||||
selector: &Ciphertext,
|
||||
sk: &ServerKey,
|
||||
up_scale_digits: bool,
|
||||
direction: Direction,
|
||||
) -> Ciphertext {
|
||||
let digits_to_select_from: Vec<&Ciphertext> = match direction {
|
||||
Direction::Trailing => self.digits_to_select_from.iter().collect(),
|
||||
Direction::Leading => self.digits_to_select_from.iter().rev().collect(),
|
||||
};
|
||||
|
||||
// Computation is sum_i( if i==selector { digits_to_select_from[i] } else {0} )
|
||||
// Which gives digits_to_select_from[selector]
|
||||
let mut result = digits_to_select_from
|
||||
.par_iter()
|
||||
.enumerate()
|
||||
.map(|(i, old_digit)| {
|
||||
let sum = sk.key.unchecked_add(old_digit, selector);
|
||||
|
||||
let acc = sk.select_old_digit_lut(up_scale_digits, i);
|
||||
|
||||
sk.key.apply_lookup_table(&sum, &acc)
|
||||
})
|
||||
.reduce(
|
||||
|| sk.key.create_trivial(0),
|
||||
|mut sum: Ciphertext, new: Ciphertext| {
|
||||
sk.key.unchecked_add_assign(&mut sum, &new);
|
||||
|
||||
sum
|
||||
},
|
||||
);
|
||||
|
||||
result.degree = if up_scale_digits {
|
||||
Degree(12)
|
||||
} else {
|
||||
Degree(3)
|
||||
};
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct CountConsecutiveBitsResult {
|
||||
#[allow(unused)]
|
||||
pub(crate) flag: Ciphertext,
|
||||
pub(crate) digits: Vec<Ciphertext>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::integer::keycache::KEY_CACHE;
|
||||
use crate::integer::{ClientKey, IntegerKeyKind, RadixCiphertext};
|
||||
use crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
#[test]
|
||||
fn test_unchecked_new_count_consecutive_bits_trivial_input_param_message_2_carry_2() {
|
||||
let param = PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128;
|
||||
|
||||
let (cks, sks) = KEY_CACHE.get_from_params(param, IntegerKeyKind::Radix);
|
||||
|
||||
for direction in [Direction::Leading, Direction::Trailing] {
|
||||
for bit_value in [BitValue::Zero, BitValue::One] {
|
||||
for num_blocks in 1..64 {
|
||||
let num_bits = 2 * num_blocks;
|
||||
|
||||
println!("num_bits: {num_bits}",);
|
||||
|
||||
for target_result in 0..=num_bits {
|
||||
for _ in 0..10 {
|
||||
test_one_random(
|
||||
&cks,
|
||||
&sks,
|
||||
num_blocks,
|
||||
direction,
|
||||
bit_value,
|
||||
target_result,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_one_random(
|
||||
cks: &ClientKey,
|
||||
sks: &ServerKey,
|
||||
num_blocks: usize,
|
||||
direction: Direction,
|
||||
bit_value: BitValue,
|
||||
target_result: usize,
|
||||
) {
|
||||
let num_bits = 2 * num_blocks;
|
||||
|
||||
let message = build_number(num_bits, target_result, direction, bit_value);
|
||||
|
||||
let (expected_flag, expected_result) =
|
||||
expected_result(num_bits, message, direction, bit_value);
|
||||
|
||||
let (flag, result) =
|
||||
get_result_for_trivial(cks, sks, num_blocks, message, direction, bit_value);
|
||||
|
||||
assert_eq!(expected_flag, flag);
|
||||
|
||||
if target_result == num_bits {
|
||||
assert!(!expected_flag);
|
||||
|
||||
assert_eq!(expected_result, 0);
|
||||
} else {
|
||||
assert_eq!(target_result as u64, expected_result);
|
||||
}
|
||||
|
||||
assert_eq!(expected_result, result);
|
||||
}
|
||||
|
||||
fn expected_result(
|
||||
num_bits: usize,
|
||||
message: u128,
|
||||
direction: Direction,
|
||||
bit_value: BitValue,
|
||||
) -> (bool, u64) {
|
||||
let full_value = match bit_value {
|
||||
BitValue::Zero => 0,
|
||||
BitValue::One => (1 << num_bits) - 1,
|
||||
};
|
||||
|
||||
if message == full_value {
|
||||
(false, 0)
|
||||
} else {
|
||||
let leading_bits_to_ignore = 128 - num_bits;
|
||||
|
||||
let expected_result = match (direction, bit_value) {
|
||||
(Direction::Trailing, BitValue::Zero) => message.trailing_zeros(),
|
||||
(Direction::Trailing, BitValue::One) => message.trailing_ones(),
|
||||
(Direction::Leading, BitValue::Zero) => {
|
||||
(message << leading_bits_to_ignore).leading_zeros()
|
||||
}
|
||||
(Direction::Leading, BitValue::One) => {
|
||||
(message << leading_bits_to_ignore).leading_ones()
|
||||
}
|
||||
};
|
||||
|
||||
(true, expected_result as u64)
|
||||
}
|
||||
}
|
||||
|
||||
fn build_number(
|
||||
num_bits: usize,
|
||||
target_result: usize,
|
||||
direction: Direction,
|
||||
bit_value: BitValue,
|
||||
) -> u128 {
|
||||
let full_bits = num_bits - target_result;
|
||||
|
||||
let message: u128 = if full_bits == 0 {
|
||||
0
|
||||
} else {
|
||||
match direction {
|
||||
Direction::Leading => {
|
||||
(1_u128 << (full_bits - 1)) + thread_rng().gen_range(0..1 << (full_bits - 1))
|
||||
}
|
||||
Direction::Trailing => {
|
||||
let full_number =
|
||||
1_u128 + (thread_rng().gen_range(0..1 << (full_bits - 1)) << 1);
|
||||
full_number << target_result
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match bit_value {
|
||||
BitValue::Zero => message,
|
||||
//complement
|
||||
BitValue::One => (1_u128 << num_bits) - 1 - message,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_result_for_trivial(
|
||||
cks: &ClientKey,
|
||||
sks: &ServerKey,
|
||||
num_blocks: usize,
|
||||
message: u128,
|
||||
direction: Direction,
|
||||
bit_value: BitValue,
|
||||
) -> (bool, u64) {
|
||||
let input: RadixCiphertext = sks.create_trivial_radix(message, num_blocks);
|
||||
|
||||
let CountConsecutiveBitsResult { flag, digits } =
|
||||
sks.unchecked_count_consecutive_bits_2_2_unsigned(&input, direction, bit_value);
|
||||
|
||||
let flag = match cks.key.decrypt_message_and_carry(&flag) {
|
||||
0 => false,
|
||||
1 => true,
|
||||
_ => panic!(),
|
||||
};
|
||||
|
||||
let mut result = 0;
|
||||
for (i, digit) in digits.iter().enumerate() {
|
||||
let digit = cks.key.decrypt_message_and_carry(digit);
|
||||
|
||||
result += digit << (2 * i);
|
||||
}
|
||||
|
||||
(flag, result)
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ use crate::integer::{
|
||||
BooleanBlock, IntegerCiphertext, IntegerRadixCiphertext, RadixCiphertext, ServerKey,
|
||||
SignedRadixCiphertext,
|
||||
};
|
||||
use crate::shortint::{CarryModulus, Ciphertext, MessageModulus};
|
||||
use crate::shortint::Ciphertext;
|
||||
use rayon::prelude::*;
|
||||
|
||||
/// A 'bit' value
|
||||
@@ -140,12 +140,6 @@ impl ServerKey {
|
||||
return self.create_trivial_zero_radix(0);
|
||||
}
|
||||
|
||||
if self.message_modulus() == MessageModulus(4) && self.carry_modulus() == CarryModulus(4) {
|
||||
let unsigned_ct = RadixCiphertext::from_blocks(ct.blocks().to_vec());
|
||||
|
||||
return self.count_consecutive_bits_2_2_unsigned(&unsigned_ct, direction, bit_value);
|
||||
}
|
||||
|
||||
let num_bits_in_message = self.key.message_modulus.0.ilog2();
|
||||
let original_num_blocks = ct.blocks().len();
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ mod bitwise_op;
|
||||
mod block_shift;
|
||||
pub(crate) mod cmux;
|
||||
mod comparison;
|
||||
mod count_consecutive_bits;
|
||||
mod div_mod;
|
||||
mod modulus_switch_compression;
|
||||
mod mul;
|
||||
|
||||
@@ -10,7 +10,6 @@ use crate::core_crypto::commons::math::random::{DefaultRandomGenerator, XofSeed}
|
||||
use crate::core_crypto::commons::parameters::{LweCiphertextCount, PlaintextCount};
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::{LweCiphertext, LweCompactCiphertextList, PlaintextList};
|
||||
use crate::core_crypto::prelude::lwe_compact_ciphertext_list_add_assign;
|
||||
use crate::shortint::ciphertext::NoiseLevel;
|
||||
use crate::shortint::key_switching_key::KeySwitchingKeyMaterialView;
|
||||
use crate::shortint::{Ciphertext, CompactPublicKey, PBSOrder};
|
||||
@@ -19,8 +18,6 @@ use rayon::prelude::*;
|
||||
use sha3::digest::{ExtendableOutput, Update};
|
||||
use std::io::Read;
|
||||
|
||||
use super::CompactCiphertextList;
|
||||
|
||||
/// Size of the re-randomization seed in bits
|
||||
const RERAND_SEED_BITS: usize = 256;
|
||||
|
||||
@@ -251,14 +248,6 @@ impl CompactPublicKey {
|
||||
let mut encryption_generator =
|
||||
NoiseRandomGenerator::<DefaultRandomGenerator>::new_from_seed(seed.0);
|
||||
|
||||
self.prepare_cpk_zero_for_rerand_with_generator(&mut encryption_generator, zero_count)
|
||||
}
|
||||
|
||||
pub(crate) fn prepare_cpk_zero_for_rerand_with_generator(
|
||||
&self,
|
||||
encryption_generator: &mut NoiseRandomGenerator<DefaultRandomGenerator>,
|
||||
zero_count: LweCiphertextCount,
|
||||
) -> LweCompactCiphertextList<Vec<u64>> {
|
||||
let mut encryption_of_zero = LweCompactCiphertextList::new(
|
||||
0,
|
||||
self.parameters().encryption_lwe_dimension.to_lwe_size(),
|
||||
@@ -279,7 +268,7 @@ impl CompactPublicKey {
|
||||
&plaintext_list,
|
||||
cpk_encryption_noise_distribution,
|
||||
cpk_encryption_noise_distribution,
|
||||
encryption_generator,
|
||||
&mut encryption_generator,
|
||||
);
|
||||
|
||||
encryption_of_zero
|
||||
@@ -321,7 +310,8 @@ impl CompactPublicKey {
|
||||
KeySwitchingKeyMaterialView.";
|
||||
return Err(crate::error!("{}", err));
|
||||
} else if ksk_output_lwe_size != ct.ct.lwe_size() {
|
||||
let err = "Mismatched LweSize between Ciphertext being re-randomized and provided \
|
||||
let err =
|
||||
"Mismatched LweSwize between Ciphertext being re-randomized and provided \
|
||||
KeySwitchingKeyMaterialView.";
|
||||
return Err(crate::error!("{}", err));
|
||||
} else if ct.noise_level() > NoiseLevel::NOMINAL {
|
||||
@@ -401,7 +391,7 @@ impl CompactPublicKey {
|
||||
|
||||
for ct in cts.iter() {
|
||||
if key_lwe_size != ct.ct.lwe_size() {
|
||||
let err = "Mismatched LweSize between Ciphertexts \
|
||||
let err = "Mismatched LweSwize between Ciphertexts \
|
||||
being re-randomized and provided CompactPublicKey";
|
||||
return Err(crate::error!("{}", err));
|
||||
} else if ct.noise_level() > NoiseLevel::NOMINAL {
|
||||
@@ -427,54 +417,28 @@ impl CompactPublicKey {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Re-randomize compact ciphertext lists using the provided seed.
|
||||
pub fn re_randomize_compact_ciphertext_lists<'a>(
|
||||
&self,
|
||||
compact_lists: impl Iterator<Item = &'a mut CompactCiphertextList>,
|
||||
seed: ReRandomizationSeed,
|
||||
) -> crate::Result<()> {
|
||||
let key_lwe_size = self.key.lwe_dimension().to_lwe_size();
|
||||
let mut encryption_generator =
|
||||
NoiseRandomGenerator::<DefaultRandomGenerator>::new_from_seed(seed.0);
|
||||
|
||||
for list in compact_lists {
|
||||
if key_lwe_size != list.ct_list.lwe_size() {
|
||||
return Err(crate::error!(
|
||||
"Mismatched LweSize between Compact Lists \
|
||||
being re-randomized and provided CompactPublicKey",
|
||||
));
|
||||
}
|
||||
let encryption_of_zero = self.prepare_cpk_zero_for_rerand_with_generator(
|
||||
&mut encryption_generator,
|
||||
list.ct_list.lwe_ciphertext_count(),
|
||||
);
|
||||
lwe_compact_ciphertext_list_add_assign(&mut list.ct_list, &encryption_of_zero);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use rand::Rng;
|
||||
|
||||
use super::*;
|
||||
use crate::shortint::ciphertext::ShortintCompactCiphertextListCastingMode;
|
||||
use crate::shortint::key_switching_key::{KeySwitchingKeyBuildHelper, KeySwitchingKeyMaterial};
|
||||
use crate::shortint::parameters::test_params::*;
|
||||
use crate::shortint::parameters::test_params::{
|
||||
TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2,
|
||||
};
|
||||
use crate::shortint::parameters::{
|
||||
AtomicPatternParameters, CompactPublicKeyEncryptionParameters, ReRandomizationParameters,
|
||||
PARAM_MESSAGE_2_CARRY_2_KS_PBS,
|
||||
};
|
||||
use crate::shortint::{gen_keys, CompactPrivateKey, KeySwitchingKeyView};
|
||||
use crate::shortint::{gen_keys, CompactPrivateKey};
|
||||
|
||||
/// Test the case where we rerand more ciphertexts that what can be stored in one cpk lwe
|
||||
/// Test the trivial case
|
||||
#[test]
|
||||
fn test_rerand_with_dedicated_cpk_ci_run_filter() {
|
||||
let compute_params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let compute_params = PARAM_MESSAGE_2_CARRY_2_KS_PBS;
|
||||
let cpk_params = TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
|
||||
let rerand_ksk_params =
|
||||
TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
@@ -487,7 +451,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_rerand_with_derived_cpk_ci_run_filter() {
|
||||
let compute_params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let compute_params = PARAM_MESSAGE_2_CARRY_2_KS_PBS;
|
||||
let rerand_params = ReRandomizationParameters::DerivedCPKWithoutKeySwitch;
|
||||
|
||||
test_rerand_impl(compute_params.into(), None, rerand_params);
|
||||
@@ -596,125 +560,4 @@ mod test {
|
||||
assert_eq!(dec, 3);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rerand_compact_list_ci_run_filter() {
|
||||
let mut rng = rand::thread_rng();
|
||||
let compute_params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let cpk_params = TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
|
||||
let ks_params = TEST_PARAM_KEYSWITCH_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
const CT_COUNT: usize = 37;
|
||||
|
||||
let (cks, sks) = gen_keys(compute_params);
|
||||
|
||||
let privk = CompactPrivateKey::new(cpk_params);
|
||||
let pubk = CompactPublicKey::new(&privk);
|
||||
|
||||
let ksk_builder = KeySwitchingKeyBuildHelper::new((&privk, None), (&cks, &sks), ks_params);
|
||||
let casting_key: KeySwitchingKeyView<'_> = ksk_builder.as_key_switching_key_view();
|
||||
|
||||
let casting_mode = ShortintCompactCiphertextListCastingMode::CastIfNecessary {
|
||||
casting_key,
|
||||
functions: None,
|
||||
};
|
||||
|
||||
let messages: [u64; CT_COUNT] =
|
||||
core::array::from_fn(|_| rng.gen_range(0..cpk_params.message_modulus.0));
|
||||
let mut enc = pubk.encrypt_slice(&messages);
|
||||
|
||||
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rng.gen());
|
||||
let mut re_rand_context = ReRandomizationContext::new(*b"TFHE_Rrd", *b"TFHE_Enc");
|
||||
|
||||
re_rand_context.add_ciphertext_data_slice(enc.ct_list.as_ref());
|
||||
re_rand_context.add_bytes(&nonce);
|
||||
re_rand_context.add_bytes(b"expand");
|
||||
|
||||
let mut seeder = re_rand_context.finalize();
|
||||
|
||||
pubk.re_randomize_compact_ciphertext_lists(std::iter::once(&mut enc), seeder.next_seed())
|
||||
.unwrap();
|
||||
|
||||
let cast = enc.expand(casting_mode).unwrap();
|
||||
|
||||
assert_eq!(cast.len(), CT_COUNT);
|
||||
for (ct, clear) in cast.iter().zip(&messages) {
|
||||
assert_eq!(cks.decrypt(ct), *clear)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "zk-pok")]
|
||||
#[test]
|
||||
fn test_rerand_proven_compact_list_ci_run_filter() {
|
||||
use crate::zk::{CompactPkeCrs, ZkComputeLoad};
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let compute_params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let cpk_params = TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
|
||||
let ks_params = TEST_PARAM_KEYSWITCH_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
// Make sure that the resulting proven list will be composed of multiple inner compact lists
|
||||
const CT_COUNT: usize = 37;
|
||||
|
||||
let (cks, sks) = gen_keys(compute_params);
|
||||
|
||||
let privk = CompactPrivateKey::new(cpk_params);
|
||||
let pubk = CompactPublicKey::new(&privk);
|
||||
|
||||
let crs = CompactPkeCrs::from_shortint_params(cpk_params, LweCiphertextCount(4)).unwrap();
|
||||
let metadata = [b's', b'h', b'o', b'r', b't', b'i', b'n', b't'];
|
||||
|
||||
let ksk_builder = KeySwitchingKeyBuildHelper::new((&privk, None), (&cks, &sks), ks_params);
|
||||
let casting_key: KeySwitchingKeyView<'_> = ksk_builder.as_key_switching_key_view();
|
||||
|
||||
let id = |x: u64| x;
|
||||
let dyn_id: &(dyn Fn(u64) -> u64 + Sync) = &id;
|
||||
|
||||
let functions = vec![Some(vec![dyn_id; 1]); CT_COUNT];
|
||||
|
||||
let casting_mode = ShortintCompactCiphertextListCastingMode::CastIfNecessary {
|
||||
casting_key,
|
||||
functions: Some(functions.as_slice()),
|
||||
};
|
||||
|
||||
let messages: [u64; CT_COUNT] =
|
||||
core::array::from_fn(|_| rng.gen_range(0..cpk_params.message_modulus.0));
|
||||
let mut enc = pubk
|
||||
.encrypt_and_prove_slice(
|
||||
&messages,
|
||||
&crs,
|
||||
&metadata,
|
||||
ZkComputeLoad::Verify,
|
||||
cpk_params.message_modulus.0,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rng.gen());
|
||||
let mut re_rand_context = ReRandomizationContext::new(*b"TFHE_Rrd", *b"TFHE_Enc");
|
||||
|
||||
re_rand_context.add_ciphertext_data_slice(
|
||||
&enc.proved_lists
|
||||
.iter()
|
||||
.flat_map(|list| list.0.ct_list.as_ref())
|
||||
.copied()
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
re_rand_context.add_bytes(&nonce);
|
||||
re_rand_context.add_bytes(b"expand");
|
||||
|
||||
let mut seeder = re_rand_context.finalize();
|
||||
|
||||
pubk.re_randomize_compact_ciphertext_lists(
|
||||
enc.proved_lists.iter_mut().map(|(list, _)| list),
|
||||
seeder.next_seed(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let cast = enc.expand_without_verification(casting_mode).unwrap();
|
||||
|
||||
assert_eq!(cast.len(), CT_COUNT);
|
||||
for (ct, clear) in cast.iter().zip(&messages) {
|
||||
assert_eq!(cks.decrypt(ct), *clear)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +183,10 @@ impl ProvenCompactCiphertextList {
|
||||
}
|
||||
modes
|
||||
}
|
||||
None => vec![casting_mode; self.proved_lists.len()],
|
||||
None => vec![
|
||||
ShortintCompactCiphertextListCastingMode::NoCasting;
|
||||
self.proved_lists.len()
|
||||
],
|
||||
},
|
||||
ShortintCompactCiphertextListCastingMode::NoCasting => {
|
||||
vec![ShortintCompactCiphertextListCastingMode::NoCasting; self.proved_lists.len()]
|
||||
@@ -358,8 +361,7 @@ mod tests {
|
||||
use crate::conformance::ParameterSetConformant;
|
||||
use crate::core_crypto::prelude::LweCiphertextCount;
|
||||
use crate::shortint::ciphertext::ProvenCompactCiphertextListConformanceParams;
|
||||
use crate::shortint::parameters::test_params::*;
|
||||
use crate::shortint::parameters::ShortintCompactCiphertextListCastingMode;
|
||||
use crate::shortint::parameters::*;
|
||||
use crate::shortint::{
|
||||
ClientKey, CompactPrivateKey, CompactPublicKey, KeySwitchingKey, ServerKey,
|
||||
};
|
||||
@@ -370,9 +372,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_zk_ciphertext_encryption_ci_run_filter() {
|
||||
let params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let pke_params = TEST_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let ksk_params = TEST_PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
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 crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(4)).unwrap();
|
||||
let priv_key = CompactPrivateKey::new(pke_params);
|
||||
@@ -432,9 +434,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_zk_compact_ciphertext_list_encryption_ci_run_filter() {
|
||||
let params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let pke_params = TEST_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let ksk_params = TEST_PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
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 crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(4)).unwrap();
|
||||
let priv_key = CompactPrivateKey::new(pke_params);
|
||||
@@ -483,59 +485,10 @@ mod tests {
|
||||
assert_eq!(msgs, decrypted);
|
||||
}
|
||||
|
||||
/// Test a case where we need to keyswitch to compute params but no functions are applied
|
||||
#[test]
|
||||
fn test_zk_compact_ciphertext_list_encryption_no_fn_ci_run_filter() {
|
||||
let params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let pke_params = TEST_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let ksk_params = TEST_PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(4)).unwrap();
|
||||
let priv_key = CompactPrivateKey::new(pke_params);
|
||||
let pub_key = CompactPublicKey::new(&priv_key);
|
||||
let ck = ClientKey::new(params);
|
||||
let sk = ServerKey::new(&ck);
|
||||
let ksk = KeySwitchingKey::new((&priv_key, None), (&ck, &sk), ksk_params);
|
||||
|
||||
let metadata = [b's', b'h', b'o', b'r', b't', b'i', b'n', b't'];
|
||||
|
||||
let msgs = (0..512)
|
||||
.map(|_| random::<u64>() % params.message_modulus.0)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let proven_ct = pub_key
|
||||
.encrypt_and_prove_slice(
|
||||
&msgs,
|
||||
&crs,
|
||||
&metadata,
|
||||
ZkComputeLoad::Proof,
|
||||
params.message_modulus.0,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(proven_ct.verify(&crs, &pub_key, &metadata).is_valid());
|
||||
|
||||
let expanded = proven_ct
|
||||
.verify_and_expand(
|
||||
&crs,
|
||||
&pub_key,
|
||||
&metadata,
|
||||
ShortintCompactCiphertextListCastingMode::CastIfNecessary {
|
||||
casting_key: ksk.as_view(),
|
||||
functions: None,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let decrypted = expanded
|
||||
.iter()
|
||||
.map(|ciphertext| ck.decrypt(ciphertext))
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(msgs, decrypted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zk_proof_conformance_ci_run_filter() {
|
||||
let params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let pke_params = TEST_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let pke_params = PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let max_lwe_count_per_compact_list = LweCiphertextCount(320);
|
||||
let total_lwe_count = 512;
|
||||
|
||||
@@ -120,13 +120,13 @@ impl NoiseSquashingCompressionKey {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::shortint::ciphertext::{Degree, MaxDegree};
|
||||
use crate::shortint::ciphertext::MaxDegree;
|
||||
use crate::shortint::keycache::KEY_CACHE;
|
||||
use crate::shortint::list_compression::private_key::NoiseSquashingCompressionPrivateKey;
|
||||
use crate::shortint::noise_squashing::{
|
||||
NoiseSquashingKey, NoiseSquashingPrivateKey, NoiseSquashingPrivateKeyView,
|
||||
};
|
||||
use crate::shortint::parameters::test_params::*;
|
||||
use crate::shortint::parameters::*;
|
||||
|
||||
use rand::prelude::*;
|
||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||
@@ -134,15 +134,15 @@ mod test {
|
||||
#[test]
|
||||
fn test_noise_squashing_compression_ci_run_filter() {
|
||||
let keycache_entry =
|
||||
KEY_CACHE.get_from_param(TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128);
|
||||
KEY_CACHE.get_from_param(PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128);
|
||||
let (cks, sks) = (keycache_entry.client_key(), keycache_entry.server_key());
|
||||
let noise_squashing_private_key = NoiseSquashingPrivateKey::new(
|
||||
TEST_PARAM_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
);
|
||||
let noise_squashing_key = NoiseSquashingKey::new(cks, &noise_squashing_private_key);
|
||||
|
||||
let compression_private_key = NoiseSquashingCompressionPrivateKey::new(
|
||||
TEST_PARAM_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
);
|
||||
|
||||
let compression_key = noise_squashing_private_key
|
||||
@@ -152,8 +152,7 @@ mod test {
|
||||
|
||||
let id_lut = sks.generate_lookup_table(|x| x);
|
||||
let max_ct_count =
|
||||
TEST_PARAM_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128
|
||||
.lwe_per_glwe;
|
||||
NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128.lwe_per_glwe;
|
||||
|
||||
for ct_count in [0, 1, max_ct_count.0] {
|
||||
// Generate random msgs
|
||||
|
||||
@@ -2,7 +2,6 @@ use crate::shortint::keycache::KEY_CACHE;
|
||||
use crate::shortint::noise_squashing::{
|
||||
CompressedNoiseSquashingKey, NoiseSquashingKey, NoiseSquashingPrivateKey,
|
||||
};
|
||||
use crate::shortint::parameters::test_params::*;
|
||||
use crate::shortint::parameters::*;
|
||||
use rand::prelude::*;
|
||||
use rand::thread_rng;
|
||||
@@ -10,15 +9,15 @@ use rand::thread_rng;
|
||||
#[test]
|
||||
fn test_classic_noise_squashing_ci_run_filter() {
|
||||
test_noise_squashing(
|
||||
TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
TEST_PARAM_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multi_bit_noise_squashing_ci_run_filter() {
|
||||
test_noise_squashing(
|
||||
TEST_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
NOISE_SQUASHING_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
);
|
||||
}
|
||||
@@ -26,8 +25,8 @@ fn test_multi_bit_noise_squashing_ci_run_filter() {
|
||||
#[test]
|
||||
fn test_ks32_noise_squashing_ci_run_filter() {
|
||||
test_noise_squashing(
|
||||
TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128,
|
||||
TEST_PARAM_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128,
|
||||
NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -342,13 +342,11 @@ pub(crate) mod test {
|
||||
#[test]
|
||||
fn oprf_compare_plain_ci_run_filter() {
|
||||
use crate::shortint::gen_keys;
|
||||
use crate::shortint::parameters::test_params::{
|
||||
TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128,
|
||||
TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
};
|
||||
use crate::shortint::parameters::test_params::TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128;
|
||||
use crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
|
||||
|
||||
for params in [
|
||||
ShortintParameterSet::from(TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128),
|
||||
ShortintParameterSet::from(PARAM_MESSAGE_2_CARRY_2_KS_PBS),
|
||||
ShortintParameterSet::from(TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128),
|
||||
] {
|
||||
let (ck, sk) = gen_keys(params);
|
||||
@@ -449,15 +447,15 @@ pub(crate) mod test {
|
||||
use crate::shortint::gen_keys;
|
||||
use crate::shortint::parameters::test_params::{
|
||||
TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128,
|
||||
TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
TEST_PARAM_MULTI_BIT_GROUP_3_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128,
|
||||
};
|
||||
use crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
|
||||
|
||||
for params in [
|
||||
ShortintParameterSet::from(
|
||||
TEST_PARAM_MULTI_BIT_GROUP_3_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128,
|
||||
),
|
||||
ShortintParameterSet::from(TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128),
|
||||
ShortintParameterSet::from(PARAM_MESSAGE_2_CARRY_2_KS_PBS),
|
||||
ShortintParameterSet::from(TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128),
|
||||
] {
|
||||
let (ck, sk) = gen_keys(params);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use super::aliases::*;
|
||||
use super::current_params::meta::cpu::*;
|
||||
use super::current_params::meta::gpu::*;
|
||||
use super::current_params::*;
|
||||
@@ -86,7 +85,7 @@ pub const TEST_PARAM_MESSAGE_4_CARRY_4_COMPACT_PK_PBS_KS_GAUSSIAN_2M128: Classic
|
||||
pub const TEST_PARAM_MESSAGE_1_CARRY_1_KS_PBS_GAUSSIAN_2M64: ClassicPBSParameters =
|
||||
V1_6_PARAM_MESSAGE_1_CARRY_1_KS_PBS_GAUSSIAN_2M64;
|
||||
pub const TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M64: ClassicPBSParameters =
|
||||
PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M64;
|
||||
V1_6_PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M64;
|
||||
pub const TEST_PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M64: ClassicPBSParameters =
|
||||
V1_6_PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M64;
|
||||
pub const TEST_PARAM_MESSAGE_4_CARRY_4_KS_PBS_GAUSSIAN_2M64: ClassicPBSParameters =
|
||||
@@ -110,7 +109,7 @@ pub const TEST_PARAM_MESSAGE_1_CARRY_7_KS_PBS_GAUSSIAN_2M128: ClassicPBSParamete
|
||||
pub const TEST_PARAM_MESSAGE_2_CARRY_1_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
|
||||
V1_6_PARAM_MESSAGE_2_CARRY_1_KS_PBS_GAUSSIAN_2M128;
|
||||
pub const TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
|
||||
PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
|
||||
V1_6_PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
|
||||
pub const TEST_PARAM_MESSAGE_2_CARRY_3_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
|
||||
V1_6_PARAM_MESSAGE_2_CARRY_3_KS_PBS_GAUSSIAN_2M128;
|
||||
pub const TEST_PARAM_MESSAGE_2_CARRY_4_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
|
||||
@@ -124,7 +123,7 @@ pub const TEST_PARAM_MESSAGE_3_CARRY_1_KS_PBS_GAUSSIAN_2M128: ClassicPBSParamete
|
||||
pub const TEST_PARAM_MESSAGE_3_CARRY_2_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
|
||||
V1_6_PARAM_MESSAGE_3_CARRY_2_KS_PBS_GAUSSIAN_2M128;
|
||||
pub const TEST_PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
|
||||
PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
|
||||
V1_6_PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
|
||||
pub const TEST_PARAM_MESSAGE_3_CARRY_4_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
|
||||
V1_6_PARAM_MESSAGE_3_CARRY_4_KS_PBS_GAUSSIAN_2M128;
|
||||
pub const TEST_PARAM_MESSAGE_3_CARRY_5_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
|
||||
@@ -154,7 +153,7 @@ pub const TEST_PARAM_MESSAGE_2_CARRY_2_PBS_KS_GAUSSIAN_2M128: ClassicPBSParamete
|
||||
|
||||
// KS PBS TUniform
|
||||
pub const TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128: ClassicPBSParameters =
|
||||
PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
V1_6_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
// MultiBit
|
||||
// CPU Gaussian
|
||||
@@ -180,7 +179,8 @@ pub const TEST_PARAM_GPU_MULTI_BIT_GROUP_3_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M6
|
||||
|
||||
// GPU TUniform
|
||||
pub const TEST_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
|
||||
MultiBitPBSParameters = PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
MultiBitPBSParameters =
|
||||
V1_6_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
// PKE ZK V1
|
||||
pub const TEST_PARAM_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV1:
|
||||
@@ -189,7 +189,7 @@ pub const TEST_PARAM_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV1:
|
||||
|
||||
// PKE ZK V2
|
||||
pub const TEST_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
|
||||
CompactPublicKeyEncryptionParameters = PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
CompactPublicKeyEncryptionParameters = V1_6_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
pub const TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2:
|
||||
CompactPublicKeyEncryptionParameters =
|
||||
V1_6_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
|
||||
@@ -202,13 +202,14 @@ pub const TEST_PARAM_KEYSWITCH_1_1_KS_PBS_TO_2_2_KS_PBS_GAUSSIAN_2M128:
|
||||
ShortintKeySwitchingParameters = V1_6_PARAM_KEYSWITCH_1_1_KS_PBS_TO_2_2_KS_PBS_GAUSSIAN_2M128;
|
||||
|
||||
pub const TEST_PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
|
||||
ShortintKeySwitchingParameters = PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
ShortintKeySwitchingParameters = V1_6_PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
pub const TEST_PARAM_KEYSWITCH_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
|
||||
ShortintKeySwitchingParameters =
|
||||
PARAM_KEYSWITCH_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
V1_6_PARAM_KEYSWITCH_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
pub const TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
|
||||
ShortintKeySwitchingParameters = PARAM_KEYSWITCH_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
ShortintKeySwitchingParameters =
|
||||
V1_6_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
// ZKV1
|
||||
pub const TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV1:
|
||||
ShortintKeySwitchingParameters =
|
||||
@@ -216,21 +217,21 @@ pub const TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M12
|
||||
|
||||
// Compression
|
||||
pub const TEST_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128: CompressionParameters =
|
||||
COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
V1_6_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
pub const TEST_COMP_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
|
||||
CompressionParameters =
|
||||
COMP_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
V1_6_COMP_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
// KS32 PBS AP
|
||||
pub const TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128: KeySwitch32PBSParameters =
|
||||
PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128;
|
||||
V1_6_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128;
|
||||
|
||||
pub const TEST_PARAM_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
|
||||
NoiseSquashingCompressionParameters =
|
||||
NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
V1_6_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
pub const TEST_PARAM_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
|
||||
NoiseSquashingParameters = NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
NoiseSquashingParameters = V1_6_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
// Meta params
|
||||
pub const TEST_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_SMALL_ZKV2_TUNIFORM_2M128: MetaParameters =
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::shortint::ciphertext::NoiseLevel;
|
||||
use crate::shortint::keycache::KEY_CACHE;
|
||||
use crate::shortint::parameters::test_params::TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
use crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
|
||||
use crate::shortint::{Ciphertext, MaxNoiseLevel, ServerKey};
|
||||
|
||||
fn test_ct_unary_op_noise_level_propagation(sk: &ServerKey, ct: &Ciphertext) {
|
||||
@@ -319,7 +319,7 @@ fn test_ct_scalar_op_assign_noise_level_propagation(sk: &ServerKey, ct: &Ciphert
|
||||
#[cfg(not(tarpaulin))] // This test is ignored in coverage, it takes around 4 hours to run otherwise.
|
||||
#[test]
|
||||
fn test_noise_level_propagation_ci_run_filter() {
|
||||
let params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let params = PARAM_MESSAGE_2_CARRY_2_KS_PBS;
|
||||
|
||||
let keys = KEY_CACHE.get_from_param(params);
|
||||
let (ck, sk) = (keys.client_key(), keys.server_key());
|
||||
|
||||
@@ -46,15 +46,6 @@ impl Named for CompactPkeProof {
|
||||
const NAME: &'static str = "zk::CompactPkeProof";
|
||||
}
|
||||
|
||||
impl CompactPkeProof {
|
||||
pub fn to_le_bytes(&self) -> Vec<u8> {
|
||||
match self {
|
||||
Self::PkeV1(proof) => proof.to_le_bytes(),
|
||||
Self::PkeV2(proof) => proof.to_le_bytes(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
/// Used to specify the kind of proofs that are allowed to be checked by the verifier.
|
||||
///
|
||||
|
||||
@@ -6,10 +6,47 @@ mod traits;
|
||||
pub use backend::Backend;
|
||||
pub use bench_crate::BenchCrate;
|
||||
use serde::Serialize;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::{env, fmt};
|
||||
pub use tfhe::hlapi::HlapiBench;
|
||||
pub use tfhe::{HlIntegerOp, TfheLayer};
|
||||
|
||||
use crate::tfhe::hlapi::dex::Dex;
|
||||
use crate::tfhe::hlapi::erc7984::Erc7984;
|
||||
|
||||
pub struct TestResult {
|
||||
file: File,
|
||||
}
|
||||
|
||||
impl TestResult {
|
||||
pub fn new(file_name: &str) -> Self {
|
||||
let file_path = Path::new(file_name);
|
||||
Self::from_path(file_path)
|
||||
}
|
||||
|
||||
pub fn from_path(path: &Path) -> Self {
|
||||
if !path.exists() {
|
||||
if let Some(parent) = path.parent() {
|
||||
std::fs::create_dir_all(parent).expect("cannot create parent dirs");
|
||||
}
|
||||
File::create(path).expect("cannot create result file");
|
||||
}
|
||||
let file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(path)
|
||||
.expect("cannot open result file");
|
||||
Self { file }
|
||||
}
|
||||
|
||||
pub fn write_result(&mut self, name: &str, value: usize) {
|
||||
let line = format!("{name},{value}\n");
|
||||
let error_message = format!("cannot write {name} result into file");
|
||||
self.file.write_all(line.as_bytes()).expect(&error_message);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub enum OperandType {
|
||||
CipherText,
|
||||
@@ -22,14 +59,36 @@ impl OperandType {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
/// Benchmark type driven by the `__TFHE_RS_BENCH_TYPE` environment variable.
|
||||
///
|
||||
/// Only `Latency` and `Throughput` can come from the environment; `PbsCount`
|
||||
/// is hard-coded at specific call sites.
|
||||
#[derive(Clone, Copy, Serialize)]
|
||||
pub enum BenchmarkType {
|
||||
Latency,
|
||||
Throughput,
|
||||
}
|
||||
|
||||
/// The metric being recorded by a benchmark, used in [`BenchmarkSpec`].
|
||||
#[derive(Clone, Copy, Serialize)]
|
||||
pub enum BenchmarkMetric {
|
||||
Latency,
|
||||
Throughput,
|
||||
PbsCount,
|
||||
}
|
||||
|
||||
impl From<BenchmarkType> for BenchmarkMetric {
|
||||
fn from(ct: BenchmarkType) -> Self {
|
||||
match ct {
|
||||
BenchmarkType::Latency => BenchmarkMetric::Latency,
|
||||
BenchmarkType::Throughput => BenchmarkMetric::Throughput,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BenchmarkType {
|
||||
pub fn from_env() -> Result<Self, String> {
|
||||
/// Retrieves the benchmark type from the environment variable `__TFHE_RS_BENCH_TYPE`.
|
||||
fn from_env() -> Result<Self, String> {
|
||||
let raw_value = env::var("__TFHE_RS_BENCH_TYPE").unwrap_or("latency".to_string());
|
||||
match raw_value.to_lowercase().as_str() {
|
||||
"latency" => Ok(BenchmarkType::Latency),
|
||||
@@ -39,6 +98,9 @@ impl BenchmarkType {
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the benchmark type from the environment variable `__TFHE_RS_BENCH_TYPE`.
|
||||
///
|
||||
/// Returns only `Latency` or `Throughput` — never `PbsCount`.
|
||||
pub fn get_bench_type() -> &'static BenchmarkType {
|
||||
use std::sync::OnceLock;
|
||||
static BENCH_TYPE: OnceLock<BenchmarkType> = OnceLock::new();
|
||||
@@ -48,7 +110,7 @@ pub fn get_bench_type() -> &'static BenchmarkType {
|
||||
/// Enforces the naming convention for benchmark IDs.
|
||||
///
|
||||
/// ```text
|
||||
/// {crate}::{layer}::{bench}::{op}(::{backend})?(::throughput)?::{param}(::scalar)?(::{type})?
|
||||
/// {crate}::{layer}::{bench}::{op}(::{backend})?(::{benchmark_type})?::{param}(::scalar)?(::{type})?(::{num_elements}_elements)?
|
||||
/// ```
|
||||
///
|
||||
/// `param_name` and `type_name` are kept as `&str` because their values
|
||||
@@ -60,7 +122,8 @@ pub struct BenchmarkSpec<'a> {
|
||||
pub param_name: &'a str,
|
||||
pub operand_type: &'a OperandType,
|
||||
pub type_name: Option<&'a str>,
|
||||
pub bench_type: &'a BenchmarkType,
|
||||
pub bench_type: BenchmarkMetric,
|
||||
pub num_elements: Option<usize>,
|
||||
}
|
||||
|
||||
impl<'a> BenchmarkSpec<'a> {
|
||||
@@ -70,7 +133,8 @@ impl<'a> BenchmarkSpec<'a> {
|
||||
param_name: &'a str,
|
||||
operand_type: &'a OperandType,
|
||||
type_name: Option<&'a str>,
|
||||
bench_type: &'a BenchmarkType,
|
||||
bench_type: impl Into<BenchmarkMetric>,
|
||||
num_elements: Option<usize>,
|
||||
) -> Self {
|
||||
Self {
|
||||
bench_crate,
|
||||
@@ -78,16 +142,17 @@ impl<'a> BenchmarkSpec<'a> {
|
||||
param_name,
|
||||
operand_type,
|
||||
type_name,
|
||||
bench_type,
|
||||
bench_type: bench_type.into(),
|
||||
num_elements,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_hlapi(
|
||||
pub fn new_hlapi_ops(
|
||||
hlapi_op: HlIntegerOp,
|
||||
param_name: &'a str,
|
||||
operand_type: &'a OperandType,
|
||||
type_name: Option<&'a str>,
|
||||
bench_type: &'a BenchmarkType,
|
||||
bench_type: impl Into<BenchmarkMetric>,
|
||||
backend: Backend,
|
||||
) -> Self {
|
||||
Self {
|
||||
@@ -96,7 +161,47 @@ impl<'a> BenchmarkSpec<'a> {
|
||||
param_name,
|
||||
operand_type,
|
||||
type_name,
|
||||
bench_type,
|
||||
bench_type: bench_type.into(),
|
||||
num_elements: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_hlapi_erc7984(
|
||||
hlapi_erc7984_op: Erc7984,
|
||||
param_name: &'a str,
|
||||
operand_type: &'a OperandType,
|
||||
type_name: Option<&'a str>,
|
||||
bench_type: impl Into<BenchmarkMetric>,
|
||||
backend: Backend,
|
||||
num_elements: Option<usize>,
|
||||
) -> Self {
|
||||
Self {
|
||||
bench_crate: BenchCrate::Tfhe(TfheLayer::Hlapi(HlapiBench::Erc7984(hlapi_erc7984_op))),
|
||||
backend,
|
||||
param_name,
|
||||
operand_type,
|
||||
type_name,
|
||||
bench_type: bench_type.into(),
|
||||
num_elements,
|
||||
}
|
||||
}
|
||||
pub fn new_hlapi_dex(
|
||||
hlapi_dex: Dex,
|
||||
param_name: &'a str,
|
||||
operand_type: &'a OperandType,
|
||||
type_name: Option<&'a str>,
|
||||
bench_type: impl Into<BenchmarkMetric>,
|
||||
backend: Backend,
|
||||
num_elements: Option<usize>,
|
||||
) -> Self {
|
||||
Self {
|
||||
bench_crate: BenchCrate::Tfhe(TfheLayer::Hlapi(HlapiBench::Dex(hlapi_dex))),
|
||||
backend,
|
||||
param_name,
|
||||
operand_type,
|
||||
type_name,
|
||||
bench_type: bench_type.into(),
|
||||
num_elements,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,8 +212,10 @@ impl fmt::Display for BenchmarkSpec<'_> {
|
||||
if !matches!(self.backend, Backend::Cpu) {
|
||||
write!(f, "::{}", self.backend)?;
|
||||
}
|
||||
if matches!(self.bench_type, BenchmarkType::Throughput) {
|
||||
write!(f, "::throughput")?;
|
||||
match self.bench_type {
|
||||
BenchmarkMetric::Throughput => write!(f, "::throughput")?,
|
||||
BenchmarkMetric::PbsCount => write!(f, "::pbs_count")?,
|
||||
BenchmarkMetric::Latency => {}
|
||||
}
|
||||
write!(f, "::{}", self.param_name)?;
|
||||
if self.operand_type.is_scalar() {
|
||||
@@ -117,6 +224,9 @@ impl fmt::Display for BenchmarkSpec<'_> {
|
||||
if let Some(type_name) = self.type_name {
|
||||
write!(f, "::{type_name}")?;
|
||||
}
|
||||
if let Some(num_elements) = self.num_elements {
|
||||
write!(f, "::{num_elements}_elements")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -133,7 +243,8 @@ mod tests {
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::CipherText,
|
||||
Some("FheUint64"),
|
||||
&BenchmarkType::Latency,
|
||||
BenchmarkMetric::Latency,
|
||||
None,
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
@@ -149,7 +260,8 @@ mod tests {
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::CipherText,
|
||||
Some("FheUint128"),
|
||||
&BenchmarkType::Latency,
|
||||
BenchmarkMetric::Latency,
|
||||
None,
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
@@ -165,7 +277,8 @@ mod tests {
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::CipherText,
|
||||
Some("FheUint64"),
|
||||
&BenchmarkType::Throughput,
|
||||
BenchmarkMetric::Throughput,
|
||||
None,
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
@@ -181,7 +294,8 @@ mod tests {
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::PlainText,
|
||||
Some("FheUint64"),
|
||||
&BenchmarkType::Latency,
|
||||
BenchmarkMetric::Latency,
|
||||
None,
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
@@ -197,11 +311,164 @@ mod tests {
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::CipherText,
|
||||
None,
|
||||
&BenchmarkType::Latency,
|
||||
BenchmarkMetric::Latency,
|
||||
None,
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
"tfhe::hlapi::ops::neg::PARAM_MESSAGE_2_CARRY_2"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hlapi_erc7984_with_num_elements() {
|
||||
use crate::tfhe::hlapi::erc7984::TransferFlavor;
|
||||
|
||||
let spec = BenchmarkSpec::new_hlapi_erc7984(
|
||||
Erc7984::Transfer(TransferFlavor::Whitepaper),
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::CipherText,
|
||||
None,
|
||||
BenchmarkMetric::Latency,
|
||||
Backend::Cpu,
|
||||
Some(10),
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
"tfhe::hlapi::erc7984::transfer::whitepaper::PARAM_MESSAGE_2_CARRY_2::10_elements"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hlapi_erc7984_without_num_elements() {
|
||||
use crate::tfhe::hlapi::erc7984::TransferFlavor;
|
||||
|
||||
let spec = BenchmarkSpec::new_hlapi_erc7984(
|
||||
Erc7984::Transfer(TransferFlavor::NoCmux),
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::CipherText,
|
||||
None,
|
||||
BenchmarkMetric::Latency,
|
||||
Backend::Cpu,
|
||||
None,
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
"tfhe::hlapi::erc7984::transfer::no_cmux::PARAM_MESSAGE_2_CARRY_2"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hlapi_erc7984_num_elements_with_backend() {
|
||||
use crate::tfhe::hlapi::erc7984::TransferFlavor;
|
||||
|
||||
let spec = BenchmarkSpec::new_hlapi_erc7984(
|
||||
Erc7984::Transfer(TransferFlavor::Overflow),
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::CipherText,
|
||||
None,
|
||||
BenchmarkMetric::Latency,
|
||||
Backend::Cuda,
|
||||
Some(5),
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
"tfhe::hlapi::erc7984::transfer::overflow::cuda::PARAM_MESSAGE_2_CARRY_2::5_elements"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hlapi_erc7984_num_elements_with_throughput() {
|
||||
use crate::tfhe::hlapi::erc7984::TransferFlavor;
|
||||
|
||||
let spec = BenchmarkSpec::new_hlapi_erc7984(
|
||||
Erc7984::Transfer(TransferFlavor::Safe),
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::CipherText,
|
||||
None,
|
||||
BenchmarkMetric::Throughput,
|
||||
Backend::Cpu,
|
||||
Some(20),
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
"tfhe::hlapi::erc7984::transfer::safe::throughput::PARAM_MESSAGE_2_CARRY_2::20_elements"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hlapi_erc7984_with_pbs_count() {
|
||||
use crate::tfhe::hlapi::erc7984::TransferFlavor;
|
||||
|
||||
let spec = BenchmarkSpec::new_hlapi_erc7984(
|
||||
Erc7984::Transfer(TransferFlavor::Safe),
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::CipherText,
|
||||
None,
|
||||
BenchmarkMetric::PbsCount,
|
||||
Backend::Cpu,
|
||||
None,
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
"tfhe::hlapi::erc7984::transfer::safe::pbs_count::PARAM_MESSAGE_2_CARRY_2"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hlapi_dex_swap_request_latency() {
|
||||
use crate::tfhe::hlapi::dex::DexFlavor;
|
||||
|
||||
let spec = BenchmarkSpec::new_hlapi_dex(
|
||||
Dex::SwapRequest(DexFlavor::Whitepaper),
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::CipherText,
|
||||
Some("FheUint64"),
|
||||
BenchmarkMetric::Latency,
|
||||
Backend::Cpu,
|
||||
None,
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
"tfhe::hlapi::dex::swap_request::whitepaper::PARAM_MESSAGE_2_CARRY_2::FheUint64"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hlapi_dex_swap_claim_throughput_with_elements() {
|
||||
use crate::tfhe::hlapi::dex::DexFlavor;
|
||||
|
||||
let spec = BenchmarkSpec::new_hlapi_dex(
|
||||
Dex::SwapClaim(DexFlavor::NoCmux),
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::CipherText,
|
||||
Some("FheUint64"),
|
||||
BenchmarkMetric::Throughput,
|
||||
Backend::Cuda,
|
||||
Some(10),
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
"tfhe::hlapi::dex::swap_claim::no_cmux::cuda::throughput::PARAM_MESSAGE_2_CARRY_2::FheUint64::10_elements"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hlapi_dex_with_pbs_count() {
|
||||
use crate::tfhe::hlapi::dex::DexFlavor;
|
||||
|
||||
let spec = BenchmarkSpec::new_hlapi_dex(
|
||||
Dex::SwapRequest(DexFlavor::Finalize),
|
||||
"PARAM_MESSAGE_2_CARRY_2",
|
||||
&OperandType::CipherText,
|
||||
Some("FheUint64"),
|
||||
BenchmarkMetric::PbsCount,
|
||||
Backend::Cpu,
|
||||
None,
|
||||
);
|
||||
assert_eq!(
|
||||
spec.to_string(),
|
||||
"tfhe::hlapi::dex::swap_request::finalize::pbs_count::PARAM_MESSAGE_2_CARRY_2::FheUint64"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
37
utils/benchmark_spec/src/tfhe/hlapi/dex.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use core::fmt;
|
||||
|
||||
use strum::Display;
|
||||
|
||||
use crate::traits::SpecFmt;
|
||||
|
||||
/// DEX (decentralized exchange) benchmark operations for the HLAPI layer.
|
||||
#[derive(Clone, Copy, Display)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum Dex {
|
||||
SwapRequest(DexFlavor),
|
||||
SwapClaim(DexFlavor),
|
||||
}
|
||||
|
||||
impl Dex {
|
||||
fn op(&self) -> &dyn fmt::Display {
|
||||
match self {
|
||||
Dex::SwapRequest(op) => op,
|
||||
Dex::SwapClaim(op) => op,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecFmt for Dex {
|
||||
fn fmt_spec(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "::{}::{}", self, self.op())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Display)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum DexFlavor {
|
||||
Whitepaper,
|
||||
NoCmux,
|
||||
Prepare,
|
||||
Finalize,
|
||||
}
|
||||
37
utils/benchmark_spec/src/tfhe/hlapi/erc7984.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use core::fmt;
|
||||
|
||||
use strum::Display;
|
||||
|
||||
use crate::traits::SpecFmt;
|
||||
|
||||
/// ERC-7984 token transfer benchmark operations for the HLAPI layer.
|
||||
#[derive(Clone, Copy, Display)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum Erc7984 {
|
||||
Transfer(TransferFlavor),
|
||||
}
|
||||
|
||||
impl Erc7984 {
|
||||
fn op(&self) -> &dyn fmt::Display {
|
||||
match self {
|
||||
Erc7984::Transfer(op) => op,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecFmt for Erc7984 {
|
||||
fn fmt_spec(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "::{}::{}", self, self.op())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Display)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum TransferFlavor {
|
||||
Whitepaper,
|
||||
NoCmux,
|
||||
Overflow,
|
||||
Safe,
|
||||
HpuOptim,
|
||||
HpuSimd,
|
||||
}
|
||||
@@ -1,3 +1,8 @@
|
||||
pub mod dex;
|
||||
pub mod erc7984;
|
||||
|
||||
use dex::Dex;
|
||||
use erc7984::Erc7984;
|
||||
use std::fmt;
|
||||
use strum::Display;
|
||||
|
||||
@@ -17,18 +22,23 @@ pub use super::hl_integer_op::HlIntegerOp;
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum HlapiBench {
|
||||
Ops(HlIntegerOp),
|
||||
Erc7984(Erc7984),
|
||||
Dex(Dex),
|
||||
}
|
||||
|
||||
impl HlapiBench {
|
||||
fn op(&self) -> &dyn fmt::Display {
|
||||
fn op(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
HlapiBench::Ops(op) => op,
|
||||
HlapiBench::Ops(op) => write!(f, "::{op}"),
|
||||
HlapiBench::Erc7984(op) => op.fmt_spec(f),
|
||||
HlapiBench::Dex(op) => op.fmt_spec(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SpecFmt for HlapiBench {
|
||||
fn fmt_spec(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "::{}::{}", self, self.op())
|
||||
write!(f, "::{}", self)?;
|
||||
self.op(f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::process::ExitCode;
|
||||
@@ -376,15 +375,6 @@ impl Registry {
|
||||
fn diff_enum(old_enum: &EnumSnapshot, new_enum: &EnumSnapshot, entries: &mut Vec<DiffEntry>) {
|
||||
let name = &old_enum.enum_name;
|
||||
|
||||
let mut rename_map: HashMap<&str, &str> = HashMap::new();
|
||||
for ov in &old_enum.variants {
|
||||
if let Some(nv) = new_enum.variants.iter().find(|nv| nv.index == ov.index) {
|
||||
if ov.inner_type_def_path != nv.inner_type_def_path {
|
||||
rename_map.insert(&ov.inner_type_def_path, &nv.inner_type_def_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Variant additions & modifications
|
||||
for nv in &new_enum.variants {
|
||||
match old_enum.variants.iter().find(|ov| ov.index == nv.index) {
|
||||
@@ -406,11 +396,7 @@ impl Registry {
|
||||
// Upgrade additions & modifications
|
||||
for nu in &new_enum.upgrades {
|
||||
match old_enum.upgrades.iter().find(|ou| {
|
||||
let resolved_target = rename_map
|
||||
.get(ou.target_def_path.as_str())
|
||||
.copied()
|
||||
.unwrap_or(ou.target_def_path.as_str());
|
||||
ou.source_def_path == nu.source_def_path && resolved_target == nu.target_def_path
|
||||
ou.source_def_path == nu.source_def_path && ou.target_def_path == nu.target_def_path
|
||||
}) {
|
||||
None => entries.push(DiffEntry::upgrade_added(name, nu)),
|
||||
Some(ou) if ou.body_hash != nu.body_hash => {
|
||||
@@ -423,11 +409,7 @@ impl Registry {
|
||||
// Upgrade removals
|
||||
for ou in &old_enum.upgrades {
|
||||
if !new_enum.upgrades.iter().any(|nu| {
|
||||
let resolved_target = rename_map
|
||||
.get(ou.target_def_path.as_str())
|
||||
.copied()
|
||||
.unwrap_or(ou.target_def_path.as_str());
|
||||
nu.source_def_path == ou.source_def_path && resolved_target == nu.target_def_path
|
||||
nu.source_def_path == ou.source_def_path && nu.target_def_path == ou.target_def_path
|
||||
}) {
|
||||
entries.push(DiffEntry::upgrade_removed(name, ou));
|
||||
}
|
||||
@@ -694,110 +676,6 @@ mod tests {
|
||||
assert_eq!(count_by_severity(&entries, Severity::Error), 0);
|
||||
}
|
||||
|
||||
// ---- upgrade target rename (adding a new enum version) ----
|
||||
|
||||
/// Simulates adding V2 to an enum: Foo (at V1) becomes FooV1, new Foo is V2.
|
||||
/// The existing upgrade FooV0 → Foo should be recognized as FooV0 → FooV1
|
||||
/// (same upgrade, just renamed target) and NOT produce a false UpgradeRemoved + UpgradeAdded.
|
||||
#[test]
|
||||
fn no_false_positive_when_new_version_renames_target() {
|
||||
// Before: V0(FooV0), V1(Foo) with upgrade FooV0 → Foo
|
||||
let old = registry(vec![enum_snap(
|
||||
"FooVersions",
|
||||
vec![variant(0, "FooV0", "aaa"), variant(1, "Foo", "bbb")],
|
||||
vec![upgrade("FooV0", "Foo", "uuu")],
|
||||
)]);
|
||||
// After: V0(FooV0), V1(FooV1), V2(Foo) with upgrades FooV0 → FooV1, FooV1 → Foo
|
||||
let new = registry(vec![enum_snap(
|
||||
"FooVersions",
|
||||
vec![
|
||||
variant(0, "FooV0", "aaa"),
|
||||
variant(1, "FooV1", "bbb"), // same hash, just renamed
|
||||
variant(2, "Foo", "ccc"),
|
||||
],
|
||||
vec![
|
||||
upgrade("FooV0", "FooV1", "uuu"), // same body hash as the old FooV0 → Foo
|
||||
upgrade("FooV1", "Foo", "vvv"), // genuinely new upgrade
|
||||
],
|
||||
)]);
|
||||
|
||||
let entries = old.diff(&new);
|
||||
|
||||
// Expected: new variant V2 + new upgrade FooV1→Foo = 2 neutral, 0 warnings, 0 errors
|
||||
assert_eq!(count_by_severity(&entries, Severity::Neutral), 2);
|
||||
assert_eq!(count_by_severity(&entries, Severity::Warning), 0);
|
||||
assert_eq!(count_by_severity(&entries, Severity::Error), 0);
|
||||
|
||||
// Verify the 2 neutral entries are exactly: variant added + upgrade added
|
||||
assert!(
|
||||
entries
|
||||
.iter()
|
||||
.any(|e| matches!(e, DiffEntry::VersionsDispatchVariantAdded { index: 2, .. }))
|
||||
);
|
||||
assert!(entries.iter().any(|e| matches!(
|
||||
e,
|
||||
DiffEntry::UpgradeAdded {
|
||||
source,
|
||||
target,
|
||||
..
|
||||
} if source == "FooV1" && target == "Foo"
|
||||
)));
|
||||
}
|
||||
|
||||
/// Same scenario but the upgrade body also changed — should produce a hash-changed warning
|
||||
/// instead of a false removed+added pair.
|
||||
#[test]
|
||||
fn renamed_target_with_changed_upgrade_body() {
|
||||
let old = registry(vec![enum_snap(
|
||||
"FooVersions",
|
||||
vec![variant(0, "FooV0", "aaa"), variant(1, "Foo", "bbb")],
|
||||
vec![upgrade("FooV0", "Foo", "uuu")],
|
||||
)]);
|
||||
let new = registry(vec![enum_snap(
|
||||
"FooVersions",
|
||||
vec![
|
||||
variant(0, "FooV0", "aaa"),
|
||||
variant(1, "FooV1", "bbb"),
|
||||
variant(2, "Foo", "ccc"),
|
||||
],
|
||||
vec![
|
||||
upgrade("FooV0", "FooV1", "CHANGED"), // same logical upgrade, body changed
|
||||
upgrade("FooV1", "Foo", "vvv"),
|
||||
],
|
||||
)]);
|
||||
|
||||
let entries = old.diff(&new);
|
||||
|
||||
// The renamed upgrade has a changed body → 1 warning (UpgradeHashChanged)
|
||||
// New variant + new upgrade → 2 neutral
|
||||
assert_eq!(count_by_severity(&entries, Severity::Neutral), 2);
|
||||
assert_eq!(count_by_severity(&entries, Severity::Warning), 1);
|
||||
assert_eq!(count_by_severity(&entries, Severity::Error), 0);
|
||||
assert!(
|
||||
entries
|
||||
.iter()
|
||||
.any(|e| matches!(e, DiffEntry::UpgradeHashChanged { .. }))
|
||||
);
|
||||
}
|
||||
|
||||
/// When no rename happens (target name is stable), upgrades still match normally.
|
||||
#[test]
|
||||
fn no_rename_upgrades_still_match() {
|
||||
let old = registry(vec![enum_snap(
|
||||
"E",
|
||||
vec![variant(0, "V0", "aaa"), variant(1, "V1", "bbb")],
|
||||
vec![upgrade("V0", "V1", "uuu")],
|
||||
)]);
|
||||
let new = registry(vec![enum_snap(
|
||||
"E",
|
||||
vec![variant(0, "V0", "aaa"), variant(1, "V1", "bbb")],
|
||||
vec![upgrade("V0", "V1", "uuu")],
|
||||
)]);
|
||||
|
||||
let entries = old.diff(&new);
|
||||
assert!(entries.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diff_full_flow_mixed_changes() {
|
||||
let old = registry(vec![
|
||||
|
||||
@@ -994,7 +994,6 @@ dependencies = [
|
||||
"tfhe-csprng",
|
||||
"tfhe-fft",
|
||||
"tfhe-ntt",
|
||||
"tfhe-safe-serialize",
|
||||
"tfhe-versionable",
|
||||
"tfhe-zk-pok",
|
||||
]
|
||||
@@ -1046,15 +1045,6 @@ dependencies = [
|
||||
"pulp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tfhe-safe-serialize"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"serde",
|
||||
"tfhe-versionable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tfhe-versionable"
|
||||
version = "0.7.0"
|
||||
@@ -1083,13 +1073,11 @@ dependencies = [
|
||||
"ark-ff",
|
||||
"ark-poly",
|
||||
"getrandom",
|
||||
"itertools 0.14.0",
|
||||
"num-bigint",
|
||||
"rand",
|
||||
"rayon",
|
||||
"serde",
|
||||
"sha3",
|
||||
"tfhe-safe-serialize",
|
||||
"tfhe-versionable",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||