mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 05:06:44 +01:00
added digit decomposition
This commit is contained in:
@@ -146,7 +146,6 @@ pub mod macros {
|
|||||||
macro_rules! apply_sv {
|
macro_rules! apply_sv {
|
||||||
($self:expr, $f:expr, $a:expr, $b:expr, $CHUNK:expr) => {
|
($self:expr, $f:expr, $a:expr, $b:expr, $CHUNK:expr) => {
|
||||||
let n: usize = $b.len();
|
let n: usize = $b.len();
|
||||||
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
CHUNK & (CHUNK - 1) == 0,
|
CHUNK & (CHUNK - 1) == 0,
|
||||||
"invalid CHUNK const: not a power of two"
|
"invalid CHUNK const: not a power of two"
|
||||||
@@ -426,13 +425,13 @@ pub mod macros {
|
|||||||
)
|
)
|
||||||
.for_each(|(a, b, e)| {
|
.for_each(|(a, b, e)| {
|
||||||
$f(&$self, &a[0], &b[0], $c, $d, &mut e[0]);
|
$f(&$self, &a[0], &b[0], $c, $d, &mut e[0]);
|
||||||
$f(&$self, &a[1], &b[1], $c, $d, &mut e[1]);
|
$f(&$self, &a[1], &b[1], $c, $d, &mut e[1]);
|
||||||
$f(&$self, &a[2], &b[2], $c, $d, &mut e[2]);
|
$f(&$self, &a[2], &b[2], $c, $d, &mut e[2]);
|
||||||
$f(&$self, &a[3], &b[3], $c, $d, &mut e[3]);
|
$f(&$self, &a[3], &b[3], $c, $d, &mut e[3]);
|
||||||
$f(&$self, &a[4], &b[4], $c, $d, &mut e[4]);
|
$f(&$self, &a[4], &b[4], $c, $d, &mut e[4]);
|
||||||
$f(&$self, &a[5], &b[5], $c, $d, &mut e[5]);
|
$f(&$self, &a[5], &b[5], $c, $d, &mut e[5]);
|
||||||
$f(&$self, &a[6], &b[6], $c, $d, &mut e[6]);
|
$f(&$self, &a[6], &b[6], $c, $d, &mut e[6]);
|
||||||
$f(&$self, &a[7], &b[7], $c, $d, &mut e[7]);
|
$f(&$self, &a[7], &b[7], $c, $d, &mut e[7]);
|
||||||
});
|
});
|
||||||
|
|
||||||
let m = n - (n & 7);
|
let m = n - (n & 7);
|
||||||
@@ -450,4 +449,59 @@ pub mod macros {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! apply_vsssvv {
|
||||||
|
($self:expr, $f:expr, $a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $g:expr, $CHUNK:expr) => {
|
||||||
|
let n: usize = $a.len();
|
||||||
|
debug_assert!(
|
||||||
|
$e.len() == n,
|
||||||
|
"invalid argument b: e.len() = {} != a.len() = {}",
|
||||||
|
$e.len(),
|
||||||
|
n
|
||||||
|
);
|
||||||
|
debug_assert!(
|
||||||
|
$g.len() == n,
|
||||||
|
"invalid argument g: g.len() = {} != a.len() = {}",
|
||||||
|
$g.len(),
|
||||||
|
n
|
||||||
|
);
|
||||||
|
debug_assert!(
|
||||||
|
CHUNK & (CHUNK - 1) == 0,
|
||||||
|
"invalid CHUNK const: not a power of two"
|
||||||
|
);
|
||||||
|
|
||||||
|
match CHUNK {
|
||||||
|
8 => {
|
||||||
|
izip!(
|
||||||
|
$a.chunks_exact(8),
|
||||||
|
$e.chunks_exact_mut(8),
|
||||||
|
$g.chunks_exact_mut(8)
|
||||||
|
)
|
||||||
|
.for_each(|(a, e, g)| {
|
||||||
|
$f(&$self, &a[0], $b, $c, $d, &mut e[0], &mut g[0]);
|
||||||
|
$f(&$self, &a[1], $b, $c, $d, &mut e[1], &mut g[1]);
|
||||||
|
$f(&$self, &a[2], $b, $c, $d, &mut e[2], &mut g[2]);
|
||||||
|
$f(&$self, &a[3], $b, $c, $d, &mut e[3], &mut g[3]);
|
||||||
|
$f(&$self, &a[4], $b, $c, $d, &mut e[4], &mut g[4]);
|
||||||
|
$f(&$self, &a[5], $b, $c, $d, &mut e[5], &mut g[5]);
|
||||||
|
$f(&$self, &a[6], $b, $c, $d, &mut e[6], &mut g[6]);
|
||||||
|
$f(&$self, &a[7], $b, $c, $d, &mut e[7], &mut g[7]);
|
||||||
|
});
|
||||||
|
|
||||||
|
let m = n - (n & 7);
|
||||||
|
izip!($a[m..].iter(), $e[m..].iter_mut(), $g[m..].iter_mut()).for_each(
|
||||||
|
|(a, e, g)| {
|
||||||
|
$f(&$self, a, $b, $c, $d, e, g);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
izip!($a.iter(), $e.iter_mut(), $g.iter_mut()).for_each(|(a, e, g)| {
|
||||||
|
$f(&$self, a, $b, $c, $d, e, g);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,6 +187,22 @@ pub trait ScalarOperations<O> {
|
|||||||
d: &barrett::Barrett<u64>,
|
d: &barrett::Barrett<u64>,
|
||||||
a: &mut u64,
|
a: &mut u64,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fn sa_rsh_sb_mask_sc_into_sa(&self, c: &u64, b: &u64, a: &mut u64);
|
||||||
|
|
||||||
|
fn sa_rsh_sb_mask_sc_into_sd(&self, a: &u64, b: &u64, c: &u64, d: &mut u64);
|
||||||
|
|
||||||
|
fn sa_rsh_sb_mask_sc_add_sd_into_sd(&self, a: &u64, b: &u64, c: &u64, d: &mut u64);
|
||||||
|
|
||||||
|
fn sa_signed_digit_into_sb<const CARRYOVERWRITE: bool, const BALANCED: bool>(
|
||||||
|
&self,
|
||||||
|
a: &u64,
|
||||||
|
base: &u64,
|
||||||
|
shift: &u64,
|
||||||
|
mask: &u64,
|
||||||
|
carry: &mut u64,
|
||||||
|
b: &mut u64,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait VectorOperations<O> {
|
pub trait VectorOperations<O> {
|
||||||
@@ -354,4 +370,48 @@ pub trait VectorOperations<O> {
|
|||||||
sd: &barrett::Barrett<u64>,
|
sd: &barrett::Barrett<u64>,
|
||||||
va: &mut [u64],
|
va: &mut [u64],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// vec(a) <- (vec(a)>>scalar(b)) & scalar(c).
|
||||||
|
fn va_rsh_sb_mask_sd_into_va<const CHUNK: usize>(&self, sb: &u64, sc: &u64, va: &mut [u64]);
|
||||||
|
|
||||||
|
// vec(d) <- (vec(a)>>scalar(b)) & scalar(c).
|
||||||
|
fn va_rsh_sb_mask_sc_into_vd<const CHUNK: usize>(
|
||||||
|
&self,
|
||||||
|
va: &[u64],
|
||||||
|
sb: &u64,
|
||||||
|
sc: &u64,
|
||||||
|
vd: &mut [u64],
|
||||||
|
);
|
||||||
|
|
||||||
|
// vec(d) <- vec(d) + (vec(a)>>scalar(b)) & scalar(c).
|
||||||
|
fn va_rsh_sb_mask_sc_add_vd_into_vd<const CHUNK: usize>(
|
||||||
|
&self,
|
||||||
|
va: &[u64],
|
||||||
|
sb: &u64,
|
||||||
|
sc: &u64,
|
||||||
|
vd: &mut [u64],
|
||||||
|
);
|
||||||
|
|
||||||
|
// vec(c) <- i-th unsigned digit base 2^{sb} of vec(a).
|
||||||
|
// vec(c) is ensured to be in the range [0, 2^{sb}-1[ with E[vec(c)] = 2^{sb}-1.
|
||||||
|
fn va_ith_digit_unsigned_base_sb_into_vc<const CHUNK: usize>(
|
||||||
|
&self,
|
||||||
|
i: usize,
|
||||||
|
va: &[u64],
|
||||||
|
sb: &u64,
|
||||||
|
vc: &mut [u64],
|
||||||
|
);
|
||||||
|
|
||||||
|
// vec(c) <- i-th signed digit base 2^{w} of vec(a).
|
||||||
|
// Reads the carry of the i-1-th iteration and write the carry on the i-th iteration on carry.
|
||||||
|
// if i > 0, carry of the i-1th iteration must be provided.
|
||||||
|
// if BALANCED: vec(c) is ensured to be [-2^{sb-1}, 2^{sb-1}[ with E[vec(c)] = 0, else E[vec(c)] = -0.5
|
||||||
|
fn va_ith_digit_signed_base_sb_into_vc<const CHUNK: usize, const BALANCED: bool>(
|
||||||
|
&self,
|
||||||
|
i: usize,
|
||||||
|
va: &[u64],
|
||||||
|
sb: &u64,
|
||||||
|
carry: &mut [u64],
|
||||||
|
vc: &mut [u64],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ use crate::modulus::prime::Prime;
|
|||||||
use crate::modulus::{ScalarOperations, VectorOperations};
|
use crate::modulus::{ScalarOperations, VectorOperations};
|
||||||
use crate::modulus::{NONE, REDUCEMOD};
|
use crate::modulus::{NONE, REDUCEMOD};
|
||||||
use crate::{
|
use crate::{
|
||||||
apply_ssv, apply_sv, apply_svv, apply_v, apply_vssv, apply_vsv, apply_vv, apply_vvssv,
|
apply_ssv, apply_sv, apply_svv, apply_v, apply_vsssvv, apply_vssv, apply_vsv, apply_vv,
|
||||||
apply_vvsv, apply_vvv,
|
apply_vvssv, apply_vvsv, apply_vvv,
|
||||||
};
|
};
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
|
|
||||||
@@ -211,6 +211,47 @@ impl ScalarOperations<u64> for Prime<u64> {
|
|||||||
self.sa_sub_sb_into_sb::<SBRANGE, NONE>(&(b + c), a);
|
self.sa_sub_sb_into_sb::<SBRANGE, NONE>(&(b + c), a);
|
||||||
self.barrett.mul_external_assign::<REDUCE>(*d, a);
|
self.barrett.mul_external_assign::<REDUCE>(*d, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn sa_rsh_sb_mask_sc_into_sa(&self, b: &u64, c: &u64, a: &mut u64) {
|
||||||
|
*a = (*a >> b) & c
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn sa_rsh_sb_mask_sc_into_sd(&self, a: &u64, b: &u64, c: &u64, d: &mut u64) {
|
||||||
|
*d = (*a >> b) & c
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn sa_rsh_sb_mask_sc_add_sd_into_sd(&self, a: &u64, b: &u64, c: &u64, d: &mut u64) {
|
||||||
|
*d += (*a >> b) & c
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn sa_signed_digit_into_sb<const CARRYOVERWRITE: bool, const BALANCED: bool>(
|
||||||
|
&self,
|
||||||
|
a: &u64,
|
||||||
|
base: &u64,
|
||||||
|
shift: &u64,
|
||||||
|
mask: &u64,
|
||||||
|
carry: &mut u64,
|
||||||
|
b: &mut u64,
|
||||||
|
) {
|
||||||
|
if CARRYOVERWRITE {
|
||||||
|
self.sa_rsh_sb_mask_sc_into_sd(a, shift, mask, carry);
|
||||||
|
} else {
|
||||||
|
self.sa_rsh_sb_mask_sc_add_sd_into_sd(a, shift, mask, carry);
|
||||||
|
}
|
||||||
|
|
||||||
|
let c: u64 = if BALANCED && *carry == base >> 1 {
|
||||||
|
a & 1
|
||||||
|
} else {
|
||||||
|
((*carry | (*carry << 1)) >> base) & 1
|
||||||
|
};
|
||||||
|
|
||||||
|
*b = *carry + (self.q - base) * c;
|
||||||
|
*carry = c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VectorOperations<u64> for Prime<u64> {
|
impl VectorOperations<u64> for Prime<u64> {
|
||||||
@@ -518,4 +559,92 @@ impl VectorOperations<u64> for Prime<u64> {
|
|||||||
CHUNK
|
CHUNK
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vec(a) <- (vec(a)>>scalar(b)) & scalar(c).
|
||||||
|
fn va_rsh_sb_mask_sd_into_va<const CHUNK: usize>(&self, sb: &u64, sc: &u64, va: &mut [u64]) {
|
||||||
|
apply_ssv!(self, Self::sa_rsh_sb_mask_sc_into_sa, sb, sc, va, CHUNK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vec(d) <- (vec(a)>>scalar(b)) & scalar(c).
|
||||||
|
fn va_rsh_sb_mask_sc_into_vd<const CHUNK: usize>(
|
||||||
|
&self,
|
||||||
|
va: &[u64],
|
||||||
|
sb: &u64,
|
||||||
|
sc: &u64,
|
||||||
|
vd: &mut [u64],
|
||||||
|
) {
|
||||||
|
apply_vssv!(self, Self::sa_rsh_sb_mask_sc_into_sd, va, sb, sc, vd, CHUNK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vec(d) <- vec(d) + (vec(a)>>scalar(b)) & scalar(c).
|
||||||
|
fn va_rsh_sb_mask_sc_add_vd_into_vd<const CHUNK: usize>(
|
||||||
|
&self,
|
||||||
|
va: &[u64],
|
||||||
|
sb: &u64,
|
||||||
|
sc: &u64,
|
||||||
|
vd: &mut [u64],
|
||||||
|
) {
|
||||||
|
apply_vssv!(
|
||||||
|
self,
|
||||||
|
Self::sa_rsh_sb_mask_sc_add_sd_into_sd,
|
||||||
|
va,
|
||||||
|
sb,
|
||||||
|
sc,
|
||||||
|
vd,
|
||||||
|
CHUNK
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vec(c) <- i-th unsigned digit base 2^{sb} of vec(a).
|
||||||
|
// vec(c) is ensured to be in the range [0, 2^{sb}-1[ with E[vec(c)] = 2^{sb}-1.
|
||||||
|
fn va_ith_digit_unsigned_base_sb_into_vc<const CHUNK: usize>(
|
||||||
|
&self,
|
||||||
|
i: usize,
|
||||||
|
va: &[u64],
|
||||||
|
sb: &u64,
|
||||||
|
vc: &mut [u64],
|
||||||
|
) {
|
||||||
|
self.va_rsh_sb_mask_sc_into_vd::<CHUNK>(va, &((i as u64) * sb), &((1 << sb) - 1), vc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vec(c) <- i-th signed digit base 2^{w} of vec(a).
|
||||||
|
// Reads the carry of the i-1-th iteration and write the carry on the i-th iteration on carry.
|
||||||
|
// if i > 0, carry of the i-1th iteration must be provided.
|
||||||
|
// if BALANCED: vec(c) is ensured to be [-2^{sb-1}, 2^{sb-1}[ with E[vec(c)] = 0, else E[vec(c)] = -0.5
|
||||||
|
fn va_ith_digit_signed_base_sb_into_vc<const CHUNK: usize, const BALANCED: bool>(
|
||||||
|
&self,
|
||||||
|
i: usize,
|
||||||
|
va: &[u64],
|
||||||
|
sb: &u64,
|
||||||
|
carry: &mut [u64],
|
||||||
|
vc: &mut [u64],
|
||||||
|
) {
|
||||||
|
let base: u64 = 1 << sb;
|
||||||
|
let mask: u64 = base - 1;
|
||||||
|
if i == 0 {
|
||||||
|
apply_vsssvv!(
|
||||||
|
self,
|
||||||
|
Self::sa_signed_digit_into_sb::<true, BALANCED>,
|
||||||
|
va,
|
||||||
|
&base,
|
||||||
|
&(i as u64 * sb),
|
||||||
|
&mask,
|
||||||
|
carry,
|
||||||
|
vc,
|
||||||
|
CHUNK
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
apply_vsssvv!(
|
||||||
|
self,
|
||||||
|
Self::sa_signed_digit_into_sb::<false, BALANCED>,
|
||||||
|
va,
|
||||||
|
&base,
|
||||||
|
&(i as u64 * sb),
|
||||||
|
&mask,
|
||||||
|
carry,
|
||||||
|
vc,
|
||||||
|
CHUNK
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ impl Ring<u64> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_normal(&self, source: &mut Source, sigma: f64, bound: f64, a: &mut Poly<u64>){
|
pub fn fill_normal(&self, source: &mut Source, sigma: f64, bound: f64, a: &mut Poly<u64>) {
|
||||||
self.fill_dist_f64(source, Normal::new(0.0, sigma).unwrap(), bound, a);
|
self.fill_dist_f64(source, Normal::new(0.0, sigma).unwrap(), bound, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user