arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/base2k/src/internals.rs
base2k/src/internals.rsRaw
  1use std::cmp::{max, min};
  2
  3use crate::{Backend, IntegerType, Module, ZnxBasics, ZnxLayout, ffi::module::MODULE};
  4
  5pub(crate) fn znx_post_process_ternary_op<C, A, B, const NEGATE: bool>(c: &mut C, a: &A, b: &B)
  6where
  7    C: ZnxBasics + ZnxLayout,
  8    A: ZnxBasics + ZnxLayout<Scalar = C::Scalar>,
  9    B: ZnxBasics + ZnxLayout<Scalar = C::Scalar>,
 10    C::Scalar: IntegerType,
 11{
 12    #[cfg(debug_assertions)]
 13    {
 14        assert_ne!(a.as_ptr(), b.as_ptr());
 15        assert_ne!(b.as_ptr(), c.as_ptr());
 16        assert_ne!(a.as_ptr(), c.as_ptr());
 17    }
 18
 19    let a_cols: usize = a.cols();
 20    let b_cols: usize = b.cols();
 21    let c_cols: usize = c.cols();
 22
 23    let min_ab_cols: usize = min(a_cols, b_cols);
 24    let max_ab_cols: usize = max(a_cols, b_cols);
 25
 26    // Copies shared shared cols between (c, max(a, b))
 27    if a_cols != b_cols {
 28        if a_cols > b_cols {
 29            let min_size = min(c.size(), a.size());
 30            (min_ab_cols..min(max_ab_cols, c_cols)).for_each(|i| {
 31                (0..min_size).for_each(|j| {
 32                    c.at_poly_mut(i, j).copy_from_slice(a.at_poly(i, j));
 33                    if NEGATE {
 34                        c.at_poly_mut(i, j).iter_mut().for_each(|x| *x = -*x);
 35                    }
 36                });
 37                (min_size..c.size()).for_each(|j| {
 38                    c.zero_at(i, j);
 39                });
 40            });
 41        } else {
 42            let min_size = min(c.size(), b.size());
 43            (min_ab_cols..min(max_ab_cols, c_cols)).for_each(|i| {
 44                (0..min_size).for_each(|j| {
 45                    c.at_poly_mut(i, j).copy_from_slice(b.at_poly(i, j));
 46                    if NEGATE {
 47                        c.at_poly_mut(i, j).iter_mut().for_each(|x| *x = -*x);
 48                    }
 49                });
 50                (min_size..c.size()).for_each(|j| {
 51                    c.zero_at(i, j);
 52                });
 53            });
 54        }
 55    }
 56
 57    // Zeroes the cols of c > max(a, b).
 58    if c_cols > max_ab_cols {
 59        (max_ab_cols..c_cols).for_each(|i| {
 60            (0..c.size()).for_each(|j| {
 61                c.zero_at(i, j);
 62            })
 63        });
 64    }
 65}
 66
 67#[inline(always)]
 68pub fn apply_binary_op<BE, C, A, B, const NEGATE: bool>(
 69    module: &Module<BE>,
 70    c: &mut C,
 71    a: &A,
 72    b: &B,
 73    op: impl Fn(&mut [C::Scalar], &[A::Scalar], &[B::Scalar]),
 74) where
 75    BE: Backend,
 76    C: ZnxBasics + ZnxLayout,
 77    A: ZnxBasics + ZnxLayout<Scalar = C::Scalar>,
 78    B: ZnxBasics + ZnxLayout<Scalar = C::Scalar>,
 79    C::Scalar: IntegerType,
 80{
 81    #[cfg(debug_assertions)]
 82    {
 83        assert_eq!(a.n(), module.n());
 84        assert_eq!(b.n(), module.n());
 85        assert_eq!(c.n(), module.n());
 86        assert_ne!(a.as_ptr(), b.as_ptr());
 87    }
 88    let a_cols: usize = a.cols();
 89    let b_cols: usize = b.cols();
 90    let c_cols: usize = c.cols();
 91    let min_ab_cols: usize = min(a_cols, b_cols);
 92    let min_cols: usize = min(c_cols, min_ab_cols);
 93    // Applies over shared cols between (a, b, c)
 94    (0..min_cols).for_each(|i| op(c.at_poly_mut(i, 0), a.at_poly(i, 0), b.at_poly(i, 0)));
 95    // Copies/Negates/Zeroes the remaining cols if op is not inplace.
 96    if c.as_ptr() != a.as_ptr() && c.as_ptr() != b.as_ptr() {
 97        znx_post_process_ternary_op::<C, A, B, NEGATE>(c, a, b);
 98    }
 99}
100
101#[inline(always)]
102pub fn apply_unary_op<B: Backend, T: ZnxBasics + ZnxLayout>(
103    module: &Module<B>,
104    b: &mut T,
105    a: &T,
106    op: impl Fn(&mut [T::Scalar], &[T::Scalar]),
107) where
108    <T as ZnxLayout>::Scalar: IntegerType,
109{
110    #[cfg(debug_assertions)]
111    {
112        assert_eq!(a.n(), module.n());
113        assert_eq!(b.n(), module.n());
114    }
115    let a_cols: usize = a.cols();
116    let b_cols: usize = b.cols();
117    let min_cols: usize = min(a_cols, b_cols);
118    // Applies over the shared cols between (a, b)
119    (0..min_cols).for_each(|i| op(b.at_poly_mut(i, 0), a.at_poly(i, 0)));
120    // Zeroes the remaining cols of b.
121    (min_cols..b_cols).for_each(|i| (0..b.size()).for_each(|j| b.zero_at(i, j)));
122}
123
124pub fn ffi_ternary_op_factory<T>(
125    module_ptr: *const MODULE,
126    c_size: usize,
127    c_sl: usize,
128    a_size: usize,
129    a_sl: usize,
130    b_size: usize,
131    b_sl: usize,
132    op_fn: unsafe extern "C" fn(*const MODULE, *mut T, u64, u64, *const T, u64, u64, *const T, u64, u64),
133) -> impl Fn(&mut [T], &[T], &[T]) {
134    move |cv: &mut [T], av: &[T], bv: &[T]| unsafe {
135        op_fn(
136            module_ptr,
137            cv.as_mut_ptr(),
138            c_size as u64,
139            c_sl as u64,
140            av.as_ptr(),
141            a_size as u64,
142            a_sl as u64,
143            bv.as_ptr(),
144            b_size as u64,
145            b_sl as u64,
146        )
147    }
148}
149
150pub fn ffi_binary_op_factory_type_0<T>(
151    module_ptr: *const MODULE,
152    b_size: usize,
153    b_sl: usize,
154    a_size: usize,
155    a_sl: usize,
156    op_fn: unsafe extern "C" fn(*const MODULE, *mut T, u64, u64, *const T, u64, u64),
157) -> impl Fn(&mut [T], &[T]) {
158    move |bv: &mut [T], av: &[T]| unsafe {
159        op_fn(
160            module_ptr,
161            bv.as_mut_ptr(),
162            b_size as u64,
163            b_sl as u64,
164            av.as_ptr(),
165            a_size as u64,
166            a_sl as u64,
167        )
168    }
169}
170
171pub fn ffi_binary_op_factory_type_1<T>(
172    module_ptr: *const MODULE,
173    k: i64,
174    b_size: usize,
175    b_sl: usize,
176    a_size: usize,
177    a_sl: usize,
178    op_fn: unsafe extern "C" fn(*const MODULE, i64, *mut T, u64, u64, *const T, u64, u64),
179) -> impl Fn(&mut [T], &[T]) {
180    move |bv: &mut [T], av: &[T]| unsafe {
181        op_fn(
182            module_ptr,
183            k,
184            bv.as_mut_ptr(),
185            b_size as u64,
186            b_sl as u64,
187            av.as_ptr(),
188            a_size as u64,
189            a_sl as u64,
190        )
191    }
192}