Skip to content

Commit

Permalink
feat(c_api): add new integer types
Browse files Browse the repository at this point in the history
  • Loading branch information
nsarlin-zama committed Mar 6, 2025
1 parent cb3aa30 commit 48f3520
Show file tree
Hide file tree
Showing 9 changed files with 465 additions and 4 deletions.
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ clippy_rustdoc_gpu: install_rs_check_toolchain
.PHONY: clippy_c_api # Run clippy lints enabling the boolean, shortint and the C API
clippy_c_api: install_rs_check_toolchain
RUSTFLAGS="$(RUSTFLAGS)" cargo "$(CARGO_RS_CHECK_TOOLCHAIN)" clippy \
--features=boolean-c-api,shortint-c-api,high-level-c-api \
--features=boolean-c-api,shortint-c-api,high-level-c-api,extended-types \
-p $(TFHE_SPEC) -- --no-deps -D warnings

.PHONY: clippy_js_wasm_api # Run clippy lints enabling the boolean, shortint, integer and the js wasm API
Expand Down Expand Up @@ -512,13 +512,13 @@ build_tfhe_coverage: install_rs_build_toolchain
.PHONY: build_c_api # Build the C API for boolean, shortint and integer
build_c_api: install_rs_check_toolchain
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_CHECK_TOOLCHAIN) build --profile $(CARGO_PROFILE) \
--features=boolean-c-api,shortint-c-api,high-level-c-api,zk-pok \
--features=boolean-c-api,shortint-c-api,high-level-c-api,zk-pok,extended-types \
-p $(TFHE_SPEC)

.PHONY: build_c_api_gpu # Build the C API for boolean, shortint and integer
build_c_api_gpu: install_rs_check_toolchain
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_CHECK_TOOLCHAIN) build --profile $(CARGO_PROFILE) \
--features=boolean-c-api,shortint-c-api,high-level-c-api,zk-pok,gpu \
--features=boolean-c-api,shortint-c-api,high-level-c-api,zk-pok,extended-types,gpu \
-p $(TFHE_SPEC)

.PHONY: build_c_api_experimental_deterministic_fft # Build the C API for boolean, shortint and integer with experimental deterministic FFT
Expand Down
88 changes: 88 additions & 0 deletions tfhe/src/c_api/high_level_api/i1024.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use crate::c_api::utils::*;
use std::os::raw::c_int;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct I1024 {
words: [u64; 16],
}

impl From<crate::integer::bigint::I1024> for I1024 {
fn from(value: crate::integer::bigint::I1024) -> Self {
Self { words: value.0 }
}
}

impl From<I1024> for crate::integer::bigint::I1024 {
fn from(value: I1024) -> Self {
Self(value.words)
}
}

/// Creates a I1024 from little endian bytes
///
/// len must be 128
#[no_mangle]
pub unsafe extern "C" fn I1024_from_little_endian_bytes(
input: *const u8,
len: usize,
result: *mut I1024,
) -> c_int {
catch_panic(|| {
let mut inner = crate::integer::bigint::I1024::default();

let input = std::slice::from_raw_parts(input, len);
inner.copy_from_le_byte_slice(input);

*result = I1024::from(inner);
})
}

/// Creates a I1024 from big endian bytes
///
/// len must be 128
#[no_mangle]
pub unsafe extern "C" fn I1024_from_big_endian_bytes(
input: *const u8,
len: usize,
result: *mut I1024,
) -> c_int {
catch_panic(|| {
let mut inner = crate::integer::bigint::I1024::default();

let input = std::slice::from_raw_parts(input, len);
inner.copy_from_be_byte_slice(input);

*result = I1024::from(inner);
})
}

/// len must be 128
#[no_mangle]
pub unsafe extern "C" fn I1024_little_endian_bytes(
input: I1024,
result: *mut u8,
len: usize,
) -> c_int {
catch_panic(|| {
check_ptr_is_non_null_and_aligned(result).unwrap();

let bytes = std::slice::from_raw_parts_mut(result, len);
crate::integer::bigint::I1024::from(input).copy_to_le_byte_slice(bytes);
})
}

/// len must be 128
#[no_mangle]
pub unsafe extern "C" fn I1024_big_endian_bytes(
input: I1024,
result: *mut u8,
len: usize,
) -> c_int {
catch_panic(|| {
check_ptr_is_non_null_and_aligned(result).unwrap();

let bytes = std::slice::from_raw_parts_mut(result, len);
crate::integer::bigint::I1024::from(input).copy_to_be_byte_slice(bytes);
})
}
88 changes: 88 additions & 0 deletions tfhe/src/c_api/high_level_api/i2048.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use crate::c_api::utils::*;
use std::os::raw::c_int;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct I2048 {
words: [u64; 32],
}

impl From<crate::integer::bigint::I2048> for I2048 {
fn from(value: crate::integer::bigint::I2048) -> Self {
Self { words: value.0 }
}
}

impl From<I2048> for crate::integer::bigint::I2048 {
fn from(value: I2048) -> Self {
Self(value.words)
}
}

/// Creates a I2048 from little endian bytes
///
/// len must be 256
#[no_mangle]
pub unsafe extern "C" fn I2048_from_little_endian_bytes(
input: *const u8,
len: usize,
result: *mut I2048,
) -> c_int {
catch_panic(|| {
let mut inner = crate::integer::bigint::I2048::default();

let input = std::slice::from_raw_parts(input, len);
inner.copy_from_le_byte_slice(input);

*result = I2048::from(inner);
})
}

/// Creates a I2048 from big endian bytes
///
/// len must be 256
#[no_mangle]
pub unsafe extern "C" fn I2048_from_big_endian_bytes(
input: *const u8,
len: usize,
result: *mut I2048,
) -> c_int {
catch_panic(|| {
let mut inner = crate::integer::bigint::I2048::default();

let input = std::slice::from_raw_parts(input, len);
inner.copy_from_be_byte_slice(input);

*result = I2048::from(inner);
})
}

/// len must be 256
#[no_mangle]
pub unsafe extern "C" fn I2048_little_endian_bytes(
input: I2048,
result: *mut u8,
len: usize,
) -> c_int {
catch_panic(|| {
check_ptr_is_non_null_and_aligned(result).unwrap();

let bytes = std::slice::from_raw_parts_mut(result, len);
crate::integer::bigint::I2048::from(input).copy_to_le_byte_slice(bytes);
})
}

/// len must be 256
#[no_mangle]
pub unsafe extern "C" fn I2048_big_endian_bytes(
input: I2048,
result: *mut u8,
len: usize,
) -> c_int {
catch_panic(|| {
check_ptr_is_non_null_and_aligned(result).unwrap();

let bytes = std::slice::from_raw_parts_mut(result, len);
crate::integer::bigint::I2048::from(input).copy_to_be_byte_slice(bytes);
})
}
67 changes: 67 additions & 0 deletions tfhe/src/c_api/high_level_api/i256.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use crate::c_api::utils::*;
use std::os::raw::c_int;

/// w0, w1, w2, w3 are words in little endian order
/// using two's complement representation
#[repr(C)]
Expand Down Expand Up @@ -25,3 +28,67 @@ impl From<I256> for crate::integer::I256 {
Self([value.w0, value.w1, value.w2, value.w3])
}
}

/// Creates a I256 from little endian bytes
///
/// len must be 32
#[no_mangle]
pub unsafe extern "C" fn i256_from_little_endian_bytes(
input: *const u8,
len: usize,
result: *mut I256,
) -> c_int {
catch_panic(|| {
let mut inner = crate::integer::I256::default();

let input = std::slice::from_raw_parts(input, len);
inner.copy_from_le_byte_slice(input);

*result = I256::from(inner);
})
}

/// Creates a I256 from big endian bytes
///
/// len must be 32
#[no_mangle]
pub unsafe extern "C" fn i256_from_big_endian_bytes(
input: *const u8,
len: usize,
result: *mut I256,
) -> c_int {
catch_panic(|| {
let mut inner = crate::integer::I256::default();

let input = std::slice::from_raw_parts(input, len);
inner.copy_from_be_byte_slice(input);

*result = I256::from(inner);
})
}

/// len must be 32
#[no_mangle]
pub unsafe extern "C" fn i256_little_endian_bytes(
input: I256,
result: *mut u8,
len: usize,
) -> c_int {
catch_panic(|| {
check_ptr_is_non_null_and_aligned(result).unwrap();

let bytes = std::slice::from_raw_parts_mut(result, len);
crate::integer::I256::from(input).copy_to_le_byte_slice(bytes);
})
}

/// len must be 32
#[no_mangle]
pub unsafe extern "C" fn i256_big_endian_bytes(input: I256, result: *mut u8, len: usize) -> c_int {
catch_panic(|| {
check_ptr_is_non_null_and_aligned(result).unwrap();

let bytes = std::slice::from_raw_parts_mut(result, len);
crate::integer::I256::from(input).copy_to_be_byte_slice(bytes);
})
}
84 changes: 84 additions & 0 deletions tfhe/src/c_api/high_level_api/i512.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use crate::c_api::utils::*;
use std::os::raw::c_int;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct I512 {
words: [u64; 8],
}

impl From<crate::integer::bigint::I512> for I512 {
fn from(value: crate::integer::bigint::I512) -> Self {
Self { words: value.0 }
}
}

impl From<I512> for crate::integer::bigint::I512 {
fn from(value: I512) -> Self {
Self(value.words)
}
}

/// Creates a I512 from little endian bytes
///
/// len must be 64
#[no_mangle]
pub unsafe extern "C" fn I512_from_little_endian_bytes(
input: *const u8,
len: usize,
result: *mut I512,
) -> c_int {
catch_panic(|| {
let mut inner = crate::integer::bigint::I512::default();

let input = std::slice::from_raw_parts(input, len);
inner.copy_from_le_byte_slice(input);

*result = I512::from(inner);
})
}

/// Creates a I512 from big endian bytes
///
/// len must be 64
#[no_mangle]
pub unsafe extern "C" fn I512_from_big_endian_bytes(
input: *const u8,
len: usize,
result: *mut I512,
) -> c_int {
catch_panic(|| {
let mut inner = crate::integer::bigint::I512::default();

let input = std::slice::from_raw_parts(input, len);
inner.copy_from_be_byte_slice(input);

*result = I512::from(inner);
})
}

/// len must be 64
#[no_mangle]
pub unsafe extern "C" fn I512_little_endian_bytes(
input: I512,
result: *mut u8,
len: usize,
) -> c_int {
catch_panic(|| {
check_ptr_is_non_null_and_aligned(result).unwrap();

let bytes = std::slice::from_raw_parts_mut(result, len);
crate::integer::bigint::I512::from(input).copy_to_le_byte_slice(bytes);
})
}

/// len must be 64
#[no_mangle]
pub unsafe extern "C" fn I512_big_endian_bytes(input: I512, result: *mut u8, len: usize) -> c_int {
catch_panic(|| {
check_ptr_is_non_null_and_aligned(result).unwrap();

let bytes = std::slice::from_raw_parts_mut(result, len);
crate::integer::bigint::I512::from(input).copy_to_be_byte_slice(bytes);
})
}
Loading

0 comments on commit 48f3520

Please sign in to comment.