|
| 1 | +pub mod impl_babybear { |
| 2 | + use crate::array_try_from_uniform_bytes; |
| 3 | + use p3::{ |
| 4 | + self, |
| 5 | + babybear::{BabyBear, Poseidon2BabyBear}, |
| 6 | + challenger::DuplexChallenger, |
| 7 | + field::{ |
| 8 | + BasedVectorSpace, Field, PackedValue, PrimeCharacteristicRing, PrimeField32, |
| 9 | + TwoAdicField, |
| 10 | + extension::{BinomialExtensionField, BinomiallyExtendable}, |
| 11 | + }, |
| 12 | + poseidon2::ExternalLayerConstants, |
| 13 | + }; |
| 14 | + |
| 15 | + use crate::{ |
| 16 | + ExtensionField, FieldFrom, FieldInto, FromUniformBytes, PoseidonField, SmallField, |
| 17 | + impl_from_uniform_bytes_for_binomial_extension, |
| 18 | + }; |
| 19 | + |
| 20 | + pub type BabyBearExt4 = BinomialExtensionField<BabyBear, 4>; |
| 21 | + |
| 22 | + pub const POSEIDON2_BABYBEAR_WIDTH: usize = 16; |
| 23 | + pub const POSEIDON2_BABYBEAR_RATE: usize = 8; |
| 24 | + |
| 25 | + pub const BABYBEAR_RC16_EXTERNAL_INITIAL: [[BabyBear; 16]; 4] = BabyBear::new_2d_array([ |
| 26 | + [ |
| 27 | + 0x69cbb6af, 0x46ad93f9, 0x60a00f4e, 0x6b1297cd, 0x23189afe, 0x732e7bef, 0x72c246de, |
| 28 | + 0x2c941900, 0x0557eede, 0x1580496f, 0x3a3ea77b, 0x54f3f271, 0x0f49b029, 0x47872fe1, |
| 29 | + 0x221e2e36, 0x1ab7202e, |
| 30 | + ], |
| 31 | + [ |
| 32 | + 0x487779a6, 0x3851c9d8, 0x38dc17c0, 0x209f8849, 0x268dcee8, 0x350c48da, 0x5b9ad32e, |
| 33 | + 0x0523272b, 0x3f89055b, 0x01e894b2, 0x13ddedde, 0x1b2ef334, 0x7507d8b4, 0x6ceeb94e, |
| 34 | + 0x52eb6ba2, 0x50642905, |
| 35 | + ], |
| 36 | + [ |
| 37 | + 0x05453f3f, 0x06349efc, 0x6922787c, 0x04bfff9c, 0x768c714a, 0x3e9ff21a, 0x15737c9c, |
| 38 | + 0x2229c807, 0x0d47f88c, 0x097e0ecc, 0x27eadba0, 0x2d7d29e4, 0x3502aaa0, 0x0f475fd7, |
| 39 | + 0x29fbda49, 0x018afffd, |
| 40 | + ], |
| 41 | + [ |
| 42 | + 0x0315b618, 0x6d4497d1, 0x1b171d9e, 0x52861abd, 0x2e5d0501, 0x3ec8646c, 0x6e5f250a, |
| 43 | + 0x148ae8e6, 0x17f5fa4a, 0x3e66d284, 0x0051aa3b, 0x483f7913, 0x2cfe5f15, 0x023427ca, |
| 44 | + 0x2cc78315, 0x1e36ea47, |
| 45 | + ], |
| 46 | + ]); |
| 47 | + |
| 48 | + pub const BABYBEAR_RC16_EXTERNAL_FINAL: [[BabyBear; 16]; 4] = BabyBear::new_2d_array([ |
| 49 | + [ |
| 50 | + 0x7290a80d, 0x6f7e5329, 0x598ec8a8, 0x76a859a0, 0x6559e868, 0x657b83af, 0x13271d3f, |
| 51 | + 0x1f876063, 0x0aeeae37, 0x706e9ca6, 0x46400cee, 0x72a05c26, 0x2c589c9e, 0x20bd37a7, |
| 52 | + 0x6a2d3d10, 0x20523767, |
| 53 | + ], |
| 54 | + [ |
| 55 | + 0x5b8fe9c4, 0x2aa501d6, 0x1e01ac3e, 0x1448bc54, 0x5ce5ad1c, 0x4918a14d, 0x2c46a83f, |
| 56 | + 0x4fcf6876, 0x61d8d5c8, 0x6ddf4ff9, 0x11fda4d3, 0x02933a8f, 0x170eaf81, 0x5a9c314f, |
| 57 | + 0x49a12590, 0x35ec52a1, |
| 58 | + ], |
| 59 | + [ |
| 60 | + 0x58eb1611, 0x5e481e65, 0x367125c9, 0x0eba33ba, 0x1fc28ded, 0x066399ad, 0x0cbec0ea, |
| 61 | + 0x75fd1af0, 0x50f5bf4e, 0x643d5f41, 0x6f4fe718, 0x5b3cbbde, 0x1e3afb3e, 0x296fb027, |
| 62 | + 0x45e1547b, 0x4a8db2ab, |
| 63 | + ], |
| 64 | + [ |
| 65 | + 0x59986d19, 0x30bcdfa3, 0x1db63932, 0x1d7c2824, 0x53b33681, 0x0673b747, 0x038a98a3, |
| 66 | + 0x2c5bce60, 0x351979cd, 0x5008fb73, 0x547bca78, 0x711af481, 0x3f93bf64, 0x644d987b, |
| 67 | + 0x3c8bcd87, 0x608758b8, |
| 68 | + ], |
| 69 | + ]); |
| 70 | + |
| 71 | + pub const BABYBEAR_RC16_INTERNAL: [BabyBear; 13] = BabyBear::new_array([ |
| 72 | + 0x5a8053c0, 0x693be639, 0x3858867d, 0x19334f6b, 0x128f0fd8, 0x4e2b1ccb, 0x61210ce0, |
| 73 | + 0x3c318939, 0x0b5b2f22, 0x2edb11d5, 0x213effdf, 0x0cac4606, 0x241af16d, |
| 74 | + ]); |
| 75 | + |
| 76 | + impl FieldFrom<u64> for BabyBear { |
| 77 | + fn from_v(v: u64) -> Self { |
| 78 | + Self::from_u64(v) |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + impl FieldFrom<u64> for BabyBearExt4 { |
| 83 | + fn from_v(v: u64) -> Self { |
| 84 | + Self::from_u64(v) |
| 85 | + } |
| 86 | + } |
| 87 | + |
| 88 | + impl FieldInto<BabyBear> for BabyBear { |
| 89 | + fn into_f(self) -> BabyBear { |
| 90 | + self |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + impl PoseidonField for BabyBear { |
| 95 | + type P = Poseidon2BabyBear<POSEIDON2_BABYBEAR_WIDTH>; |
| 96 | + type T = DuplexChallenger<Self, Self::P, POSEIDON2_BABYBEAR_WIDTH, POSEIDON2_BABYBEAR_RATE>; |
| 97 | + fn get_default_challenger() -> Self::T { |
| 98 | + let p = Poseidon2BabyBear::new( |
| 99 | + ExternalLayerConstants::new( |
| 100 | + BABYBEAR_RC16_EXTERNAL_INITIAL.to_vec(), |
| 101 | + BABYBEAR_RC16_EXTERNAL_FINAL.to_vec(), |
| 102 | + ), |
| 103 | + BABYBEAR_RC16_INTERNAL.to_vec(), |
| 104 | + ); |
| 105 | + DuplexChallenger::< |
| 106 | + Self, |
| 107 | + Self::P, |
| 108 | + POSEIDON2_BABYBEAR_WIDTH, |
| 109 | + POSEIDON2_BABYBEAR_RATE, |
| 110 | + >::new(p) |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + impl FromUniformBytes for BabyBear { |
| 115 | + type Bytes = [u8; 8]; |
| 116 | + |
| 117 | + fn try_from_uniform_bytes(bytes: [u8; 8]) -> Option<Self> { |
| 118 | + let value = u32::from_le_bytes(bytes[..4].try_into().unwrap()); |
| 119 | + let is_canonical = value < Self::ORDER_U32; |
| 120 | + is_canonical.then(|| Self::from_u32(value)) |
| 121 | + } |
| 122 | + } |
| 123 | + |
| 124 | + impl SmallField for BabyBear { |
| 125 | + const MODULUS_U64: u64 = Self::ORDER_U32 as u64; |
| 126 | + |
| 127 | + /// Convert a byte string into a list of field elements |
| 128 | + fn bytes_to_field_elements(bytes: &[u8]) -> Vec<Self> { |
| 129 | + bytes |
| 130 | + .chunks(8) |
| 131 | + .map(|chunk| { |
| 132 | + let mut array = [0u8; 8]; |
| 133 | + array[..chunk.len()].copy_from_slice(chunk); |
| 134 | + unsafe { std::ptr::read_unaligned(array.as_ptr() as *const u64) } |
| 135 | + }) |
| 136 | + .map(Self::from_u64) |
| 137 | + .collect::<Vec<_>>() |
| 138 | + } |
| 139 | + |
| 140 | + /// Convert a field elements to a u64. |
| 141 | + fn to_canonical_u64(&self) -> u64 { |
| 142 | + self.as_canonical_u32() as u64 |
| 143 | + } |
| 144 | + } |
| 145 | + |
| 146 | + impl_from_uniform_bytes_for_binomial_extension!(p3::babybear::BabyBear, 4); |
| 147 | + |
| 148 | + impl ExtensionField for BabyBearExt4 { |
| 149 | + const DEGREE: usize = 4; |
| 150 | + const MULTIPLICATIVE_GENERATOR: Self = <BabyBearExt4 as Field>::GENERATOR; |
| 151 | + const TWO_ADICITY: usize = BabyBear::TWO_ADICITY; |
| 152 | + // Passing two-adacity itself to this function will get the root of unity |
| 153 | + // with the largest order, i.e., order = 2^two-adacity. |
| 154 | + const BASE_TWO_ADIC_ROOT_OF_UNITY: Self::BaseField = BabyBear::new(0x78000000); |
| 155 | + const TWO_ADIC_ROOT_OF_UNITY: Self = |
| 156 | + BinomialExtensionField::new_unchecked([BabyBear::new(0x78000000); 4]); |
| 157 | + // non-residue is the value w such that the extension field is |
| 158 | + // F[X]/(X^2 - w) |
| 159 | + const NONRESIDUE: Self::BaseField = <BabyBear as BinomiallyExtendable<4>>::W; |
| 160 | + |
| 161 | + type BaseField = BabyBear; |
| 162 | + |
| 163 | + fn from_bases(bases: &[BabyBear]) -> Self { |
| 164 | + debug_assert_eq!(bases.len(), 2); |
| 165 | + Self::from_basis_coefficients_slice(bases) |
| 166 | + } |
| 167 | + |
| 168 | + fn as_bases(&self) -> &[BabyBear] { |
| 169 | + self.as_basis_coefficients_slice() |
| 170 | + } |
| 171 | + |
| 172 | + /// Convert limbs into self |
| 173 | + fn from_limbs(limbs: &[Self::BaseField]) -> Self { |
| 174 | + Self::from_bases(&limbs[0..4]) |
| 175 | + } |
| 176 | + |
| 177 | + fn to_canonical_u64_vec(&self) -> Vec<u64> { |
| 178 | + self.as_basis_coefficients_slice() |
| 179 | + .iter() |
| 180 | + .map(|v: &Self::BaseField| v.as_canonical_u32() as u64) |
| 181 | + .collect() |
| 182 | + } |
| 183 | + } |
| 184 | +} |
0 commit comments