Skip to main content

Polynomial

Struct Polynomial 

Source
struct Polynomial<M>(Vec<MInt<M>>)
where
    M: MIntDotProduct;

Tuple Fields§

§0: Vec<MInt<M>>

Implementations§

Source§

impl<M> Polynomial<M>
where M: MIntDotProduct,

Source

fn exact_div(self, rhs: &Self) -> Option<Self>

Examples found in repository?
crates/competitive/src/math/mint_matrix.rs (line 275)
255fn frobenius_decomposition<M>(
256    a: &Matrix<AddMulOperation<MInt<M>>>,
257    rng: &mut Xorshift,
258) -> Option<FrobeniusDecomposition<M>>
259where
260    M: MIntDotProduct + MIntConvert<u64>,
261{
262    let n = a.shape.0;
263    let mut rows = Vec::with_capacity(n);
264    let mut t = Vec::with_capacity(n);
265    let mut blocks: Vec<Polynomial<M>> = Vec::new();
266    while rows.len() < n {
267        let s = rows.len();
268        let v = (0..n).map(|_| MInt::from(rng.rand64())).collect();
269        let c = generate_frobenius_block(a, v, &mut rows, &mut t);
270        if rows.len() == s {
271            continue;
272        }
273        let p = Polynomial(c.0[s..].to_vec());
274        if c.0[..s].iter().any(|x| !x.is_zero()) {
275            let q = c.exact_div(&p)?;
276            let d = rows.len() - s;
277            let mut coefficients = q.0[..s].to_vec();
278            let mut shifts = Vec::with_capacity(d);
279            for _ in 0..d {
280                shifts.push(coefficients.clone());
281                let mut first = 0;
282                for block in &blocks {
283                    let len = block.0.len() - 1;
284                    let c = &mut coefficients[first..first + len];
285                    let last = c[len - 1];
286                    for j in (1..len).rev() {
287                        c[j] = c[j - 1] - last * block.0[j];
288                    }
289                    c[0] = -last * block.0[0];
290                    first += len;
291                }
292            }
293            let shifts: Matrix<AddMulOperation<MInt<M>>> = Matrix::from_vec(shifts);
294            if d < 32 {
295                let (previous, current) = t.split_at_mut(s);
296                for (shift, row) in shifts.data.iter().zip(current) {
297                    for (factor, source) in shift.iter().zip(previous.iter()) {
298                        if !factor.is_zero() {
299                            MInt::add_scaled_assign(row, source, factor);
300                        }
301                    }
302                }
303            } else {
304                let previous = Matrix::from_vec(t[..s].to_vec());
305                let correction = &shifts * &previous;
306                for (row, correction) in t[s..].iter_mut().zip(&correction.data) {
307                    for (x, &y) in row.iter_mut().zip(correction) {
308                        *x += y;
309                    }
310                }
311            }
312            for row in &mut rows[s..] {
313                // Keep the reduced vector fixed: T_new += S*T_old gives C_old -= C_new*S.
314                let (previous, current) = row.row[n..].split_at_mut(s);
315                for (&x, shift) in current.iter().zip(&shifts.data) {
316                    MInt::add_scaled_assign(previous, shift, &-x);
317                }
318            }
319        }
320        blocks.push(p);
321    }
322
323    let mut t_inv = vec![vec![MInt::zero(); n]; n];
324    for i in (0..n).rev() {
325        let row = &rows[i];
326        let mut c = row.row[n..].to_vec();
327        c.resize(n, MInt::zero());
328        for x in &mut c {
329            *x *= row.inv;
330        }
331        for next in &rows[i + 1..] {
332            let factor = -row.row[next.pivot] * row.inv;
333            if !factor.is_zero() {
334                MInt::add_scaled_assign(&mut c, &t_inv[next.pivot], &factor);
335            }
336        }
337        t_inv[row.pivot] = c;
338    }
339    Some(FrobeniusDecomposition {
340        t: Matrix::from_vec(t),
341        t_inv: Matrix::from_vec(t_inv),
342        blocks,
343    })
344}
Source

fn square_mod(&self, p: &Self) -> Self

Examples found in repository?
crates/competitive/src/math/mint_matrix.rs (line 242)
234    fn x_pow_mod(&self, k: usize) -> Self {
235        let d = self.0.len() - 1;
236        if d == 1 {
237            return Self(vec![(-self.0[0]).pow(k)]);
238        }
239        let mut r = Self(vec![MInt::zero(); d]);
240        r.0[0] = MInt::one();
241        for bit in (0..usize::BITS - k.leading_zeros()).rev() {
242            r = r.square_mod(self);
243            if k >> bit & 1 != 0 {
244                let x = r.0[d - 1];
245                for i in (1..d).rev() {
246                    r.0[i] = r.0[i - 1] - x * self.0[i];
247                }
248                r.0[0] = -x * self.0[0];
249            }
250        }
251        r
252    }
Source

fn x_pow_mod(&self, k: usize) -> Self

Examples found in repository?
crates/competitive/src/math/mint_matrix.rs (line 356)
350    fn pow(&self, k: usize) -> Matrix<AddMulOperation<MInt<M>>> {
351        let n = self.t.shape.0;
352        let mut a = vec![vec![MInt::zero(); n]; n];
353        let mut s = 0;
354        for p in &self.blocks {
355            let d = p.0.len() - 1;
356            let mut c = p.x_pow_mod(k).0;
357            for row in &mut a[s..s + d] {
358                row[s..s + d].copy_from_slice(&c);
359                let x = c[d - 1];
360                for i in (1..d).rev() {
361                    c[i] = c[i - 1] - x * p.0[i];
362                }
363                c[0] = -x * p.0[0];
364            }
365            s += d;
366        }
367        Matrix::from_vec(a)
368    }

Auto Trait Implementations§

§

impl<M> Freeze for Polynomial<M>
where Vec<MInt<M>>: Freeze,

§

impl<M> RefUnwindSafe for Polynomial<M>
where Vec<MInt<M>>: RefUnwindSafe,

§

impl<M> Send for Polynomial<M>
where Vec<MInt<M>>: Send,

§

impl<M> Sync for Polynomial<M>
where Vec<MInt<M>>: Sync,

§

impl<M> Unpin for Polynomial<M>
where Vec<MInt<M>>: Unpin,

§

impl<M> UnsafeUnpin for Polynomial<M>
where Vec<MInt<M>>: UnsafeUnpin,

§

impl<M> UnwindSafe for Polynomial<M>
where Vec<MInt<M>>: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToArrayVecScalar for T

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.