use core::fmt::Debug;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign};
use core::slice;
use crate::ops::Square;
use crate::types::Field;
pub unsafe trait PackedField:
'static
+ Add<Self, Output = Self>
+ Add<Self::Scalar, Output = Self>
+ AddAssign<Self>
+ AddAssign<Self::Scalar>
+ Copy
+ Debug
+ Default
+ From<Self::Scalar>
+ Div<Self::Scalar, Output = Self>
+ Mul<Self, Output = Self>
+ Mul<Self::Scalar, Output = Self>
+ MulAssign<Self>
+ MulAssign<Self::Scalar>
+ Square
+ Neg<Output = Self>
+ Product
+ Send
+ Sub<Self, Output = Self>
+ Sub<Self::Scalar, Output = Self>
+ SubAssign<Self>
+ SubAssign<Self::Scalar>
+ Sum
+ Sync
where
Self::Scalar: Add<Self, Output = Self>,
Self::Scalar: Mul<Self, Output = Self>,
Self::Scalar: Sub<Self, Output = Self>,
{
type Scalar: Field;
const WIDTH: usize;
const ZEROS: Self;
const ONES: Self;
fn from_arr(arr: [Self::Scalar; Self::WIDTH]) -> Self;
fn as_arr(&self) -> [Self::Scalar; Self::WIDTH];
fn from_slice(slice: &[Self::Scalar]) -> &Self;
fn from_slice_mut(slice: &mut [Self::Scalar]) -> &mut Self;
fn as_slice(&self) -> &[Self::Scalar];
fn as_slice_mut(&mut self) -> &mut [Self::Scalar];
fn interleave(&self, other: Self, block_len: usize) -> (Self, Self);
fn pack_slice(buf: &[Self::Scalar]) -> &[Self] {
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_mut(buf: &mut [Self::Scalar]) -> &mut [Self] {
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 doubles(&self) -> Self {
*self * Self::Scalar::TWO
}
}
unsafe impl<F: Field> PackedField for F {
type Scalar = Self;
const WIDTH: usize = 1;
const ZEROS: Self = F::ZERO;
const ONES: Self = F::ONE;
fn from_arr(arr: [Self::Scalar; Self::WIDTH]) -> Self {
arr[0]
}
fn as_arr(&self) -> [Self::Scalar; Self::WIDTH] {
[*self]
}
fn from_slice(slice: &[Self::Scalar]) -> &Self {
&slice[0]
}
fn from_slice_mut(slice: &mut [Self::Scalar]) -> &mut Self {
&mut slice[0]
}
fn as_slice(&self) -> &[Self::Scalar] {
slice::from_ref(self)
}
fn as_slice_mut(&mut self) -> &mut [Self::Scalar] {
slice::from_mut(self)
}
fn interleave(&self, other: Self, block_len: usize) -> (Self, Self) {
match block_len {
1 => (*self, other),
_ => panic!("unsupported block length"),
}
}
}