use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Sub, SubAssign};
use core::{mem, slice};
use crate::field::Field;
use crate::AbstractField;
pub trait Packable: 'static + Default + Copy + Send + Sync + PartialEq + Eq {}
pub unsafe trait PackedValue: 'static + Copy + From<Self::Value> + Send + Sync {
type Value: Packable;
const WIDTH: usize;
fn from_slice(slice: &[Self::Value]) -> &Self;
fn from_slice_mut(slice: &mut [Self::Value]) -> &mut Self;
fn from_fn<F>(f: F) -> Self
where
F: FnMut(usize) -> Self::Value;
fn as_slice(&self) -> &[Self::Value];
fn as_slice_mut(&mut self) -> &mut [Self::Value];
fn pack_slice(buf: &[Self::Value]) -> &[Self] {
assert!(mem::align_of::<Self>() <= mem::align_of::<Self::Value>());
assert!(
buf.len() % Self::WIDTH == 0,
"Slice length (got {}) must be a multiple of packed field width ({}).",
buf.len(),
Self::WIDTH
);
let buf_ptr = buf.as_ptr().cast::<Self>();
let n = buf.len() / Self::WIDTH;
unsafe { slice::from_raw_parts(buf_ptr, n) }
}
fn pack_slice_with_suffix(buf: &[Self::Value]) -> (&[Self], &[Self::Value]) {
let (packed, suffix) = buf.split_at(buf.len() - buf.len() % Self::WIDTH);
(Self::pack_slice(packed), suffix)
}
fn pack_slice_mut(buf: &mut [Self::Value]) -> &mut [Self] {
assert!(mem::align_of::<Self>() <= mem::align_of::<Self::Value>());
assert!(
buf.len() % Self::WIDTH == 0,
"Slice length (got {}) must be a multiple of packed field width ({}).",
buf.len(),
Self::WIDTH
);
let buf_ptr = buf.as_mut_ptr().cast::<Self>();
let n = buf.len() / Self::WIDTH;
unsafe { slice::from_raw_parts_mut(buf_ptr, n) }
}
fn pack_slice_with_suffix_mut(buf: &mut [Self::Value]) -> (&mut [Self], &mut [Self::Value]) {
let (packed, suffix) = buf.split_at_mut(buf.len() - buf.len() % Self::WIDTH);
(Self::pack_slice_mut(packed), suffix)
}
fn unpack_slice(buf: &[Self]) -> &[Self::Value] {
assert!(mem::align_of::<Self>() >= mem::align_of::<Self::Value>());
let buf_ptr = buf.as_ptr().cast::<Self::Value>();
let n = buf.len() * Self::WIDTH;
unsafe { slice::from_raw_parts(buf_ptr, n) }
}
}
pub unsafe trait PackedField: AbstractField<F = Self::Scalar>
+ PackedValue<Value = Self::Scalar>
+ From<Self::Scalar>
+ Add<Self::Scalar, Output = Self>
+ AddAssign<Self::Scalar>
+ Sub<Self::Scalar, Output = Self>
+ SubAssign<Self::Scalar>
+ Mul<Self::Scalar, Output = Self>
+ MulAssign<Self::Scalar>
+ Div<Self::Scalar, Output = Self>
{
type Scalar: Field + Add<Self, Output = Self> + Mul<Self, Output = Self> + Sub<Self, Output = Self>;
fn interleave(&self, other: Self, block_len: usize) -> (Self, Self);
}
unsafe impl<T: Packable> PackedValue for T {
type Value = Self;
const WIDTH: usize = 1;
fn from_slice(slice: &[Self::Value]) -> &Self {
&slice[0]
}
fn from_slice_mut(slice: &mut [Self::Value]) -> &mut Self {
&mut slice[0]
}
fn from_fn<Fn>(mut f: Fn) -> Self
where
Fn: FnMut(usize) -> Self::Value,
{
f(0)
}
fn as_slice(&self) -> &[Self::Value] {
slice::from_ref(self)
}
fn as_slice_mut(&mut self) -> &mut [Self::Value] {
slice::from_mut(self)
}
}
unsafe impl<F: Field> PackedField for F {
type Scalar = Self;
fn interleave(&self, other: Self, block_len: usize) -> (Self, Self) {
match block_len {
1 => (*self, other),
_ => panic!("unsupported block length"),
}
}
}
impl Packable for u8 {}
impl Packable for u16 {}
impl Packable for u32 {}
impl Packable for u64 {}
impl Packable for u128 {}