/ fields / src / macros.rs
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  }