macros.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the deltavm library. 3 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 8 // http://www.apache.org/licenses/LICENSE-2.0 9 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #[macro_export] 17 macro_rules! field { 18 ($name:ident, $c0:expr) => { 19 $name { 0: $c0, 1: std::marker::PhantomData } 20 }; 21 ($name:ident, $c0:expr, $c1:expr $(,)?) => { 22 $name { c0: $c0, c1: $c1 } 23 }; 24 ($name:ident, $c0:expr, $c1:expr, $c2:expr $(,)?) => { 25 $name { c0: $c0, c1: $c1, c2: $c2 } 26 }; 27 } 28 29 macro_rules! impl_field_to_biginteger { 30 ($field: ident, $biginteger: ident, $parameters: ident) => { 31 #[allow(clippy::from_over_into)] 32 impl<P: $parameters> Into<$biginteger> for $field<P> { 33 fn into(self) -> $biginteger { 34 self.to_bigint() 35 } 36 } 37 }; 38 } 39 40 macro_rules! impl_primefield_standard_sample { 41 ($field: ident, $params: ident) => { 42 impl<P: $params> rand::distributions::Distribution<$field<P>> for rand::distributions::Standard { 43 #[inline] 44 fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> $field<P> { 45 loop { 46 let mut tmp = $field(rng.sample(rand::distributions::Standard), PhantomData); 47 // Mask away the unused bits at the beginning. 48 tmp.0.as_mut().last_mut().map(|val| *val &= u64::MAX >> P::REPR_SHAVE_BITS); 49 50 if tmp.is_valid() { 51 return tmp; 52 } 53 } 54 } 55 } 56 }; 57 } 58 59 macro_rules! impl_primefield_from_int { 60 ($field: ident, u128, $params: ident) => { 61 impl<P: $params> From<u128> for $field<P> { 62 /// Attempts to convert an integer into a field element. 63 /// Panics if the provided integer is invalid (e.g. larger than the field modulus). 64 fn from(other: u128) -> Self { 65 let upper = (other >> 64) as u64; 66 let lower = ((other << 64) >> 64) as u64; 67 let mut default_int = P::BigInteger::default(); 68 default_int.0[0] = lower; 69 default_int.0[1] = upper; 70 Self::from_bigint(default_int).unwrap() 71 } 72 } 73 }; 74 ($field: ident, $int: ident, $params: ident) => { 75 impl<P: $params> From<$int> for $field<P> { 76 /// Attempts to convert an integer into a field element. 77 /// Panics if the provided integer is invalid (e.g. larger than the field modulus). 78 fn from(other: $int) -> Self { 79 Self::from_bigint(P::BigInteger::from(u64::from(other))).unwrap() 80 } 81 } 82 }; 83 } 84 85 macro_rules! sqrt_impl { 86 ($Self:ident, $P:tt, $self:expr) => {{ 87 use crate::LegendreSymbol::*; 88 // https://eprint.iacr.org/2020/1407.pdf (page 4, algorithm 1) 89 match $self.legendre() { 90 Zero => Some(*$self), 91 QuadraticNonResidue => None, 92 QuadraticResidue => { 93 let n = $P::TWO_ADICITY as u64; 94 // `T` is equivalent to `m` in the paper. 95 let v = $self.pow($P::T_MINUS_ONE_DIV_TWO); 96 let x = *$self * v.square(); 97 98 let k = (n - 1).isqrt(); 99 // It's important that k_2 results in a number which makes `l_minus_one_times_k` 100 // divisible by `k`, because the native arithmetic will not match the field 101 // arithmetic otherwise (native numbers will divide and round down, but field 102 // elements will end up nowhere near the native number). 103 let k_2 = if n % 2 == 0 { k / 2 } else { (n - 1) % k }; 104 let k_1 = k - k_2; 105 let l_minus_one_times_k = n - 1 - k_2; 106 let l_minus_one = l_minus_one_times_k / k; 107 let l = l_minus_one + 1; 108 109 let l_s = 110 || std::iter::repeat(l_minus_one).take(k_1 as usize).chain(std::iter::repeat(l).take(k_2 as usize)); 111 112 let mut l_sum = 0; 113 let x_s = l_s().take((k as usize) - 1).map(|l| { 114 l_sum += l; 115 x.pow(BigInteger::from(2u64.pow((n - 1 - l_sum) as u32))) 116 }); 117 let x_s = x_s.chain(Some(x)); 118 119 let find = |delta: $Self| -> u64 { 120 let mut mu = delta; 121 let mut i = 0; 122 while mu != -$Self::one() { 123 mu.square_in_place(); 124 i += 1; 125 } 126 i 127 }; 128 129 let eval = |mut delta: $Self| -> u64 { 130 let mut s = 0u64; 131 while delta != $Self::one() { 132 let i = find(delta); 133 let n_minus_one_minus_i = n - 1 - i; 134 s += 2u64.pow(n_minus_one_minus_i as u32); 135 if i > 0 { 136 delta *= $Self($P::POWERS_OF_ROOTS_OF_UNITY[n_minus_one_minus_i as usize], PhantomData); 137 } else { 138 delta = -delta; 139 } 140 } 141 s 142 }; 143 144 let calculate_gamma = |i: usize, q_s: &[u64], last: bool| -> $Self { 145 let mut gamma = $Self::one(); 146 if i != 0 { 147 q_s.iter().zip(l_s()).enumerate().for_each(|(j, (q, l))| { 148 let mut kappa = l_s().take(j).sum::<u64>() + 1 + l_s().skip(i + 1).sum::<u64>(); 149 if last { 150 kappa -= 1; 151 } 152 let mut value = *q; 153 (0..l as usize).for_each(|k| { 154 let bit = value & 1 == 1; 155 if bit { 156 gamma *= $Self($P::POWERS_OF_ROOTS_OF_UNITY[(kappa as usize) + k], PhantomData); 157 } 158 value = value.wrapping_shr(1u32); 159 }); 160 }); 161 } 162 gamma 163 }; 164 165 let mut q_s = Vec::<u64>::with_capacity(k as usize); 166 let two_to_n_minus_l = 2u64.pow((n - l) as u32); 167 let two_to_n_minus_l_minus_one = 2u64.pow((n - l_minus_one) as u32); 168 x_s.enumerate().for_each(|(i, x)| { 169 // Calculate g^t. 170 // This algorithm deviates from the standard description in the paper, and is 171 // explained in detail in page 6, in section 2.1. 172 let gamma = calculate_gamma(i, &q_s, false); 173 let alpha = x * gamma; 174 q_s.push( 175 eval(alpha) / if i < k_1 as usize { two_to_n_minus_l_minus_one } else { two_to_n_minus_l }, 176 ); 177 }); 178 179 // Calculate g^{t/2}. 180 let gamma = calculate_gamma(k as usize, &q_s, true); 181 Some(*$self * v * gamma) 182 } 183 } 184 }}; 185 } 186 187 macro_rules! impl_primefield_serializer { 188 ($field: ident, $params: ident, $byte_size: expr) => { 189 impl<P: $params> CanonicalSerializeWithFlags for $field<P> { 190 #[allow(unused_qualifications)] 191 fn serialize_with_flags<W: std::io::Write, F: deltavm_utilities::Flags>( 192 &self, 193 mut writer: W, 194 flags: F, 195 ) -> Result<(), deltavm_utilities::serialize::SerializationError> { 196 use deltavm_utilities::serialize::{SerializationError, number_of_bits_and_bytes}; 197 // All reasonable `Flags` should be less than 8 bits in size 198 // (256 values are enough for anyone!) 199 if F::BIT_SIZE > 8 { 200 return Err(SerializationError::NotEnoughSpace); 201 } 202 203 // Calculate the number of bytes required to represent a field element 204 // serialized with `flags`. If `F::BIT_SIZE < 8`, 205 // this is at most `$byte_size + 1` 206 let output_byte_size = number_of_bits_and_bytes(P::MODULUS_BITS as usize + F::BIT_SIZE).1; 207 208 // Write out `self` to a temporary buffer. 209 // The size of the buffer is $byte_size + 1 because `F::BIT_SIZE` 210 // is at most 8 bits. 211 let mut bytes = [0u8; $byte_size + 1]; 212 self.write_le(&mut bytes[..$byte_size])?; 213 214 // Mask out the bits of the last byte that correspond to the flag. 215 bytes[output_byte_size - 1] |= flags.u8_bitmask(); 216 217 writer.write_all(&bytes[..output_byte_size])?; 218 Ok(()) 219 } 220 221 // Let `m = 8 * n` for some `n` be the smallest multiple of 8 greater 222 // than `P::MODULUS_BITS`. 223 // If `(m - P::MODULUS_BITS) >= F::BIT_SIZE` , then this method returns `n`; 224 // otherwise, it returns `n + 1`. 225 fn serialized_size_with_flags<F: deltavm_utilities::Flags>(&self) -> usize { 226 deltavm_utilities::serialize::number_of_bits_and_bytes(P::MODULUS_BITS as usize + F::BIT_SIZE).1 227 } 228 } 229 230 impl<P: $params> CanonicalSerialize for $field<P> { 231 #[allow(unused_qualifications)] 232 #[inline] 233 fn serialize_with_mode<W: std::io::Write>( 234 &self, 235 writer: W, 236 _compress: deltavm_utilities::serialize::Compress, 237 ) -> Result<(), deltavm_utilities::serialize::SerializationError> { 238 self.serialize_with_flags(writer, deltavm_utilities::serialize::EmptyFlags) 239 } 240 241 #[inline] 242 fn serialized_size(&self, _compress: deltavm_utilities::serialize::Compress) -> usize { 243 use deltavm_utilities::EmptyFlags; 244 self.serialized_size_with_flags::<EmptyFlags>() 245 } 246 } 247 248 impl<P: $params> $field<P> { 249 const SERIALIZED_SIZE: usize = 250 deltavm_utilities::serialize::number_of_bits_to_number_of_bytes(P::MODULUS_BITS as usize); 251 } 252 253 impl<P: $params> CanonicalDeserializeWithFlags for $field<P> { 254 #[allow(unused_qualifications)] 255 fn deserialize_with_flags<R: std::io::Read, F: deltavm_utilities::Flags>( 256 mut reader: R, 257 ) -> Result<(Self, F), deltavm_utilities::serialize::SerializationError> { 258 use deltavm_utilities::serialize::SerializationError; 259 // All reasonable `Flags` should be less than 8 bits in size 260 // (256 values are enough for anyone!) 261 if F::BIT_SIZE > 8 { 262 return Err(SerializationError::NotEnoughSpace); 263 } 264 // Calculate the number of bytes required to represent a field element 265 // serialized with `flags`. If `F::BIT_SIZE < 8`, 266 // this is at most `$byte_size + 1` 267 let output_byte_size = Self::SERIALIZED_SIZE; 268 269 let mut masked_bytes = [0; $byte_size + 1]; 270 reader.read_exact(&mut masked_bytes[..output_byte_size])?; 271 272 let flags = F::from_u8_remove_flags(&mut masked_bytes[output_byte_size - 1]) 273 .ok_or(SerializationError::UnexpectedFlags)?; 274 275 Ok((Self::read_le(&masked_bytes[..])?, flags)) 276 } 277 } 278 279 impl<P: $params> deltavm_utilities::Valid for $field<P> { 280 fn check(&self) -> Result<(), deltavm_utilities::SerializationError> { 281 Ok(()) 282 } 283 284 fn batch_check<'a>( 285 _batch: impl Iterator<Item = &'a Self> + Send, 286 ) -> Result<(), deltavm_utilities::SerializationError> 287 where 288 Self: 'a, 289 { 290 Ok(()) 291 } 292 } 293 294 impl<P: $params> CanonicalDeserialize for $field<P> { 295 #[allow(unused_qualifications)] 296 fn deserialize_with_mode<R: std::io::Read>( 297 reader: R, 298 _compress: deltavm_utilities::serialize::Compress, 299 _validate: deltavm_utilities::serialize::Validate, 300 ) -> Result<Self, deltavm_utilities::SerializationError> { 301 use deltavm_utilities::serialize::EmptyFlags; 302 Self::deserialize_with_flags::<R, EmptyFlags>(reader).map(|(r, _)| r) 303 } 304 } 305 306 impl<P: $params> serde::Serialize for $field<P> { 307 fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 308 let mut bytes = Vec::with_capacity(Self::SERIALIZED_SIZE); 309 self.serialize_uncompressed(&mut bytes).map_err(serde::ser::Error::custom)?; 310 311 if serializer.is_human_readable() { 312 serializer.collect_str(self) 313 } else { 314 deltavm_utilities::ToBytesSerializer::serialize(&bytes, serializer) 315 } 316 } 317 } 318 319 impl<'de, P: $params> serde::Deserialize<'de> for $field<P> { 320 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { 321 match deserializer.is_human_readable() { 322 true => { 323 let s: String = serde::Deserialize::deserialize(deserializer)?; 324 core::str::FromStr::from_str(&s).map_err(serde::de::Error::custom) 325 } 326 false => { 327 struct SerVisitor<P>(std::marker::PhantomData<P>); 328 329 impl<'de, P: $params> serde::de::Visitor<'de> for SerVisitor<P> { 330 type Value = $field<P>; 331 332 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 333 formatter.write_str("a valid field element") 334 } 335 336 fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error> 337 where 338 S: serde::de::SeqAccess<'de>, 339 { 340 let len = $field::<P>::SERIALIZED_SIZE; 341 let bytes = (0..len) 342 .map(|_| { 343 seq.next_element()? 344 .ok_or_else(|| serde::de::Error::custom("could not read bytes")) 345 }) 346 .collect::<Result<Vec<_>, _>>()?; 347 348 CanonicalDeserialize::deserialize_compressed(&*bytes).map_err(serde::de::Error::custom) 349 } 350 } 351 352 let visitor = SerVisitor(std::marker::PhantomData); 353 deserializer.deserialize_tuple(Self::SERIALIZED_SIZE, visitor) 354 } 355 } 356 } 357 } 358 }; 359 } 360 361 macro_rules! impl_field_from_random_bytes_with_flags { 362 ($u64_limbs: expr) => { 363 #[inline] 364 fn from_random_bytes_with_flags<F: deltavm_utilities::Flags>(bytes: &[u8]) -> Option<(Self, F)> { 365 (F::BIT_SIZE <= 8) 366 .then(|| { 367 let mut result_bytes = [0u8; $u64_limbs * 8 + 1]; 368 // Copy the input into a temporary buffer. 369 result_bytes.iter_mut().zip(bytes).for_each(|(result, input)| { 370 *result = *input; 371 }); 372 // This mask retains everything in the last limb 373 // that is below `P::MODULUS_BITS`. 374 let last_limb_mask = (u64::MAX >> P::REPR_SHAVE_BITS).to_le_bytes(); 375 let mut last_bytes_mask = [0u8; 9]; 376 last_bytes_mask[..8].copy_from_slice(&last_limb_mask); 377 378 // Length of the buffer containing the field element and the flag. 379 let output_byte_size = Self::SERIALIZED_SIZE; 380 // Location of the flag is the last byte of the serialized 381 // form of the field element. 382 let flag_location = output_byte_size - 1; 383 384 // At which byte is the flag located in the last limb? 385 let flag_location_in_last_limb = flag_location - (8 * ($u64_limbs - 1)); 386 387 // Take all but the last 9 bytes. 388 let last_bytes = &mut result_bytes[8 * ($u64_limbs - 1)..]; 389 390 // The mask only has the last `F::BIT_SIZE` bits set 391 let flags_mask = u8::MAX.checked_shl(8 - (F::BIT_SIZE as u32)).unwrap_or(0); 392 393 // Mask away the remaining bytes, and try to reconstruct the 394 // flag 395 let mut flags: u8 = 0; 396 for (i, (b, m)) in last_bytes.iter_mut().zip(&last_bytes_mask).enumerate() { 397 if i == flag_location_in_last_limb { 398 flags = *b & flags_mask 399 } 400 *b &= m; 401 } 402 Self::deserialize_uncompressed(&result_bytes[..($u64_limbs * 8)]) 403 .ok() 404 .and_then(|f| F::from_u8(flags).map(|flag| (f, flag))) 405 }) 406 .flatten() 407 } 408 }; 409 } 410 411 /// Implements Add, Sub, AddAssign, and SubAssign on Self by deferring to an implementation on &Self 412 #[macro_export] 413 macro_rules! impl_add_sub_from_field_ref { 414 ($type: ident, $params: ident) => { 415 #[allow(unused_qualifications)] 416 impl<P: $params> core::ops::Add<Self> for $type<P> { 417 type Output = Self; 418 419 #[inline] 420 fn add(self, other: Self) -> Self { 421 let mut result = self; 422 result.add_assign(&other); 423 result 424 } 425 } 426 427 #[allow(unused_qualifications)] 428 impl<P: $params> core::ops::Sub<Self> for $type<P> { 429 type Output = Self; 430 431 #[inline] 432 fn sub(self, other: Self) -> Self { 433 let mut result = self; 434 result.sub_assign(&other); 435 result 436 } 437 } 438 439 #[allow(unused_qualifications)] 440 impl<P: $params> core::ops::Add<&&Self> for $type<P> { 441 type Output = Self; 442 443 #[inline] 444 fn add(self, other: &&Self) -> Self { 445 let mut result = self; 446 result.add_assign(*other); 447 result 448 } 449 } 450 451 #[allow(unused_qualifications)] 452 impl<P: $params> core::ops::Sub<&&Self> for $type<P> { 453 type Output = Self; 454 455 #[inline] 456 fn sub(self, other: &&Self) -> Self { 457 let mut result = self; 458 result.sub_assign(*other); 459 result 460 } 461 } 462 463 #[allow(unused_qualifications)] 464 impl<'a, P: $params> core::ops::Add<&'a mut Self> for $type<P> { 465 type Output = Self; 466 467 #[inline] 468 fn add(self, other: &'a mut Self) -> Self { 469 let mut result = self; 470 result.add_assign(&*other); 471 result 472 } 473 } 474 475 #[allow(unused_qualifications)] 476 impl<'a, P: $params> core::ops::Sub<&'a mut Self> for $type<P> { 477 type Output = Self; 478 479 #[inline] 480 fn sub(self, other: &'a mut Self) -> Self { 481 let mut result = self; 482 result.sub_assign(&*other); 483 result 484 } 485 } 486 487 #[allow(unused_qualifications)] 488 impl<P: $params> core::ops::AddAssign<Self> for $type<P> { 489 fn add_assign(&mut self, other: Self) { 490 self.add_assign(&other) 491 } 492 } 493 494 #[allow(unused_qualifications)] 495 impl<P: $params> core::ops::SubAssign<Self> for $type<P> { 496 fn sub_assign(&mut self, other: Self) { 497 self.sub_assign(&other) 498 } 499 } 500 501 #[allow(unused_qualifications)] 502 impl<P: $params> core::ops::AddAssign<&&Self> for $type<P> { 503 fn add_assign(&mut self, other: &&Self) { 504 self.add_assign(*other) 505 } 506 } 507 508 #[allow(unused_qualifications)] 509 impl<P: $params> core::ops::SubAssign<&&Self> for $type<P> { 510 fn sub_assign(&mut self, other: &&Self) { 511 self.sub_assign(*other) 512 } 513 } 514 515 #[allow(unused_qualifications)] 516 impl<'a, P: $params> core::ops::AddAssign<&'a mut Self> for $type<P> { 517 fn add_assign(&mut self, other: &'a mut Self) { 518 self.add_assign(&*other) 519 } 520 } 521 522 #[allow(unused_qualifications)] 523 impl<'a, P: $params> core::ops::SubAssign<&'a mut Self> for $type<P> { 524 fn sub_assign(&mut self, other: &'a mut Self) { 525 self.sub_assign(&*other) 526 } 527 } 528 529 #[allow(unused_qualifications)] 530 impl<P: $params> core::iter::Sum<Self> for $type<P> { 531 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self { 532 iter.fold(Self::zero(), core::ops::Add::add) 533 } 534 } 535 536 #[allow(unused_qualifications)] 537 impl<'a, P: $params> core::iter::Sum<&'a Self> for $type<P> { 538 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self { 539 iter.fold(Self::zero(), core::ops::Add::add) 540 } 541 } 542 }; 543 } 544 545 /// Implements Mul, Div, MulAssign, and DivAssign on Self by deferring to an implementation on &Self 546 #[macro_export] 547 macro_rules! impl_mul_div_from_field_ref { 548 ($type: ident, $params: ident) => { 549 #[allow(unused_qualifications)] 550 impl<P: $params> core::ops::Mul<Self> for $type<P> { 551 type Output = Self; 552 553 #[inline] 554 fn mul(self, other: Self) -> Self { 555 let mut result = self; 556 result.mul_assign(&other); 557 result 558 } 559 } 560 561 #[allow(unused_qualifications)] 562 impl<P: $params> core::ops::Div<Self> for $type<P> { 563 type Output = Self; 564 565 #[inline] 566 fn div(self, other: Self) -> Self { 567 let mut result = self; 568 result.div_assign(&other); 569 result 570 } 571 } 572 573 #[allow(unused_qualifications)] 574 impl<P: $params> core::ops::Mul<&&Self> for $type<P> { 575 type Output = Self; 576 577 #[inline] 578 fn mul(self, other: &&Self) -> Self { 579 let mut result = self; 580 result.mul_assign(*other); 581 result 582 } 583 } 584 585 #[allow(unused_qualifications)] 586 impl<P: $params> core::ops::Div<&&Self> for $type<P> { 587 type Output = Self; 588 589 #[inline] 590 fn div(self, other: &&Self) -> Self { 591 let mut result = self; 592 result.div_assign(*other); 593 result 594 } 595 } 596 597 #[allow(unused_qualifications)] 598 impl<'a, P: $params> core::ops::Mul<&'a mut Self> for $type<P> { 599 type Output = Self; 600 601 #[inline] 602 fn mul(self, other: &'a mut Self) -> Self { 603 let mut result = self; 604 result.mul_assign(&*other); 605 result 606 } 607 } 608 609 #[allow(unused_qualifications)] 610 impl<'a, P: $params> core::ops::Div<&'a mut Self> for $type<P> { 611 type Output = Self; 612 613 #[inline] 614 fn div(self, other: &'a mut Self) -> Self { 615 let mut result = self; 616 result.div_assign(&*other); 617 result 618 } 619 } 620 621 #[allow(unused_qualifications)] 622 impl<P: $params> core::ops::MulAssign<Self> for $type<P> { 623 fn mul_assign(&mut self, other: Self) { 624 self.mul_assign(&other) 625 } 626 } 627 628 #[allow(unused_qualifications)] 629 impl<P: $params> core::ops::DivAssign<Self> for $type<P> { 630 fn div_assign(&mut self, other: Self) { 631 self.div_assign(&other) 632 } 633 } 634 635 #[allow(unused_qualifications)] 636 impl<P: $params> core::ops::MulAssign<&&Self> for $type<P> { 637 fn mul_assign(&mut self, other: &&Self) { 638 self.mul_assign(*other) 639 } 640 } 641 642 #[allow(unused_qualifications)] 643 impl<P: $params> core::ops::DivAssign<&&Self> for $type<P> { 644 fn div_assign(&mut self, other: &&Self) { 645 self.div_assign(*other) 646 } 647 } 648 649 #[allow(unused_qualifications)] 650 impl<'a, P: $params> core::ops::MulAssign<&'a mut Self> for $type<P> { 651 fn mul_assign(&mut self, other: &'a mut Self) { 652 self.mul_assign(&*other) 653 } 654 } 655 656 #[allow(unused_qualifications)] 657 impl<'a, P: $params> core::ops::DivAssign<&'a mut Self> for $type<P> { 658 fn div_assign(&mut self, other: &'a mut Self) { 659 self.div_assign(&*other) 660 } 661 } 662 663 #[allow(unused_qualifications)] 664 impl<P: $params> core::iter::Product<Self> for $type<P> { 665 fn product<I: Iterator<Item = Self>>(iter: I) -> Self { 666 iter.fold(Self::one(), core::ops::Mul::mul) 667 } 668 } 669 670 #[allow(unused_qualifications)] 671 impl<'a, P: $params> core::iter::Product<&'a Self> for $type<P> { 672 fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self { 673 iter.fold(Self::one(), Mul::mul) 674 } 675 } 676 }; 677 }