mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-11 15:48:20 -05:00
Compare commits
1 Commits
go/test/te
...
tm/array-f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92163c2646 |
@@ -7,7 +7,7 @@ use crate::high_level_api::array::{ArrayBackend, BackendDataContainer, BackendDa
|
||||
use crate::high_level_api::global_state;
|
||||
use crate::integer::BooleanBlock;
|
||||
use crate::prelude::{FheDecrypt, FheTryEncrypt};
|
||||
use crate::{ClientKey, FheId};
|
||||
use crate::{ClientKey, FheBool, FheId, Tag};
|
||||
use rayon::prelude::*;
|
||||
use std::ops::RangeBounds;
|
||||
|
||||
@@ -36,6 +36,28 @@ impl ArrayBackend for CpuFheBoolArrayBackend {
|
||||
type Owned = Vec<BooleanBlock>;
|
||||
}
|
||||
|
||||
impl From<Vec<FheBool>> for CpuFheBoolArray {
|
||||
fn from(value: Vec<FheBool>) -> Self {
|
||||
let vec = value
|
||||
.into_iter()
|
||||
.map(|b| BooleanBlock::new_unchecked(b.into_raw_parts()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let shape = vec![vec.len()];
|
||||
Self::new(vec, shape)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CpuFheBoolArray> for Vec<FheBool> {
|
||||
fn from(value: CpuFheBoolArray) -> Self {
|
||||
value
|
||||
.into_container()
|
||||
.into_iter()
|
||||
.map(|boolean_block| FheBool::new(boolean_block, Tag::default()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl BackendDataContainer for &[BooleanBlock] {
|
||||
type Backend = CpuFheBoolArrayBackend;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ use crate::integer::server_key::radix_parallel::scalar_div_mod::SignedReciprocab
|
||||
use crate::integer::server_key::{Reciprocable, ScalarMultiplier};
|
||||
use crate::integer::{IntegerRadixCiphertext, RadixCiphertext, SignedRadixCiphertext};
|
||||
use crate::prelude::{FheDecrypt, FheTryEncrypt};
|
||||
use crate::{ClientKey, Error};
|
||||
use crate::{ClientKey, Error, FheInt, FheUint, Tag};
|
||||
use rayon::prelude::*;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::RangeBounds;
|
||||
@@ -54,6 +54,48 @@ where
|
||||
type Owned = Vec<T>;
|
||||
}
|
||||
|
||||
impl<Id: FheUintId> From<Vec<FheUint<Id>>> for CpuFheUintArray<Id> {
|
||||
fn from(value: Vec<FheUint<Id>>) -> Self {
|
||||
let vec: Vec<_> = value
|
||||
.into_iter()
|
||||
.map(|uint| uint.into_raw_parts().0)
|
||||
.collect();
|
||||
let shape = vec![vec.len()];
|
||||
Self::new(vec, shape)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id: FheUintId> From<CpuFheUintArray<Id>> for Vec<FheUint<Id>> {
|
||||
fn from(value: CpuFheUintArray<Id>) -> Self {
|
||||
value
|
||||
.into_container()
|
||||
.into_iter()
|
||||
.map(|radix| FheUint::new(radix, Tag::default()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id: FheIntId> From<Vec<FheInt<Id>>> for CpuFheIntArray<Id> {
|
||||
fn from(value: Vec<FheInt<Id>>) -> Self {
|
||||
let vec: Vec<_> = value
|
||||
.into_iter()
|
||||
.map(|uint| uint.into_raw_parts().0)
|
||||
.collect();
|
||||
let shape = vec![vec.len()];
|
||||
Self::new(vec, shape)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id: FheIntId> From<CpuFheIntArray<Id>> for Vec<FheInt<Id>> {
|
||||
fn from(value: CpuFheIntArray<Id>) -> Self {
|
||||
value
|
||||
.into_container()
|
||||
.into_iter()
|
||||
.map(|radix| FheInt::new(radix, Tag::default()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
fn par_map_sks_op_on_pair_of_elements<'a, T, F>(
|
||||
|
||||
@@ -11,7 +11,7 @@ use super::super::{FheBackendArray, FheBackendArraySlice, FheBackendArraySliceMu
|
||||
use crate::array::traits::TensorSlice;
|
||||
use crate::integer::BooleanBlock;
|
||||
use crate::prelude::{FheDecrypt, FheTryEncrypt};
|
||||
use crate::{ClientKey, Device};
|
||||
use crate::{ClientKey, CpuFheBoolArray, Device, FheBool};
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::ops::RangeBounds;
|
||||
|
||||
@@ -33,6 +33,43 @@ impl ArrayBackend for DynFheBoolArrayBackend {
|
||||
type Owned = InnerBoolArray;
|
||||
}
|
||||
|
||||
impl TryFrom<Vec<FheBool>> for FheBoolArray {
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(values: Vec<FheBool>) -> Result<Self, Self::Error> {
|
||||
if values.is_empty() {
|
||||
return Ok(Self::new(InnerBoolArray::Cpu(vec![]), vec![0]));
|
||||
}
|
||||
|
||||
let shape = vec![values.len()];
|
||||
let device_of_first = values[0].current_device();
|
||||
let inner = match device_of_first {
|
||||
Device::Cpu => {
|
||||
let new_values = values
|
||||
.into_iter()
|
||||
.map(|value| value.ciphertext.into_cpu())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
InnerBoolArray::Cpu(new_values)
|
||||
}
|
||||
#[cfg(feature = "gpu")]
|
||||
Device::CudaGpu => return Err(crate::error!("Array do not support GPU")),
|
||||
#[cfg(feature = "hpu")]
|
||||
Device::Hpu => return Err(crate::error!("Array do not support HPU")),
|
||||
};
|
||||
|
||||
Ok(Self::new(inner, shape))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CpuFheBoolArray> for FheBoolArray {
|
||||
fn from(cpu_array: CpuFheBoolArray) -> Self {
|
||||
let CpuFheBoolArray { elems, dims, _id } = cpu_array;
|
||||
|
||||
Self::new(InnerBoolArray::Cpu(elems), dims)
|
||||
}
|
||||
}
|
||||
|
||||
impl BitwiseArrayBackend for DynFheBoolArrayBackend {
|
||||
fn bitand<'a>(
|
||||
lhs: TensorSlice<'_, Self::Slice<'a>>,
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::high_level_api::array::{ArrayBackend, BackendDataContainer, BackendDa
|
||||
use crate::high_level_api::global_state;
|
||||
use crate::integer::gpu::ciphertext::boolean_value::CudaBooleanBlock;
|
||||
use crate::prelude::{FheDecrypt, FheTryEncrypt};
|
||||
use crate::{ClientKey, FheBoolId};
|
||||
use crate::{ClientKey, FheBool, FheBoolId, Tag};
|
||||
use rayon::prelude::*;
|
||||
use std::ops::RangeBounds;
|
||||
|
||||
@@ -72,6 +72,31 @@ impl From<Vec<CudaBooleanBlock>> for GpuBooleanOwned {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<FheBool>> for GpuFheBoolArray {
|
||||
fn from(value: Vec<FheBool>) -> Self {
|
||||
let container = with_cuda_internal_keys(|cuda_keys| {
|
||||
value
|
||||
.into_iter()
|
||||
.map(|val| val.ciphertext.into_gpu(&cuda_keys.streams))
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
let shape = vec![container.len()];
|
||||
Self::new(container, shape)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GpuFheBoolArray> for Vec<FheBool> {
|
||||
fn from(value: GpuFheBoolArray) -> Self {
|
||||
value
|
||||
.into_container()
|
||||
.0
|
||||
.into_iter()
|
||||
.map(|cuda_bool_block| FheBool::new(cuda_bool_block, Tag::default()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl BackendDataContainer for GpuBooleanSlice<'_> {
|
||||
type Backend = GpuFheBoolArrayBackend;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ use crate::integer::gpu::ciphertext::{
|
||||
use crate::integer::server_key::radix_parallel::scalar_div_mod::SignedReciprocable;
|
||||
use crate::integer::server_key::{Reciprocable, ScalarMultiplier};
|
||||
use crate::prelude::{CastInto, FheDecrypt, FheTryEncrypt};
|
||||
use crate::{ClientKey, Error};
|
||||
use crate::{ClientKey, Error, FheInt, FheUint, Tag};
|
||||
use rayon::prelude::*;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::RangeBounds;
|
||||
@@ -60,6 +60,54 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id: FheUintId> From<Vec<FheUint<Id>>> for GpuFheUintArray<Id> {
|
||||
fn from(value: Vec<FheUint<Id>>) -> Self {
|
||||
let container = with_cuda_internal_keys(|cuda_keys| {
|
||||
value
|
||||
.into_iter()
|
||||
.map(|elem| elem.ciphertext.into_gpu(&cuda_keys.streams))
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
let shape = vec![container.len()];
|
||||
Self::new(container, shape)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id: FheUintId> From<GpuFheUintArray<Id>> for Vec<FheUint<Id>> {
|
||||
fn from(value: GpuFheUintArray<Id>) -> Self {
|
||||
value
|
||||
.into_container()
|
||||
.0
|
||||
.into_iter()
|
||||
.map(|elem| FheUint::new(elem, Tag::default()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id: FheIntId> From<Vec<FheInt<Id>>> for GpuFheIntArray<Id> {
|
||||
fn from(value: Vec<FheInt<Id>>) -> Self {
|
||||
let container = with_cuda_internal_keys(|cuda_keys| {
|
||||
value
|
||||
.into_iter()
|
||||
.map(|elem| elem.ciphertext.into_gpu(&cuda_keys.streams))
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
let shape = vec![container.len()];
|
||||
Self::new(container, shape)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id: FheIntId> From<GpuFheIntArray<Id>> for Vec<FheInt<Id>> {
|
||||
fn from(value: GpuFheIntArray<Id>) -> Self {
|
||||
value
|
||||
.into_container()
|
||||
.0
|
||||
.into_iter()
|
||||
.map(|elem| FheInt::new(elem, Tag::default()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ArrayBackend for GpuIntegerArrayBackend<T>
|
||||
where
|
||||
T: CudaIntegerRadixCiphertext,
|
||||
|
||||
@@ -2,7 +2,11 @@ mod booleans;
|
||||
mod signed;
|
||||
mod unsigned;
|
||||
|
||||
use crate::{generate_keys, set_server_key, ClientKey, ConfigBuilder, FheId};
|
||||
use crate::prelude::*;
|
||||
use crate::{
|
||||
generate_keys, set_server_key, ClientKey, ConfigBuilder, CpuFheBoolArray, CpuFheInt32Array,
|
||||
CpuFheUint32Array, FheBool, FheId, FheInt32, FheUint32,
|
||||
};
|
||||
#[cfg(feature = "gpu")]
|
||||
use crate::{Config, CudaServerKey};
|
||||
use rand::distributions::{Distribution, Standard};
|
||||
@@ -11,6 +15,8 @@ use std::fmt::Debug;
|
||||
|
||||
use crate::array::traits::IOwnedArray;
|
||||
use crate::array::ClearArray;
|
||||
#[cfg(feature = "gpu")]
|
||||
use crate::array::{GpuFheBoolArray, GpuFheInt32Array, GpuFheUint32Array};
|
||||
use crate::high_level_api::array::{FheBackendArray, FheBackendArraySlice};
|
||||
use crate::prelude::{FheDecrypt, FheTryEncrypt};
|
||||
use std::ops::{BitAnd, BitOr, BitXor};
|
||||
@@ -293,3 +299,132 @@ where
|
||||
assert_eq!(result, expected_result);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
#[test]
|
||||
fn test_gpu_conversions() {
|
||||
let ck = setup_default_gpu();
|
||||
|
||||
let num_values = 50;
|
||||
|
||||
// Vec<FheUint> <=> GpuFheUint
|
||||
{
|
||||
let clears = draw_random_values::<u32>(num_values);
|
||||
let encrypted = clears
|
||||
.iter()
|
||||
.map(|v| FheUint32::encrypt(*v, &ck))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let gpu_array = GpuFheUint32Array::from(encrypted);
|
||||
let decrypted: Vec<u32> = gpu_array.decrypt(&ck);
|
||||
assert_eq!(decrypted, clears);
|
||||
|
||||
let encrypted = Vec::<FheUint32>::from(gpu_array);
|
||||
let decrypted: Vec<u32> = encrypted
|
||||
.iter()
|
||||
.map(|fheuint| fheuint.decrypt(&ck))
|
||||
.collect();
|
||||
assert_eq!(decrypted, clears);
|
||||
}
|
||||
|
||||
// Vec<FheInt> <=> GpuFheInt
|
||||
{
|
||||
let clears = draw_random_values::<i32>(num_values);
|
||||
let encrypted = clears
|
||||
.iter()
|
||||
.map(|v| FheInt32::encrypt(*v, &ck))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let gpu_array = GpuFheInt32Array::from(encrypted);
|
||||
let decrypted: Vec<i32> = gpu_array.decrypt(&ck);
|
||||
assert_eq!(decrypted, clears);
|
||||
|
||||
let encrypted = Vec::<FheInt32>::from(gpu_array);
|
||||
let decrypted: Vec<i32> = encrypted.iter().map(|fheint| fheint.decrypt(&ck)).collect();
|
||||
assert_eq!(decrypted, clears);
|
||||
}
|
||||
|
||||
// Vec<FheBool> <=> GpuFheBool
|
||||
{
|
||||
let clears = draw_random_values::<bool>(num_values);
|
||||
let encrypted = clears
|
||||
.iter()
|
||||
.map(|v| FheBool::encrypt(*v, &ck))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let gpu_array = GpuFheBoolArray::from(encrypted);
|
||||
let decrypted: Vec<bool> = gpu_array.decrypt(&ck);
|
||||
assert_eq!(decrypted, clears);
|
||||
|
||||
let encrypted = Vec::<FheBool>::from(gpu_array);
|
||||
let decrypted: Vec<bool> = encrypted
|
||||
.iter()
|
||||
.map(|fhebool| fhebool.decrypt(&ck))
|
||||
.collect();
|
||||
assert_eq!(decrypted, clears);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cpu_conversions() {
|
||||
let ck = setup_default_cpu();
|
||||
|
||||
let num_values = 50;
|
||||
|
||||
// Vec<FheUint> <=> CpuFheUint
|
||||
{
|
||||
let clears = draw_random_values::<u32>(num_values);
|
||||
let encrypted = clears
|
||||
.iter()
|
||||
.map(|v| FheUint32::encrypt(*v, &ck))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let cpu_array = CpuFheUint32Array::from(encrypted);
|
||||
let decrypted: Vec<u32> = cpu_array.decrypt(&ck);
|
||||
assert_eq!(decrypted, clears);
|
||||
|
||||
let encrypted = Vec::<FheUint32>::from(cpu_array);
|
||||
let decrypted: Vec<u32> = encrypted
|
||||
.iter()
|
||||
.map(|fheuint| fheuint.decrypt(&ck))
|
||||
.collect();
|
||||
assert_eq!(decrypted, clears);
|
||||
}
|
||||
|
||||
// Vec<FheInt> <=> CpuFheInt
|
||||
{
|
||||
let clears = draw_random_values::<i32>(num_values);
|
||||
let encrypted = clears
|
||||
.iter()
|
||||
.map(|v| FheInt32::encrypt(*v, &ck))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let cpu_array = CpuFheInt32Array::from(encrypted);
|
||||
let decrypted: Vec<i32> = cpu_array.decrypt(&ck);
|
||||
assert_eq!(decrypted, clears);
|
||||
|
||||
let encrypted = Vec::<FheInt32>::from(cpu_array);
|
||||
let decrypted: Vec<i32> = encrypted.iter().map(|fheint| fheint.decrypt(&ck)).collect();
|
||||
assert_eq!(decrypted, clears);
|
||||
}
|
||||
|
||||
// Vec<FheBool> <=> CpuFheBool
|
||||
{
|
||||
let clears = draw_random_values::<bool>(num_values);
|
||||
let encrypted = clears
|
||||
.iter()
|
||||
.map(|v| FheBool::encrypt(*v, &ck))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let cpu_array = CpuFheBoolArray::from(encrypted);
|
||||
let decrypted: Vec<bool> = cpu_array.decrypt(&ck);
|
||||
assert_eq!(decrypted, clears);
|
||||
|
||||
let encrypted = Vec::<FheBool>::from(cpu_array);
|
||||
let decrypted: Vec<bool> = encrypted
|
||||
.iter()
|
||||
.map(|fhebool| fhebool.decrypt(&ck))
|
||||
.collect();
|
||||
assert_eq!(decrypted, clears);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::integer::hpu::ciphertext::HpuRadixCiphertext;
|
||||
pub(in crate::high_level_api) enum InnerBoolean {
|
||||
Cpu(BooleanBlock),
|
||||
#[cfg(feature = "gpu")]
|
||||
Cuda(crate::integer::gpu::ciphertext::boolean_value::CudaBooleanBlock),
|
||||
Cuda(CudaBooleanBlock),
|
||||
#[cfg(feature = "hpu")]
|
||||
Hpu(HpuRadixCiphertext),
|
||||
}
|
||||
@@ -220,7 +220,6 @@ impl InnerBoolean {
|
||||
&mut cuda_ct.0
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpu")]
|
||||
pub(crate) fn into_cpu(self) -> BooleanBlock {
|
||||
match self {
|
||||
Self::Cpu(cpu_ct) => cpu_ct,
|
||||
|
||||
Reference in New Issue
Block a user