Remove Singleton type and make every Field a PackedField (#379)

* Remove `Singleton` type and make every `Field` a `PackedField`

* Minor: Clippy
This commit is contained in:
Jakub Nabaglo 2021-12-02 00:01:24 -08:00 committed by GitHub
parent 982f85fd1b
commit 6df251e144
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 128 deletions

View File

@ -5,7 +5,7 @@ use unroll::unroll_for_loops;
use crate::field::field_types::Field;
use crate::field::packable::Packable;
use crate::field::packed_field::{PackedField, Singleton};
use crate::field::packed_field::PackedField;
use crate::polynomial::{PolynomialCoeffs, PolynomialValues};
use crate::util::{log2_strict, reverse_index_bits};
@ -201,7 +201,7 @@ pub(crate) fn fft_classic<F: Field>(input: &[F], r: usize, root_table: &FftRootT
if lg_n <= lg_packed_width {
// Need the slice to be at least the width of two packed vectors for the vectorized version
// to work. Do this tiny problem in scalar.
fft_classic_simd::<Singleton<F>>(&mut values[..], r, lg_n, root_table);
fft_classic_simd::<F>(&mut values[..], r, lg_n, root_table);
} else {
fft_classic_simd::<<F as Packable>::PackedType>(&mut values[..], r, lg_n, root_table);
}

View File

@ -1,15 +1,15 @@
use crate::field::field_types::Field;
use crate::field::packed_field::{PackedField, Singleton};
use crate::field::packed_field::PackedField;
/// Points us to the default packing for a particular field. There may me multiple choices of
/// PackedField for a particular Field (e.g. Singleton works for all fields), but this is the
/// PackedField for a particular Field (e.g. every Field is also a PackedField), but this is the
/// recommended one. The recommended packing varies by target_arch and target_feature.
pub trait Packable: Field {
type PackedType: PackedField<FieldType = Self>;
}
impl<F: Field> Packable for F {
default type PackedType = Singleton<Self>;
default type PackedType = Self;
}
#[cfg(target_feature = "avx2")]

View File

@ -1,5 +1,4 @@
use std::fmt;
use std::fmt::{Debug, Formatter};
use std::fmt::Debug;
use std::iter::{Product, Sum};
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
@ -95,143 +94,35 @@ pub trait PackedField:
}
}
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct Singleton<F: Field>(pub F);
impl<F: Field> PackedField for F {
type FieldType = Self;
impl<F: Field> Add<Self> for Singleton<F> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self(self.0 + rhs.0)
}
}
impl<F: Field> Add<F> for Singleton<F> {
type Output = Self;
fn add(self, rhs: F) -> Self {
self + Self::broadcast(rhs)
}
}
impl<F: Field> AddAssign<Self> for Singleton<F> {
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs;
}
}
impl<F: Field> AddAssign<F> for Singleton<F> {
fn add_assign(&mut self, rhs: F) {
*self = *self + rhs;
}
}
impl<F: Field> Debug for Singleton<F> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "({:?})", self.0)
}
}
impl<F: Field> Default for Singleton<F> {
fn default() -> Self {
Self::zero()
}
}
impl<F: Field> Mul<Self> for Singleton<F> {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
Self(self.0 * rhs.0)
}
}
impl<F: Field> Mul<F> for Singleton<F> {
type Output = Self;
fn mul(self, rhs: F) -> Self {
self * Self::broadcast(rhs)
}
}
impl<F: Field> MulAssign<Self> for Singleton<F> {
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}
impl<F: Field> MulAssign<F> for Singleton<F> {
fn mul_assign(&mut self, rhs: F) {
*self = *self * rhs;
}
}
impl<F: Field> Neg for Singleton<F> {
type Output = Self;
fn neg(self) -> Self {
Self(-self.0)
}
}
impl<F: Field> Product for Singleton<F> {
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
Self(iter.map(|x| x.0).product())
}
}
impl<F: Field> PackedField for Singleton<F> {
const LOG2_WIDTH: usize = 0;
type FieldType = F;
fn broadcast(x: F) -> Self {
Self(x)
fn broadcast(x: Self::FieldType) -> Self {
x
}
fn from_arr(arr: [Self::FieldType; Self::WIDTH]) -> Self {
Self(arr[0])
arr[0]
}
fn to_arr(&self) -> [Self::FieldType; Self::WIDTH] {
[self.0]
[*self]
}
fn from_slice(slice: &[Self::FieldType]) -> Self {
assert!(slice.len() == 1);
Self(slice[0])
assert_eq!(slice.len(), 1);
slice[0]
}
fn to_vec(&self) -> Vec<Self::FieldType> {
vec![self.0]
vec![*self]
}
fn interleave(&self, other: Self, r: usize) -> (Self, Self) {
match r {
0 => (*self, other), // This is a no-op whenever r == LOG2_WIDTH.
_ => panic!("r cannot be more than LOG2_WIDTH"),
if r == 0 {
(*self, other)
} else {
panic!("r > LOG2_WIDTH");
}
}
fn square(&self) -> Self {
Self(self.0.square())
}
}
impl<F: Field> Sub<Self> for Singleton<F> {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
Self(self.0 - rhs.0)
}
}
impl<F: Field> Sub<F> for Singleton<F> {
type Output = Self;
fn sub(self, rhs: F) -> Self {
self - Self::broadcast(rhs)
}
}
impl<F: Field> SubAssign<Self> for Singleton<F> {
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}
impl<F: Field> SubAssign<F> for Singleton<F> {
fn sub_assign(&mut self, rhs: F) {
*self = *self - rhs;
}
}
impl<F: Field> Sum for Singleton<F> {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
Self(iter.map(|x| x.0).sum())
}
}