|
2 | 2 |
|
3 | 3 | //! Generic Field Traits
|
4 | 4 |
|
| 5 | +use core::iter::{Skip, Take}; |
5 | 6 | use core::{fmt, hash, iter, ops};
|
6 | 7 |
|
7 | 8 | /// A generic field.
|
@@ -88,6 +89,20 @@ pub trait Field:
|
88 | 89 | "bug: `ExtensionField::MULTIPLICATIVE_ORDER_FACTORS` did not include full group order"
|
89 | 90 | );
|
90 | 91 | }
|
| 92 | + |
| 93 | + /// Constructs an iterator over all the powers of an element from 0 onward. |
| 94 | + fn powers(self) -> Powers<Self> { Powers { base: self, next: Self::ONE } } |
| 95 | + |
| 96 | + /// Constructs an iterator over all the powers of an element within a given range. |
| 97 | + /// |
| 98 | + /// # Panics |
| 99 | + /// |
| 100 | + /// Panics if given a range whose start is greater than its end, or whose range |
| 101 | + /// is from 0 to `usize::MAX`. Its intended use is with [`crate::Checksum::ROOT_EXPONENTS`] |
| 102 | + /// for which neither of these conditions should ever be true. |
| 103 | + fn powers_range(self, range: ops::RangeInclusive<usize>) -> Take<Skip<Powers<Self>>> { |
| 104 | + self.powers().skip(*range.start()).take(*range.end() - range.start() + 1) |
| 105 | + } |
91 | 106 | }
|
92 | 107 |
|
93 | 108 | /// Trait describing a simple extension field (field obtained from another by
|
@@ -338,3 +353,35 @@ macro_rules! impl_ops_for_fe {
|
338 | 353 | };
|
339 | 354 | }
|
340 | 355 | pub(super) use impl_ops_for_fe;
|
| 356 | + |
| 357 | +/// An iterator over the powers of a field, starting from zero. |
| 358 | +/// |
| 359 | +/// This iterator starts from 1, but has an optimized version of [`Iterator::nth`] |
| 360 | +/// which allows efficient construction. |
| 361 | +pub struct Powers<F: Field> { |
| 362 | + base: F, |
| 363 | + next: F, |
| 364 | +} |
| 365 | + |
| 366 | +impl<F: Field> Iterator for Powers<F> { |
| 367 | + type Item = F; |
| 368 | + |
| 369 | + fn next(&mut self) -> Option<F> { |
| 370 | + let ret = Some(self.next.clone()); |
| 371 | + self.next *= &self.base; |
| 372 | + ret |
| 373 | + } |
| 374 | + |
| 375 | + /// Compute next by calling `F::powi`. |
| 376 | + /// |
| 377 | + /// The default implementation of `nth` will simply call the iterator `n` |
| 378 | + /// times, throwing away the result, which takes O(n) field multiplications. |
| 379 | + /// For a power iterator we can do much better, taking O(log(n)) multiplications. |
| 380 | + /// |
| 381 | + /// This is important because this method is called internally by `Iterator::skip`. |
| 382 | + fn nth(&mut self, n: usize) -> Option<F> { |
| 383 | + let ni64 = (n % F::MULTIPLICATIVE_ORDER) as i64; // cast ok since modulus should be small |
| 384 | + self.next *= self.base.powi(ni64); |
| 385 | + self.next() |
| 386 | + } |
| 387 | +} |
0 commit comments