From db3171bb81bb56620207fc9b7809586ff0a6c8c4 Mon Sep 17 00:00:00 2001 From: Jakub Nabaglo Date: Wed, 8 Sep 2021 11:56:05 -0700 Subject: [PATCH] Conversion to/from statically-sized arrays --- src/field/packed_crandall_avx2.rs | 83 +++++++++++++------------------ src/field/packed_field.rs | 11 ++-- 2 files changed, 41 insertions(+), 53 deletions(-) diff --git a/src/field/packed_crandall_avx2.rs b/src/field/packed_crandall_avx2.rs index 681ed1c7..83b4a8ab 100644 --- a/src/field/packed_crandall_avx2.rs +++ b/src/field/packed_crandall_avx2.rs @@ -136,26 +136,13 @@ impl PackedField for PackedCrandallAVX2 { } #[inline] - fn new_from_slice(arr: &[Self::FieldType]) -> Self { - if let [a, b, c, d] = arr { - let v = unsafe { _mm256_setr_epi64x(a.0 as i64, b.0 as i64, c.0 as i64, d.0 as i64) }; - Self::new(v) - } else { - panic!(); - } + fn from_arr(arr: [Self::FieldType; Self::WIDTH]) -> Self { + Self([arr[0].0, arr[1].0, arr[2].0, arr[3].0]) } + #[inline] - fn to_vec(&self) -> Vec { - let a = unsafe { _mm256_extract_epi64::<0>(self.get()) } as u64; - let b = unsafe { _mm256_extract_epi64::<1>(self.get()) } as u64; - let c = unsafe { _mm256_extract_epi64::<2>(self.get()) } as u64; - let d = unsafe { _mm256_extract_epi64::<3>(self.get()) } as u64; - vec![ - CrandallField(a), - CrandallField(b), - CrandallField(c), - CrandallField(d), - ] + fn to_arr(&self) -> [Self::FieldType; Self::WIDTH] { + [CrandallField(self.0[0]), CrandallField(self.0[1]), CrandallField(self.0[2]), CrandallField(self.0[3])] } #[inline] @@ -431,13 +418,13 @@ mod tests { use crate::field::crandall_field::CrandallField; use crate::field::packed_crandall_avx2::*; - const TEST_VALS_A: &[CrandallField] = &[ + const TEST_VALS_A: [CrandallField; 4] = [ CrandallField(14479013849828404771), CrandallField(9087029921428221768), CrandallField(2441288194761790662), CrandallField(5646033492608483824), ]; - const TEST_VALS_B: &[CrandallField] = &[ + const TEST_VALS_B: [CrandallField; 4] = [ CrandallField(17891926589593242302), CrandallField(11009798273260028228), CrandallField(2028722748960791447), @@ -446,15 +433,15 @@ mod tests { #[test] fn test_add() { - let packed_a = PackedCrandallAVX2::new_from_slice(TEST_VALS_A); - let packed_b = PackedCrandallAVX2::new_from_slice(TEST_VALS_B); + let packed_a = PackedCrandallAVX2::from_arr(TEST_VALS_A); + let packed_b = PackedCrandallAVX2::from_arr(TEST_VALS_B); let packed_res = packed_a + packed_b; - let arr_res = packed_res.to_vec(); + let arr_res = packed_res.to_arr(); let expected = TEST_VALS_A .iter() - .zip(TEST_VALS_B.iter()) - .map(|(&a, &b)| a + b); + .zip(TEST_VALS_B) + .map(|(&a, b)| a + b); for (exp, res) in expected.zip(arr_res) { assert_eq!(res, exp); } @@ -462,15 +449,15 @@ mod tests { #[test] fn test_mul() { - let packed_a = PackedCrandallAVX2::new_from_slice(TEST_VALS_A); - let packed_b = PackedCrandallAVX2::new_from_slice(TEST_VALS_B); + let packed_a = PackedCrandallAVX2::from_arr(TEST_VALS_A); + let packed_b = PackedCrandallAVX2::from_arr(TEST_VALS_B); let packed_res = packed_a * packed_b; - let arr_res = packed_res.to_vec(); + let arr_res = packed_res.to_arr(); let expected = TEST_VALS_A .iter() - .zip(TEST_VALS_B.iter()) - .map(|(&a, &b)| a * b); + .zip(TEST_VALS_B) + .map(|(&a, b)| a * b); for (exp, res) in expected.zip(arr_res) { assert_eq!(res, exp); } @@ -478,9 +465,9 @@ mod tests { #[test] fn test_neg() { - let packed_a = PackedCrandallAVX2::new_from_slice(TEST_VALS_A); + let packed_a = PackedCrandallAVX2::from_arr(TEST_VALS_A); let packed_res = -packed_a; - let arr_res = packed_res.to_vec(); + let arr_res = packed_res.to_arr(); let expected = TEST_VALS_A.iter().map(|&a| -a); for (exp, res) in expected.zip(arr_res) { @@ -490,12 +477,12 @@ mod tests { #[test] fn test_sub() { - let packed_a = PackedCrandallAVX2::new_from_slice(TEST_VALS_A); - let packed_b = PackedCrandallAVX2::new_from_slice(TEST_VALS_B); + let packed_a = PackedCrandallAVX2::from_arr(TEST_VALS_A); + let packed_b = PackedCrandallAVX2::from_arr(TEST_VALS_B); let packed_res = packed_a - packed_b; - let arr_res = packed_res.to_vec(); + let arr_res = packed_res.to_arr(); - let expected = TEST_VALS_A.iter().zip(TEST_VALS_B).map(|(&a, &b)| a - b); + let expected = TEST_VALS_A.iter().zip(TEST_VALS_B).map(|(&a, b)| a - b); for (exp, res) in expected.zip(arr_res) { assert_eq!(res, exp); } @@ -503,20 +490,20 @@ mod tests { #[test] fn test_interleave_is_involution() { - let packed_a = PackedCrandallAVX2::new_from_slice(TEST_VALS_A); - let packed_b = PackedCrandallAVX2::new_from_slice(TEST_VALS_B); + let packed_a = PackedCrandallAVX2::from_arr(TEST_VALS_A); + let packed_b = PackedCrandallAVX2::from_arr(TEST_VALS_B); { // Interleave, then deinterleave. let (x, y) = packed_a.interleave(packed_b, 0); let (res_a, res_b) = x.interleave(y, 0); - assert_eq!(res_a.to_vec(), TEST_VALS_A); - assert_eq!(res_b.to_vec(), TEST_VALS_B); + assert_eq!(res_a.to_arr(), TEST_VALS_A); + assert_eq!(res_b.to_arr(), TEST_VALS_B); } { let (x, y) = packed_a.interleave(packed_b, 1); let (res_a, res_b) = x.interleave(y, 1); - assert_eq!(res_a.to_vec(), TEST_VALS_A); - assert_eq!(res_b.to_vec(), TEST_VALS_B); + assert_eq!(res_a.to_arr(), TEST_VALS_A); + assert_eq!(res_b.to_arr(), TEST_VALS_B); } } @@ -559,17 +546,17 @@ mod tests { CrandallField(13), ]; - let packed_a = PackedCrandallAVX2::new_from_slice(&in_a); - let packed_b = PackedCrandallAVX2::new_from_slice(&in_b); + let packed_a = PackedCrandallAVX2::from_arr(in_a); + let packed_b = PackedCrandallAVX2::from_arr(in_b); { let (x0, y0) = packed_a.interleave(packed_b, 0); - assert_eq!(x0.to_vec()[..], int0_a); - assert_eq!(y0.to_vec()[..], int0_b); + assert_eq!(x0.to_arr(), int0_a); + assert_eq!(y0.to_arr(), int0_b); } { let (x1, y1) = packed_a.interleave(packed_b, 1); - assert_eq!(x1.to_vec()[..], int1_a); - assert_eq!(y1.to_vec()[..], int1_b); + assert_eq!(x1.to_arr(), int1_a); + assert_eq!(y1.to_arr(), int1_b); } } } diff --git a/src/field/packed_field.rs b/src/field/packed_field.rs index eaa8c5c7..b41e23a7 100644 --- a/src/field/packed_field.rs +++ b/src/field/packed_field.rs @@ -47,8 +47,8 @@ pub trait PackedField: fn broadcast(x: Self::FieldType) -> Self; - fn new_from_slice(arr: &[Self::FieldType]) -> Self; - fn to_vec(&self) -> Vec; + fn from_arr(arr: [Self::FieldType; Self::WIDTH]) -> Self; + fn to_arr(&self) -> [Self::FieldType; Self::WIDTH]; /// Take interpret two vectors as chunks of (1 << r) elements. Unpack and interleave those /// chunks. This is best seen with an example. If we have: @@ -175,11 +175,12 @@ impl PackedField for Singleton { Self(x) } - fn new_from_slice(arr: &[Self::FieldType]) -> Self { + fn from_arr(arr: [Self::FieldType; Self::WIDTH]) -> Self { Self(arr[0]) } - fn to_vec(&self) -> Vec { - vec![self.0] + + fn to_arr(&self) -> [Self::FieldType; Self::WIDTH] { + [self.0] } fn interleave(&self, other: Self, r: usize) -> (Self, Self) {