malachite_base/polynomial/mod.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::num::arithmetic::traits::{DivisibleBy, FloorLogBase2, Gcd, GcdAssign, PowerOf2};
10use crate::num::conversion::traits::ExactFrom;
11use crate::vars::{Var, VarScheme};
12use alloc::string::String;
13use alloc::vec::Vec;
14
15/// What every polynomial type has in common: a polynomial in one variable, stored as its
16/// coefficients in ascending order with no trailing zeros.
17///
18/// The functions here are the ones whose meaning does not depend on what the coefficients are. Each
19/// implementation documents its own complexity and gives its own examples.
20// There is no `is_empty` to go with `len`. Whether a polynomial is zero is asked by comparing it
21// with `ZERO`, which every polynomial type has, and a second spelling of that question, under a
22// name that suits a collection better than a polynomial, would add nothing.
23#[allow(clippy::len_without_is_empty)]
24pub trait Polynomial: Sized {
25 /// The type of a coefficient.
26 type Coefficient;
27
28 /// What [`coefficient`](Self::coefficient) and
29 /// [`leading_coefficient`](Self::leading_coefficient) return.
30 ///
31 /// This is a reference to a [`Coefficient`](Self::Coefficient) when the polynomial holds its
32 /// coefficients as they are, and a [`Coefficient`](Self::Coefficient) itself when a coefficient
33 /// is cheap to copy or has to be built on demand.
34 type CoefficientOutput<'a>
35 where
36 Self: 'a;
37
38 /// The constant polynomial 1.
39 ///
40 /// This is a function rather than an associated constant, because a polynomial holds its
41 /// coefficients in a [`Vec`] and a [`Vec`] with anything in it cannot be built at compile time.
42 fn one() -> Self;
43
44 /// The constant polynomial 2.
45 ///
46 /// This is a function rather than an associated constant, for the reason given by
47 /// [`one`](Self::one).
48 fn two() -> Self;
49
50 /// The polynomial $x$, of degree 1 with leading coefficient 1 and constant term 0.
51 ///
52 /// This is a function rather than an associated constant, for the reason given by
53 /// [`one`](Self::one).
54 fn x() -> Self;
55
56 /// Converts a [`Vec`] of coefficients, in ascending order, to a polynomial.
57 ///
58 /// The first coefficient is the constant term. Trailing zeros are dropped, so the [`Vec`] may
59 /// end with as many as it likes, and the empty [`Vec`] is the zero polynomial.
60 fn from_coefficients_asc(coefficients: Vec<Self::Coefficient>) -> Self;
61
62 /// Converts a polynomial to a [`Vec`] of its coefficients, in ascending order.
63 ///
64 /// The [`Vec`] is what [`from_coefficients_asc`](Self::from_coefficients_asc) would take back.
65 /// It holds no trailing zeros, and for the zero polynomial it is empty.
66 fn into_coefficients_asc(self) -> Vec<Self::Coefficient>;
67
68 /// Returns the degree of a polynomial.
69 ///
70 /// The zero polynomial has no degree, and gives `None`. Every other polynomial's degree is the
71 /// index of its leading coefficient, so that a nonzero constant has degree 0.
72 fn degree(&self) -> Option<u64>;
73
74 /// Returns the length of a polynomial: the number of coefficients it holds.
75 ///
76 /// A polynomial holds no trailing zeros, so its length is one more than its degree, and the
77 /// zero polynomial, which has no degree, has length 0.
78 fn len(&self) -> u64;
79
80 /// Returns one of a polynomial's coefficients.
81 ///
82 /// The index is the power of the variable the coefficient belongs to, so that index 0 gives the
83 /// constant term. An index past the degree gives zero.
84 fn coefficient(&self, index: u64) -> Self::CoefficientOutput<'_>;
85
86 /// Returns a polynomial's leading coefficient.
87 ///
88 /// The zero polynomial has no leading coefficient, and gives zero.
89 fn leading_coefficient(&self) -> Self::CoefficientOutput<'_>;
90
91 /// Determines whether a polynomial is monic: nonzero, with leading coefficient 1.
92 ///
93 /// The zero polynomial is not monic.
94 fn is_monic(&self) -> bool;
95
96 /// Mutates one of a polynomial's coefficients using a provided closure, and then returns
97 /// whatever the closure returns.
98 ///
99 /// An index past the degree is not an error: the closure is handed a zero, and the polynomial
100 /// grows to hold the result. Trailing zeros left behind by the closure are dropped.
101 fn mutate_coefficient<F: FnOnce(&mut Self::Coefficient) -> T, T>(
102 &mut self,
103 index: u64,
104 f: F,
105 ) -> T;
106
107 /// Sets the coefficients of $x^i$ for $i$ in `start..end` to zero.
108 ///
109 /// Indices past the degree are allowed; the coefficients there are zero already. Zeroing the
110 /// leading coefficient lowers the degree.
111 ///
112 /// # Panics
113 /// Panics if `start > end`.
114 fn zero_coefficients(&mut self, start: u64, end: u64);
115
116 /// Truncates a polynomial to its first `len` coefficients, taking the polynomial by reference
117 /// and returning the result.
118 ///
119 /// The result is the polynomial reduced modulo $x^{\mathrm{len}}$: every term of degree `len`
120 /// or more is dropped. A polynomial with at most `len` coefficients is returned unchanged.
121 ///
122 /// Unlike [`Vec::truncate`], this does not modify the polynomial; see
123 /// [`truncate_assign`](Self::truncate_assign) for that.
124 fn truncate(&self, len: u64) -> Self;
125
126 /// Truncates a polynomial to its first `len` coefficients, in place.
127 ///
128 /// See [`truncate`](Self::truncate).
129 fn truncate_assign(&mut self, len: u64);
130
131 /// Reverses the coefficients of a polynomial, considered as having length `len`, taking the
132 /// polynomial by reference.
133 ///
134 /// The polynomial is first truncated, or padded with zeros, to exactly `len` coefficients, and
135 /// those are then reversed, so that the result's coefficient of $x^i$ is the polynomial's
136 /// coefficient of $x^{\mathrm{len} - 1 - i}$:
137 ///
138 /// $$
139 /// f(p, n) = x^{n-1} \left( p \bmod x^n \right)\!\left(\frac{1}{x}\right).
140 /// $$
141 ///
142 /// A polynomial holds no trailing zeros, so the result may have fewer than `len` coefficients.
143 fn reverse(&self, len: u64) -> Self;
144
145 /// Reverses the coefficients of a polynomial, considered as having length `len`, in place.
146 ///
147 /// See [`reverse`](Self::reverse).
148 fn reverse_assign(&mut self, len: u64);
149
150 /// Converts a polynomial to a [`String`], naming its variable with any [`VarScheme`].
151 fn to_string_with<S: VarScheme + ?Sized>(&self, var: Var<'_, S>) -> String;
152
153 /// Converts a polynomial to a LaTeX math-mode fragment, naming its variable with any
154 /// [`VarScheme`].
155 fn to_latex_string_with<S: VarScheme + ?Sized>(&self, var: Var<'_, S>) -> String;
156
157 /// Converts a polynomial to a Typst math-mode fragment, naming its variable with any
158 /// [`VarScheme`].
159 fn to_typst_string_with<S: VarScheme + ?Sized>(&self, var: Var<'_, S>) -> String;
160
161 /// Converts a [`str`] to a polynomial, reading its variable with any [`VarScheme`].
162 ///
163 /// Returns `None` if the string is not a polynomial in that variable.
164 fn from_string_with<S: VarScheme + ?Sized>(var: Var<'_, S>, s: &str) -> Option<Self>;
165}
166
167/// Determines whether two polynomials agree below a given power of the variable.
168///
169/// This is equality of the two polynomials truncated to their first `len` coefficients, decided
170/// without building either truncation.
171pub trait EqTruncated<Rhs: ?Sized = Self> {
172 /// Determines whether two polynomials have the same coefficient of $x^i$ for every $i$ less
173 /// than `len`, taking both by reference.
174 ///
175 /// $$
176 /// f(p, q, n) = (p \bmod x^n = q \bmod x^n).
177 /// $$
178 fn eq_truncated(&self, other: &Rhs, len: u64) -> bool;
179}
180
181/// Adds two polynomials, keeping only the coefficients of $x^i$ for $i$ less than a given length.
182///
183/// This is the sum of the two polynomials truncated to their first `len` coefficients, which is
184/// also the truncation of their sum.
185///
186/// With $n$ equal to `len`, this is addition in the ring of polynomials modulo $x^n$, applied to
187/// the images of the two polynomials there. The polynomials need not already be truncated: they may
188/// have any number of coefficients, and only the first `len` of each are read.
189pub trait AddTruncated<Rhs = Self> {
190 type Output;
191
192 /// Adds two polynomials and truncates the sum to its first `len` coefficients.
193 ///
194 /// $$
195 /// f(p, q, n) = (p + q) \bmod x^n.
196 /// $$
197 fn add_truncated(self, other: Rhs, len: u64) -> Self::Output;
198}
199
200/// Adds a polynomial to another in place, keeping only the coefficients of $x^i$ for $i$ less than
201/// a given length.
202///
203/// With $n$ equal to `len`, this is addition in the ring of polynomials modulo $x^n$, applied to
204/// the images of the two polynomials there. The polynomials need not already be truncated: they may
205/// have any number of coefficients, and only the first `len` of each are read.
206pub trait AddTruncatedAssign<Rhs = Self> {
207 /// Adds a polynomial to `self` and truncates the sum to its first `len` coefficients.
208 ///
209 /// $$
210 /// p \gets (p + q) \bmod x^n.
211 /// $$
212 fn add_truncated_assign(&mut self, other: Rhs, len: u64);
213}
214
215/// Subtracts one polynomial from another, keeping only the coefficients of $x^i$ for $i$ less than
216/// a given length.
217///
218/// This is the difference of the two polynomials truncated to their first `len` coefficients, which
219/// is also the truncation of their difference.
220///
221/// With $n$ equal to `len`, this is subtraction in the ring of polynomials modulo $x^n$, applied to
222/// the images of the two polynomials there. The polynomials need not already be truncated: they may
223/// have any number of coefficients, and only the first `len` of each are read.
224pub trait SubTruncated<Rhs = Self> {
225 type Output;
226
227 /// Subtracts one polynomial from another and truncates the difference to its first `len`
228 /// coefficients.
229 ///
230 /// $$
231 /// f(p, q, n) = (p - q) \bmod x^n.
232 /// $$
233 fn sub_truncated(self, other: Rhs, len: u64) -> Self::Output;
234}
235
236/// Subtracts a polynomial from another in place, keeping only the coefficients of $x^i$ for $i$
237/// less than a given length.
238///
239/// With $n$ equal to `len`, this is subtraction in the ring of polynomials modulo $x^n$, applied to
240/// the images of the two polynomials there. The polynomials need not already be truncated: they may
241/// have any number of coefficients, and only the first `len` of each are read.
242pub trait SubTruncatedAssign<Rhs = Self> {
243 /// Subtracts a polynomial from `self` and truncates the difference to its first `len`
244 /// coefficients.
245 ///
246 /// $$
247 /// p \gets (p - q) \bmod x^n.
248 /// $$
249 fn sub_truncated_assign(&mut self, other: Rhs, len: u64);
250}
251
252/// Multiplies two polynomials, keeping only the coefficients of $x^i$ for $i$ less than a given
253/// length.
254///
255/// With $n$ equal to `len`, this is multiplication in the ring of polynomials modulo $x^n$, applied
256/// to the images of the two polynomials there. The polynomials need not already be truncated: they
257/// may have any number of coefficients, and only the first `len` of each are read.
258pub trait MulTruncated<Rhs = Self> {
259 type Output;
260
261 /// Multiplies two polynomials and truncates the product to its first `len` coefficients.
262 ///
263 /// $$
264 /// f(p, q, n) = pq \bmod x^n.
265 /// $$
266 fn mul_truncated(self, other: Rhs, len: u64) -> Self::Output;
267}
268
269/// Multiplies a polynomial by another in place, keeping only the coefficients of $x^i$ for $i$ less
270/// than a given length.
271///
272/// With $n$ equal to `len`, this is multiplication in the ring of polynomials modulo $x^n$, applied
273/// to the images of the two polynomials there. The polynomials need not already be truncated: they
274/// may have any number of coefficients, and only the first `len` of each are read.
275pub trait MulTruncatedAssign<Rhs = Self> {
276 /// Multiplies `self` by a polynomial and truncates the product to its first `len` coefficients.
277 ///
278 /// $$
279 /// p \gets pq \bmod x^n.
280 /// $$
281 fn mul_truncated_assign(&mut self, other: Rhs, len: u64);
282}
283
284/// Squares a polynomial, keeping only the coefficients of $x^i$ for $i$ less than a given length.
285///
286/// With $n$ equal to `len`, this is squaring in the ring of polynomials modulo $x^n$, applied to
287/// the image of the polynomial there. The polynomial need not already be truncated: it may have any
288/// number of coefficients, and only the first `len` are read.
289pub trait SquareTruncated {
290 type Output;
291
292 /// Squares a polynomial and truncates the square to its first `len` coefficients.
293 ///
294 /// $$
295 /// f(p, n) = p^2 \bmod x^n.
296 /// $$
297 fn square_truncated(self, len: u64) -> Self::Output;
298}
299
300/// Squares a polynomial in place, keeping only the coefficients of $x^i$ for $i$ less than a given
301/// length.
302///
303/// With $n$ equal to `len`, this is squaring in the ring of polynomials modulo $x^n$, applied to
304/// the image of the polynomial there. The polynomial need not already be truncated: it may have any
305/// number of coefficients, and only the first `len` are read.
306pub trait SquareTruncatedAssign {
307 /// Squares `self` and truncates the square to its first `len` coefficients.
308 ///
309 /// $$
310 /// p \gets p^2 \bmod x^n.
311 /// $$
312 fn square_truncated_assign(&mut self, len: u64);
313}
314
315/// Raises a polynomial to a power, keeping only the coefficients of $x^i$ for $i$ less than a given
316/// length.
317///
318/// With $n$ equal to `len`, this is powering in the ring of polynomials modulo $x^n$, applied to
319/// the image of the polynomial there. The polynomial need not already be truncated: it may have any
320/// number of coefficients, and only the first `len` are read.
321pub trait PowTruncated {
322 type Output;
323
324 /// Raises a polynomial to the power `exp` and truncates the power to its first `len`
325 /// coefficients.
326 ///
327 /// $$
328 /// f(p, e, n) = p^e \bmod x^n.
329 /// $$
330 fn pow_truncated(self, exp: u64, len: u64) -> Self::Output;
331}
332
333/// Raises a polynomial to a power in place, keeping only the coefficients of $x^i$ for $i$ less
334/// than a given length.
335///
336/// With $n$ equal to `len`, this is powering in the ring of polynomials modulo $x^n$, applied to
337/// the image of the polynomial there. The polynomial need not already be truncated: it may have any
338/// number of coefficients, and only the first `len` are read.
339pub trait PowTruncatedAssign {
340 /// Raises `self` to the power `exp` and truncates the power to its first `len` coefficients.
341 ///
342 /// $$
343 /// p \gets p^e \bmod x^n.
344 /// $$
345 fn pow_truncated_assign(&mut self, exp: u64, len: u64);
346}
347
348/// Adds two polynomials modulo $2^k$, keeping only the coefficients of $x^i$ for $i$ less than a
349/// given length. The coefficients of both must already be reduced modulo $2^k$.
350///
351/// With $n$ equal to `len`, this is addition in the ring of polynomials with coefficients modulo
352/// $2^k$, taken modulo $x^n$, applied to the images of the two polynomials there. Unlike the
353/// coefficients, which must already be reduced, the polynomials need not already be truncated: they
354/// may have any number of coefficients, and only the first `len` of each are read.
355pub trait ModPowerOf2AddTruncated<Rhs = Self> {
356 type Output;
357
358 /// Adds two polynomials modulo $2^k$ and truncates the sum to its first `len` coefficients.
359 ///
360 /// $$
361 /// f(p, q, n, k) = ((p + q) \bmod x^n) \bmod 2^k.
362 /// $$
363 fn mod_power_of_2_add_truncated(self, other: Rhs, len: u64, pow: u64) -> Self::Output;
364}
365
366/// Adds a polynomial to another modulo $2^k$ in place, keeping only the coefficients of $x^i$ for
367/// $i$ less than a given length. The coefficients of both must already be reduced modulo $2^k$.
368///
369/// With $n$ equal to `len`, this is addition in the ring of polynomials with coefficients modulo
370/// $2^k$, taken modulo $x^n$, applied to the images of the two polynomials there. Unlike the
371/// coefficients, which must already be reduced, the polynomials need not already be truncated: they
372/// may have any number of coefficients, and only the first `len` of each are read.
373pub trait ModPowerOf2AddTruncatedAssign<Rhs = Self> {
374 /// Adds a polynomial to `self` modulo $2^k$ and truncates the sum to its first `len`
375 /// coefficients.
376 ///
377 /// $$
378 /// p \gets ((p + q) \bmod x^n) \bmod 2^k.
379 /// $$
380 fn mod_power_of_2_add_truncated_assign(&mut self, other: Rhs, len: u64, pow: u64);
381}
382
383/// Subtracts one polynomial from another modulo $2^k$, keeping only the coefficients of $x^i$ for
384/// $i$ less than a given length. The coefficients of both must already be reduced modulo $2^k$.
385///
386/// With $n$ equal to `len`, this is subtraction in the ring of polynomials with coefficients modulo
387/// $2^k$, taken modulo $x^n$, applied to the images of the two polynomials there. Unlike the
388/// coefficients, which must already be reduced, the polynomials need not already be truncated: they
389/// may have any number of coefficients, and only the first `len` of each are read.
390pub trait ModPowerOf2SubTruncated<Rhs = Self> {
391 type Output;
392
393 /// Subtracts one polynomial from another modulo $2^k$ and truncates the difference to its first
394 /// `len` coefficients.
395 ///
396 /// $$
397 /// f(p, q, n, k) = ((p - q) \bmod x^n) \bmod 2^k.
398 /// $$
399 fn mod_power_of_2_sub_truncated(self, other: Rhs, len: u64, pow: u64) -> Self::Output;
400}
401
402/// Subtracts a polynomial from another modulo $2^k$ in place, keeping only the coefficients of
403/// $x^i$ for $i$ less than a given length. The coefficients of both must already be reduced modulo
404/// $2^k$.
405///
406/// With $n$ equal to `len`, this is subtraction in the ring of polynomials with coefficients modulo
407/// $2^k$, taken modulo $x^n$, applied to the images of the two polynomials there. Unlike the
408/// coefficients, which must already be reduced, the polynomials need not already be truncated: they
409/// may have any number of coefficients, and only the first `len` of each are read.
410pub trait ModPowerOf2SubTruncatedAssign<Rhs = Self> {
411 /// Subtracts a polynomial from `self` modulo $2^k$ and truncates the difference to its first
412 /// `len` coefficients.
413 ///
414 /// $$
415 /// p \gets ((p - q) \bmod x^n) \bmod 2^k.
416 /// $$
417 fn mod_power_of_2_sub_truncated_assign(&mut self, other: Rhs, len: u64, pow: u64);
418}
419
420/// Multiplies two polynomials modulo $2^k$, keeping only the coefficients of $x^i$ for $i$ less
421/// than a given length. The coefficients of both must already be reduced modulo $2^k$.
422///
423/// With $n$ equal to `len`, this is multiplication in the ring of polynomials with coefficients
424/// modulo $2^k$, taken modulo $x^n$, applied to the images of the two polynomials there. Unlike the
425/// coefficients, which must already be reduced, the polynomials need not already be truncated: they
426/// may have any number of coefficients, and only the first `len` of each are read.
427pub trait ModPowerOf2MulTruncated<Rhs = Self> {
428 type Output;
429
430 /// Multiplies two polynomials modulo $2^k$ and truncates the product to its first `len`
431 /// coefficients.
432 ///
433 /// $$
434 /// f(p, q, n, k) = (pq \bmod x^n) \bmod 2^k.
435 /// $$
436 fn mod_power_of_2_mul_truncated(self, other: Rhs, len: u64, pow: u64) -> Self::Output;
437}
438
439/// Multiplies a polynomial by another modulo $2^k$ in place, keeping only the coefficients of $x^i$
440/// for $i$ less than a given length. The coefficients of both must already be reduced modulo $2^k$.
441///
442/// With $n$ equal to `len`, this is multiplication in the ring of polynomials with coefficients
443/// modulo $2^k$, taken modulo $x^n$, applied to the images of the two polynomials there. Unlike the
444/// coefficients, which must already be reduced, the polynomials need not already be truncated: they
445/// may have any number of coefficients, and only the first `len` of each are read.
446pub trait ModPowerOf2MulTruncatedAssign<Rhs = Self> {
447 /// Multiplies `self` by a polynomial modulo $2^k$ and truncates the product to its first `len`
448 /// coefficients.
449 ///
450 /// $$
451 /// p \gets (pq \bmod x^n) \bmod 2^k.
452 /// $$
453 fn mod_power_of_2_mul_truncated_assign(&mut self, other: Rhs, len: u64, pow: u64);
454}
455
456/// Squares a polynomial modulo $2^k$, keeping only the coefficients of $x^i$ for $i$ less than a
457/// given length. The coefficients must already be reduced modulo $2^k$.
458///
459/// With $n$ equal to `len`, this is squaring in the ring of polynomials with coefficients modulo
460/// $2^k$, taken modulo $x^n$, applied to the image of the polynomial there. Unlike the
461/// coefficients, which must already be reduced, the polynomial need not already be truncated: it
462/// may have any number of coefficients, and only the first `len` are read.
463pub trait ModPowerOf2SquareTruncated {
464 type Output;
465
466 /// Squares a polynomial modulo $2^k$ and truncates the square to its first `len` coefficients.
467 ///
468 /// $$
469 /// f(p, n, k) = (p^2 \bmod x^n) \bmod 2^k.
470 /// $$
471 fn mod_power_of_2_square_truncated(self, len: u64, pow: u64) -> Self::Output;
472}
473
474/// Squares a polynomial modulo $2^k$ in place, keeping only the coefficients of $x^i$ for $i$ less
475/// than a given length. The coefficients must already be reduced modulo $2^k$.
476///
477/// With $n$ equal to `len`, this is squaring in the ring of polynomials with coefficients modulo
478/// $2^k$, taken modulo $x^n$, applied to the image of the polynomial there. Unlike the
479/// coefficients, which must already be reduced, the polynomial need not already be truncated: it
480/// may have any number of coefficients, and only the first `len` are read.
481pub trait ModPowerOf2SquareTruncatedAssign {
482 /// Squares `self` modulo $2^k$ and truncates the square to its first `len` coefficients.
483 ///
484 /// $$
485 /// p \gets (p^2 \bmod x^n) \bmod 2^k.
486 /// $$
487 fn mod_power_of_2_square_truncated_assign(&mut self, len: u64, pow: u64);
488}
489
490/// Raises a polynomial to a power modulo $2^k$, keeping only the coefficients of $x^i$ for $i$ less
491/// than a given length. The coefficients must already be reduced modulo $2^k$.
492///
493/// With $n$ equal to `len`, this is powering in the ring of polynomials with coefficients modulo
494/// $2^k$, taken modulo $x^n$, applied to the image of the polynomial there. Unlike the
495/// coefficients, which must already be reduced, the polynomial need not already be truncated: it
496/// may have any number of coefficients, and only the first `len` are read.
497pub trait ModPowerOf2PowTruncated {
498 type Output;
499
500 /// Raises a polynomial to the power `exp` modulo $2^k$ and truncates the power to its first
501 /// `len` coefficients.
502 ///
503 /// $$
504 /// f(p, e, n, k) = (p^e \bmod x^n) \bmod 2^k.
505 /// $$
506 fn mod_power_of_2_pow_truncated(self, exp: u64, len: u64, pow: u64) -> Self::Output;
507}
508
509/// Raises a polynomial to a power modulo $2^k$ in place, keeping only the coefficients of $x^i$ for
510/// $i$ less than a given length. The coefficients must already be reduced modulo $2^k$.
511///
512/// With $n$ equal to `len`, this is powering in the ring of polynomials with coefficients modulo
513/// $2^k$, taken modulo $x^n$, applied to the image of the polynomial there. Unlike the
514/// coefficients, which must already be reduced, the polynomial need not already be truncated: it
515/// may have any number of coefficients, and only the first `len` are read.
516pub trait ModPowerOf2PowTruncatedAssign {
517 /// Raises `self` to the power `exp` modulo $2^k$ and truncates the power to its first `len`
518 /// coefficients.
519 ///
520 /// $$
521 /// p \gets (p^e \bmod x^n) \bmod 2^k.
522 /// $$
523 fn mod_power_of_2_pow_truncated_assign(&mut self, exp: u64, len: u64, pow: u64);
524}
525
526/// Adds two polynomials modulo $m$, keeping only the coefficients of $x^i$ for $i$ less than a
527/// given length. The coefficients of both must already be reduced modulo $m$.
528///
529/// With $n$ equal to `len`, this is addition in the ring of polynomials with coefficients modulo
530/// $m$, taken modulo $x^n$, applied to the images of the two polynomials there. Unlike the
531/// coefficients, which must already be reduced, the polynomials need not already be truncated: they
532/// may have any number of coefficients, and only the first `len` of each are read.
533pub trait ModAddTruncated<Rhs = Self, M = Self> {
534 type Output;
535
536 /// Adds two polynomials modulo $m$ and truncates the sum to its first `len` coefficients.
537 ///
538 /// $$
539 /// f(p, q, n, m) = ((p + q) \bmod x^n) \bmod m.
540 /// $$
541 fn mod_add_truncated(self, other: Rhs, len: u64, m: M) -> Self::Output;
542}
543
544/// Adds a polynomial to another modulo $m$ in place, keeping only the coefficients of $x^i$ for $i$
545/// less than a given length. The coefficients of both must already be reduced modulo $m$.
546///
547/// With $n$ equal to `len`, this is addition in the ring of polynomials with coefficients modulo
548/// $m$, taken modulo $x^n$, applied to the images of the two polynomials there. Unlike the
549/// coefficients, which must already be reduced, the polynomials need not already be truncated: they
550/// may have any number of coefficients, and only the first `len` of each are read.
551pub trait ModAddTruncatedAssign<Rhs = Self, M = Self> {
552 /// Adds a polynomial to `self` modulo $m$ and truncates the sum to its first `len`
553 /// coefficients.
554 ///
555 /// $$
556 /// p \gets ((p + q) \bmod x^n) \bmod m.
557 /// $$
558 fn mod_add_truncated_assign(&mut self, other: Rhs, len: u64, m: M);
559}
560
561/// Subtracts one polynomial from another modulo $m$, keeping only the coefficients of $x^i$ for $i$
562/// less than a given length. The coefficients of both must already be reduced modulo $m$.
563///
564/// With $n$ equal to `len`, this is subtraction in the ring of polynomials with coefficients modulo
565/// $m$, taken modulo $x^n$, applied to the images of the two polynomials there. Unlike the
566/// coefficients, which must already be reduced, the polynomials need not already be truncated: they
567/// may have any number of coefficients, and only the first `len` of each are read.
568pub trait ModSubTruncated<Rhs = Self, M = Self> {
569 type Output;
570
571 /// Subtracts one polynomial from another modulo $m$ and truncates the difference to its first
572 /// `len` coefficients.
573 ///
574 /// $$
575 /// f(p, q, n, m) = ((p - q) \bmod x^n) \bmod m.
576 /// $$
577 fn mod_sub_truncated(self, other: Rhs, len: u64, m: M) -> Self::Output;
578}
579
580/// Subtracts a polynomial from another modulo $m$ in place, keeping only the coefficients of $x^i$
581/// for $i$ less than a given length. The coefficients of both must already be reduced modulo $m$.
582///
583/// With $n$ equal to `len`, this is subtraction in the ring of polynomials with coefficients modulo
584/// $m$, taken modulo $x^n$, applied to the images of the two polynomials there. Unlike the
585/// coefficients, which must already be reduced, the polynomials need not already be truncated: they
586/// may have any number of coefficients, and only the first `len` of each are read.
587pub trait ModSubTruncatedAssign<Rhs = Self, M = Self> {
588 /// Subtracts a polynomial from `self` modulo $m$ and truncates the difference to its first
589 /// `len` coefficients.
590 ///
591 /// $$
592 /// p \gets ((p - q) \bmod x^n) \bmod m.
593 /// $$
594 fn mod_sub_truncated_assign(&mut self, other: Rhs, len: u64, m: M);
595}
596
597/// Multiplies two polynomials modulo $m$, keeping only the coefficients of $x^i$ for $i$ less than
598/// a given length. The coefficients of both must already be reduced modulo $m$.
599///
600/// With $n$ equal to `len`, this is multiplication in the ring of polynomials with coefficients
601/// modulo $m$, taken modulo $x^n$, applied to the images of the two polynomials there. Unlike the
602/// coefficients, which must already be reduced, the polynomials need not already be truncated: they
603/// may have any number of coefficients, and only the first `len` of each are read.
604pub trait ModMulTruncated<Rhs = Self, M = Self> {
605 type Output;
606
607 /// Multiplies two polynomials modulo $m$ and truncates the product to its first `len`
608 /// coefficients.
609 ///
610 /// $$
611 /// f(p, q, n, m) = (pq \bmod x^n) \bmod m.
612 /// $$
613 fn mod_mul_truncated(self, other: Rhs, len: u64, m: M) -> Self::Output;
614}
615
616/// Multiplies a polynomial by another modulo $m$ in place, keeping only the coefficients of $x^i$
617/// for $i$ less than a given length. The coefficients of both must already be reduced modulo $m$.
618///
619/// With $n$ equal to `len`, this is multiplication in the ring of polynomials with coefficients
620/// modulo $m$, taken modulo $x^n$, applied to the images of the two polynomials there. Unlike the
621/// coefficients, which must already be reduced, the polynomials need not already be truncated: they
622/// may have any number of coefficients, and only the first `len` of each are read.
623pub trait ModMulTruncatedAssign<Rhs = Self, M = Self> {
624 /// Multiplies `self` by a polynomial modulo $m$ and truncates the product to its first `len`
625 /// coefficients.
626 ///
627 /// $$
628 /// p \gets (pq \bmod x^n) \bmod m.
629 /// $$
630 fn mod_mul_truncated_assign(&mut self, other: Rhs, len: u64, m: M);
631}
632
633/// Squares a polynomial modulo $m$, keeping only the coefficients of $x^i$ for $i$ less than a
634/// given length. The coefficients must already be reduced modulo $m$.
635///
636/// With $n$ equal to `len`, this is squaring in the ring of polynomials with coefficients modulo
637/// $m$, taken modulo $x^n$, applied to the image of the polynomial there. Unlike the coefficients,
638/// which must already be reduced, the polynomial need not already be truncated: it may have any
639/// number of coefficients, and only the first `len` are read.
640pub trait ModSquareTruncated<M = Self> {
641 type Output;
642
643 /// Squares a polynomial modulo $m$ and truncates the square to its first `len` coefficients.
644 ///
645 /// $$
646 /// f(p, n, m) = (p^2 \bmod x^n) \bmod m.
647 /// $$
648 fn mod_square_truncated(self, len: u64, m: M) -> Self::Output;
649}
650
651/// Squares a polynomial modulo $m$ in place, keeping only the coefficients of $x^i$ for $i$ less
652/// than a given length. The coefficients must already be reduced modulo $m$.
653///
654/// With $n$ equal to `len`, this is squaring in the ring of polynomials with coefficients modulo
655/// $m$, taken modulo $x^n$, applied to the image of the polynomial there. Unlike the coefficients,
656/// which must already be reduced, the polynomial need not already be truncated: it may have any
657/// number of coefficients, and only the first `len` are read.
658pub trait ModSquareTruncatedAssign<M = Self> {
659 /// Squares `self` modulo $m$ and truncates the square to its first `len` coefficients.
660 ///
661 /// $$
662 /// p \gets (p^2 \bmod x^n) \bmod m.
663 /// $$
664 fn mod_square_truncated_assign(&mut self, len: u64, m: M);
665}
666
667/// Raises a polynomial to a power modulo $m$, keeping only the coefficients of $x^i$ for $i$ less
668/// than a given length. The coefficients must already be reduced modulo $m$.
669///
670/// With $n$ equal to `len`, this is powering in the ring of polynomials with coefficients modulo
671/// $m$, taken modulo $x^n$, applied to the image of the polynomial there. Unlike the coefficients,
672/// which must already be reduced, the polynomial need not already be truncated: it may have any
673/// number of coefficients, and only the first `len` are read.
674pub trait ModPowTruncated<M = Self> {
675 type Output;
676
677 /// Raises a polynomial to the power `exp` modulo $m$ and truncates the power to its first `len`
678 /// coefficients.
679 ///
680 /// $$
681 /// f(p, e, n, m) = (p^e \bmod x^n) \bmod m.
682 /// $$
683 fn mod_pow_truncated(self, exp: u64, len: u64, m: M) -> Self::Output;
684}
685
686/// Raises a polynomial to a power modulo $m$ in place, keeping only the coefficients of $x^i$ for
687/// $i$ less than a given length. The coefficients must already be reduced modulo $m$.
688///
689/// With $n$ equal to `len`, this is powering in the ring of polynomials with coefficients modulo
690/// $m$, taken modulo $x^n$, applied to the image of the polynomial there. Unlike the coefficients,
691/// which must already be reduced, the polynomial need not already be truncated: it may have any
692/// number of coefficients, and only the first `len` are read.
693pub trait ModPowTruncatedAssign<M = Self> {
694 /// Raises `self` to the power `exp` modulo $m$ and truncates the power to its first `len`
695 /// coefficients.
696 ///
697 /// $$
698 /// p \gets (p^e \bmod x^n) \bmod m.
699 /// $$
700 fn mod_pow_truncated_assign(&mut self, exp: u64, len: u64, m: M);
701}
702
703/// Computes the square of a polynomial's $L^2$ norm: the sum of the squares of its coefficients.
704///
705/// This is exact, unlike the norm itself, which is usually irrational.
706pub trait L2NormSquared {
707 type Output;
708
709 /// Computes the sum of the squares of a polynomial's coefficients.
710 ///
711 /// $$
712 /// f(p) = \sum_i p_i^2.
713 /// $$
714 fn l2_norm_squared(self) -> Self::Output;
715}
716
717/// Computes the floor of a polynomial's $L^2$ norm: the floor of the square root of the sum of the
718/// squares of its coefficients.
719pub trait FloorL2Norm {
720 type Output;
721
722 /// Computes the floor of the square root of the sum of the squares of a polynomial's
723 /// coefficients.
724 ///
725 /// $$
726 /// f(p) = \left \lfloor \sqrt{\sum_i p_i^2} \right \rfloor.
727 /// $$
728 fn floor_l2_norm(self) -> Self::Output;
729}
730
731/// Multiplies a polynomial by $x^n$, which moves every coefficient up by $n$ places.
732pub trait MulPowerOfX {
733 type Output;
734
735 /// Multiplies a polynomial by $x^n$.
736 ///
737 /// $$
738 /// f(p, n) = x^np.
739 /// $$
740 fn mul_power_of_x(self, n: u64) -> Self::Output;
741}
742
743/// Multiplies a polynomial by $x^n$ in place, which moves every coefficient up by $n$ places.
744pub trait MulPowerOfXAssign {
745 /// Multiplies a polynomial by $x^n$ in place.
746 ///
747 /// $$
748 /// p \gets x^np.
749 /// $$
750 fn mul_power_of_x_assign(&mut self, n: u64);
751}
752
753/// Divides a polynomial by $x^n$, discarding the remainder: every coefficient moves down by $n$
754/// places, and the lowest $n$ are dropped.
755pub trait DivPowerOfX {
756 type Output;
757
758 /// Divides a polynomial by $x^n$, discarding the remainder.
759 ///
760 /// $$
761 /// f(p, n) = \sum_{i \geq n} p_ix^{i-n}.
762 /// $$
763 fn div_power_of_x(self, n: u64) -> Self::Output;
764}
765
766/// Divides a polynomial by $x^n$ in place, discarding the remainder: every coefficient moves down
767/// by $n$ places, and the lowest $n$ are dropped.
768pub trait DivPowerOfXAssign {
769 /// Divides a polynomial by $x^n$ in place, discarding the remainder.
770 ///
771 /// $$
772 /// p \gets \sum_{i \geq n} p_ix^{i-n}.
773 /// $$
774 fn div_power_of_x_assign(&mut self, n: u64);
775}
776
777/// Composes a polynomial with $x^k$, giving $p(x^k)$: the coefficient of $x^i$ moves to $x^{ik}$.
778///
779/// When $k$ is 0, the result is the constant $p(1)$, the sum of the coefficients.
780pub trait ComposePowerOfX {
781 type Output;
782
783 /// Composes a polynomial with $x^k$.
784 ///
785 /// $$
786 /// f(p, k) = p(x^k).
787 /// $$
788 fn compose_power_of_x(self, k: u64) -> Self::Output;
789}
790
791/// Composes a polynomial with $x^k$ in place, replacing $p$ with $p(x^k)$.
792///
793/// When $k$ is 0, the result is the constant $p(1)$, the sum of the coefficients.
794pub trait ComposePowerOfXAssign {
795 /// Composes a polynomial with $x^k$ in place.
796 ///
797 /// $$
798 /// p \gets p(x^k).
799 /// $$
800 fn compose_power_of_x_assign(&mut self, k: u64);
801}
802
803/// Computes the greatest common divisor of the exponents at which a polynomial has nonzero
804/// coefficients.
805///
806/// This is the largest $k$ such that $p(x) = q(x^k)$ for some polynomial $q$, when $p$ is not
807/// constant. A constant polynomial, including zero, gives 0: its only exponent with a nonzero
808/// coefficient, if any, is 0, and the GCD of $\\{0\\}$ and of the empty set are both 0.
809pub trait ExponentGcd {
810 /// Computes the greatest common divisor of the exponents at which a polynomial has nonzero
811 /// coefficients.
812 ///
813 /// $$
814 /// f(p) = \gcd \\{i : p_i \neq 0\\}.
815 /// $$
816 fn exponent_gcd(&self) -> u64;
817}
818
819// Computes the GCD of the indices of the elements of `xs` that are not zero, where `xs` holds a
820// polynomial's coefficients in ascending order with a nonzero last element, if any.
821//
822// The index of the last element always takes part, so the search starts from the GCD of it and the
823// first nonzero index after 0. From then on, only the indices that are not multiples of the current
824// GCD can lower it, so each block of `gcd` indices is scanned but for its last one; the search
825// stops as soon as the GCD is 1.
826//
827// This is equivalent to `_fmpz_poly_deflation` from `fmpz_poly/deflation.c`, FLINT 3.6.0, except
828// that a constant gives 0 rather than 1.
829#[doc(hidden)]
830pub fn slice_exponent_gcd<T>(xs: &[T], is_zero: impl Fn(&T) -> bool) -> u64 {
831 let len = xs.len();
832 if len <= 1 {
833 return 0;
834 }
835 let mut i = 1;
836 while is_zero(&xs[i]) {
837 i += 1;
838 }
839 let mut gcd = (len - 1).gcd(i);
840 while gcd > 1 && i + gcd < len {
841 let mut j = 0;
842 while j + 1 < gcd {
843 i += 1;
844 if !is_zero(&xs[i]) {
845 gcd.gcd_assign(i);
846 }
847 j += 1;
848 }
849 if j + 1 == gcd {
850 i += 1;
851 }
852 }
853 u64::exact_from(gcd)
854}
855
856/// Deflates a polynomial by $n$, giving the polynomial $q$ with $q(x^n) = p(x)$: the coefficient of
857/// $x^{in}$ moves to $x^i$.
858///
859/// This is the inverse of [`ComposePowerOfX`]. It exists only when every exponent at which $p$ has
860/// a nonzero coefficient is a multiple of $n$, that is, when $n$ divides
861/// [`exponent_gcd`](ExponentGcd::exponent_gcd); implementations panic otherwise, and when $n$ is 0.
862/// A constant polynomial deflates to itself for every positive $n$.
863pub trait DeflatePowerOfX {
864 type Output;
865
866 /// Deflates a polynomial by $n$.
867 ///
868 /// $$
869 /// f(p, n) = q, \quad \text{where} \quad q(x^n) = p(x).
870 /// $$
871 fn deflate_power_of_x(self, n: u64) -> Self::Output;
872}
873
874/// Deflates a polynomial by $n$ in place, replacing $p$ with the polynomial $q$ such that $q(x^n) =
875/// p(x)$.
876///
877/// This is the inverse of [`ComposePowerOfXAssign`]. It exists only when every exponent at which
878/// $p$ has a nonzero coefficient is a multiple of $n$, that is, when $n$ divides
879/// [`exponent_gcd`](ExponentGcd::exponent_gcd); implementations panic otherwise, and when $n$ is 0.
880/// A constant polynomial deflates to itself for every positive $n$.
881pub trait DeflatePowerOfXAssign {
882 /// Deflates a polynomial by $n$ in place.
883 ///
884 /// $$
885 /// p \gets q, \quad \text{where} \quad q(x^n) = p(x).
886 /// $$
887 fn deflate_power_of_x_assign(&mut self, n: u64);
888}
889
890// Checks that the polynomial whose coefficients `xs` holds, in ascending order with a nonzero last
891// element if any, can be deflated by `n`. Returns `n` as a `usize`, or `None` when deflating
892// changes nothing: when `n` is 1 or the polynomial is constant.
893fn deflation_step<T>(xs: &[T], n: u64, is_zero: impl Fn(&T) -> bool) -> Option<usize> {
894 assert_ne!(n, 0, "Cannot deflate a polynomial by 0");
895 if n == 1 || xs.len() <= 1 {
896 return None;
897 }
898 assert!(
899 slice_exponent_gcd(xs, is_zero).divisible_by(n),
900 "Cannot deflate a polynomial by {n}: it has a nonzero coefficient at an exponent that is \
901 not a multiple of {n}"
902 );
903 // n divides the degree, so it fits in a usize.
904 Some(usize::exact_from(n))
905}
906
907// Deflates, by `n`, the polynomial whose coefficients `xs` holds in ascending order with a nonzero
908// last element if any, in place. The coefficient at index `i * n` moves to index `i`, from the
909// bottom up, so each lands on a place whose old value is no longer needed; then the vector is
910// truncated. The leading coefficient stays nonzero.
911//
912// This is equivalent to `fmpz_poly_deflate` from `fmpz_poly/deflate.c`, FLINT 3.6.0, except that it
913// panics when some nonzero coefficient is not at a multiple of `n`.
914#[doc(hidden)]
915pub fn vec_deflate_power_of_x<T>(xs: &mut Vec<T>, n: u64, is_zero: impl Fn(&T) -> bool) {
916 if let Some(n) = deflation_step(xs, n, is_zero) {
917 let new_len = (xs.len() - 1) / n + 1;
918 for i in 1..new_len {
919 xs.swap(i, i * n);
920 }
921 xs.truncate(new_len);
922 }
923}
924
925// Deflates, by `n`, the polynomial whose coefficients `xs` holds in ascending order with a nonzero
926// last element if any, returning the coefficients of the result.
927//
928// This is equivalent to `fmpz_poly_deflate` from `fmpz_poly/deflate.c`, FLINT 3.6.0, except that it
929// panics when some nonzero coefficient is not at a multiple of `n`.
930#[doc(hidden)]
931pub fn slice_deflate_power_of_x<T: Clone>(
932 xs: &[T],
933 n: u64,
934 is_zero: impl Fn(&T) -> bool,
935) -> Vec<T> {
936 match deflation_step(xs, n, is_zero) {
937 None => xs.to_vec(),
938 Some(n) => xs.iter().step_by(n).cloned().collect(),
939 }
940}
941
942// Determines whether two coefficient slices, each holding a polynomial's coefficients in ascending
943// order, agree below index `len`.
944//
945// Only the first `len` coefficients of each count. Where one polynomial has more of those than the
946// other, the extra ones must be zero, since the other polynomial's coefficients there are; where
947// both have them, `eq` decides. Nothing is allocated.
948//
949// This is equivalent to `fmpz_poly_equal_trunc` from `fmpz_poly/equal_trunc.c`, FLINT 3.6.0, with
950// `eq` and the zero tests standing in for `fmpz_equal` and `fmpz_is_zero`.
951#[doc(hidden)]
952pub fn slices_eq_truncated<A, B>(
953 xs: &[A],
954 ys: &[B],
955 len: u64,
956 x_is_zero: impl Fn(&A) -> bool,
957 y_is_zero: impl Fn(&B) -> bool,
958 eq: impl Fn(&A, &B) -> bool,
959) -> bool {
960 let len = usize::try_from(len).unwrap_or(usize::MAX);
961 let xs = &xs[..len.min(xs.len())];
962 let ys = &ys[..len.min(ys.len())];
963 let common = xs.len().min(ys.len());
964 xs[common..].iter().all(x_is_zero)
965 && ys[common..].iter().all(y_is_zero)
966 && xs[..common]
967 .iter()
968 .zip(&ys[..common])
969 .all(|(x, y)| eq(x, y))
970}
971
972/// Computes the derivative of a polynomial, $\sum_i ia_ix^{i-1}$.
973pub trait Derivative {
974 type Output;
975
976 /// Computes the derivative of a polynomial.
977 ///
978 /// $$
979 /// f(p) = p'.
980 /// $$
981 fn derivative(self) -> Self::Output;
982}
983
984/// Replaces a polynomial with its derivative, $\sum_i ia_ix^{i-1}$.
985pub trait DerivativeAssign {
986 /// Replaces a polynomial with its derivative.
987 ///
988 /// $$
989 /// p \gets p'.
990 /// $$
991 fn derivative_assign(&mut self);
992}
993
994/// Computes the integral of a polynomial whose constant term is zero, $\sum_i a_ix^{i+1}/(i+1)$.
995pub trait Integral {
996 type Output;
997
998 /// Computes the integral of a polynomial whose constant term is zero.
999 ///
1000 /// $$
1001 /// f(p) = \int_0^x p(t)\,dt.
1002 /// $$
1003 fn integral(self) -> Self::Output;
1004}
1005
1006/// Replaces a polynomial with its integral whose constant term is zero, $\sum_i a_ix^{i+1}/(i+1)$.
1007pub trait IntegralAssign {
1008 /// Replaces a polynomial with its integral whose constant term is zero.
1009 ///
1010 /// $$
1011 /// p \gets \int_0^x p(t)\,dt.
1012 /// $$
1013 fn integral_assign(&mut self);
1014}
1015
1016/// Computes the derivative of a polynomial modulo $m$. The coefficients must already be reduced
1017/// modulo $m$.
1018///
1019/// Each coefficient $a_i$ becomes $ia_i \bmod m$, which can be zero even when $a_i$ is not, so the
1020/// derivative can lose any number of degrees.
1021pub trait ModDerivative<M> {
1022 type Output;
1023
1024 /// Computes the derivative of a polynomial modulo $m$.
1025 ///
1026 /// $$
1027 /// f(p, m) = p' \bmod m.
1028 /// $$
1029 fn mod_derivative(self, m: M) -> Self::Output;
1030}
1031
1032/// Replaces a polynomial with its derivative modulo $m$. The coefficients must already be reduced
1033/// modulo $m$.
1034///
1035/// Each coefficient $a_i$ becomes $ia_i \bmod m$, which can be zero even when $a_i$ is not, so the
1036/// derivative can lose any number of degrees.
1037pub trait ModDerivativeAssign<M> {
1038 /// Replaces a polynomial with its derivative modulo $m$.
1039 ///
1040 /// $$
1041 /// p \gets p' \bmod m.
1042 /// $$
1043 fn mod_derivative_assign(&mut self, m: M);
1044}
1045
1046/// Computes the integral modulo $m$ of a polynomial whose constant term is zero. The coefficients
1047/// must already be reduced modulo $m$.
1048///
1049/// The coefficient of $x^{k-1}$ is divided by $k$ and moved to $x^k$, so every $k$ for which that
1050/// coefficient is nonzero must be a unit modulo $m$.
1051pub trait ModIntegral<M> {
1052 type Output;
1053
1054 /// Computes the integral modulo $m$ of a polynomial whose constant term is zero.
1055 ///
1056 /// $$
1057 /// f(p, m) = \int_0^x p(t)\,dt \bmod m.
1058 /// $$
1059 fn mod_integral(self, m: M) -> Self::Output;
1060}
1061
1062/// Replaces a polynomial with its integral modulo $m$ whose constant term is zero. The coefficients
1063/// must already be reduced modulo $m$.
1064///
1065/// The coefficient of $x^{k-1}$ is divided by $k$ and moved to $x^k$, so every $k$ for which that
1066/// coefficient is nonzero must be a unit modulo $m$.
1067pub trait ModIntegralAssign<M> {
1068 /// Replaces a polynomial with its integral modulo $m$ whose constant term is zero.
1069 ///
1070 /// $$
1071 /// p \gets \int_0^x p(t)\,dt \bmod m.
1072 /// $$
1073 fn mod_integral_assign(&mut self, m: M);
1074}
1075
1076/// Computes the derivative of a polynomial modulo $2^k$. The coefficients must already be reduced
1077/// modulo $2^k$.
1078///
1079/// Each coefficient $a_i$ becomes $ia_i \bmod 2^k$, which can be zero even when $a_i$ is not, so
1080/// the derivative can lose any number of degrees.
1081pub trait ModPowerOf2Derivative {
1082 type Output;
1083
1084 /// Computes the derivative of a polynomial modulo $2^k$.
1085 ///
1086 /// $$
1087 /// f(p, k) = p' \bmod 2^k.
1088 /// $$
1089 fn mod_power_of_2_derivative(self, pow: u64) -> Self::Output;
1090}
1091
1092/// Replaces a polynomial with its derivative modulo $2^k$. The coefficients must already be reduced
1093/// modulo $2^k$.
1094///
1095/// Each coefficient $a_i$ becomes $ia_i \bmod 2^k$, which can be zero even when $a_i$ is not, so
1096/// the derivative can lose any number of degrees.
1097pub trait ModPowerOf2DerivativeAssign {
1098 /// Replaces a polynomial with its derivative modulo $2^k$.
1099 ///
1100 /// $$
1101 /// p \gets p' \bmod 2^k.
1102 /// $$
1103 fn mod_power_of_2_derivative_assign(&mut self, pow: u64);
1104}
1105
1106/// Computes the integral modulo $2^k$ of a polynomial whose constant term is zero. The coefficients
1107/// must already be reduced modulo $2^k$.
1108///
1109/// The coefficient of $x^{i-1}$ is divided by $i$ and moved to $x^i$. Only odd numbers are units
1110/// modulo $2^k$, so every nonzero coefficient must belong to an even power of $x$.
1111pub trait ModPowerOf2Integral {
1112 type Output;
1113
1114 /// Computes the integral modulo $2^k$ of a polynomial whose constant term is zero.
1115 ///
1116 /// $$
1117 /// f(p, k) = \int_0^x p(t)\,dt \bmod 2^k.
1118 /// $$
1119 fn mod_power_of_2_integral(self, pow: u64) -> Self::Output;
1120}
1121
1122/// Replaces a polynomial with its integral modulo $2^k$ whose constant term is zero. The
1123/// coefficients must already be reduced modulo $2^k$.
1124///
1125/// The coefficient of $x^{i-1}$ is divided by $i$ and moved to $x^i$. Only odd numbers are units
1126/// modulo $2^k$, so every nonzero coefficient must belong to an even power of $x$.
1127pub trait ModPowerOf2IntegralAssign {
1128 /// Replaces a polynomial with its integral modulo $2^k$ whose constant term is zero.
1129 ///
1130 /// $$
1131 /// p \gets \int_0^x p(t)\,dt \bmod 2^k.
1132 /// $$
1133 fn mod_power_of_2_integral_assign(&mut self, pow: u64);
1134}
1135
1136/// Computes the $n$th derivative of a polynomial, $\sum_i i^{\underline n}a_ix^{i-n}$, where
1137/// $i^{\underline n} = i(i-1)\cdots(i-n+1)$ is a falling factorial.
1138pub trait NthDerivative {
1139 type Output;
1140
1141 /// Computes the $n$th derivative of a polynomial.
1142 ///
1143 /// $$
1144 /// f(p, n) = p^{(n)}.
1145 /// $$
1146 fn nth_derivative(self, n: u64) -> Self::Output;
1147}
1148
1149/// Replaces a polynomial with its $n$th derivative, $\sum_i i^{\underline n}a_ix^{i-n}$, where
1150/// $i^{\underline n} = i(i-1)\cdots(i-n+1)$ is a falling factorial.
1151pub trait NthDerivativeAssign {
1152 /// Replaces a polynomial with its $n$th derivative.
1153 ///
1154 /// $$
1155 /// p \gets p^{(n)}.
1156 /// $$
1157 fn nth_derivative_assign(&mut self, n: u64);
1158}
1159
1160/// Computes the $n$th derivative of a polynomial modulo $m$. The coefficients must already be
1161/// reduced modulo $m$.
1162///
1163/// Each coefficient $a_i$ becomes $i^{\underline n}a_i \bmod m$, where $i^{\underline n}$ is a
1164/// falling factorial; this can be zero even when $a_i$ is not, so the derivative can lose any
1165/// number of degrees. Every $i^{\underline n}$ is a multiple of $n!$, so if $m$ divides $n!$, the
1166/// result is zero.
1167pub trait ModNthDerivative<M> {
1168 type Output;
1169
1170 /// Computes the $n$th derivative of a polynomial modulo $m$.
1171 ///
1172 /// $$
1173 /// f(p, n, m) = p^{(n)} \bmod m.
1174 /// $$
1175 fn mod_nth_derivative(self, n: u64, m: M) -> Self::Output;
1176}
1177
1178/// Replaces a polynomial with its $n$th derivative modulo $m$. The coefficients must already be
1179/// reduced modulo $m$.
1180///
1181/// Each coefficient $a_i$ becomes $i^{\underline n}a_i \bmod m$, where $i^{\underline n}$ is a
1182/// falling factorial; this can be zero even when $a_i$ is not, so the derivative can lose any
1183/// number of degrees. Every $i^{\underline n}$ is a multiple of $n!$, so if $m$ divides $n!$, the
1184/// result is zero.
1185pub trait ModNthDerivativeAssign<M> {
1186 /// Replaces a polynomial with its $n$th derivative modulo $m$.
1187 ///
1188 /// $$
1189 /// p \gets p^{(n)} \bmod m.
1190 /// $$
1191 fn mod_nth_derivative_assign(&mut self, n: u64, m: M);
1192}
1193
1194/// Computes the $n$th derivative of a polynomial modulo $2^k$. The coefficients must already be
1195/// reduced modulo $2^k$.
1196///
1197/// Each coefficient $a_i$ becomes $i^{\underline n}a_i \bmod 2^k$, where $i^{\underline n}$ is a
1198/// falling factorial; this can be zero even when $a_i$ is not, so the derivative can lose any
1199/// number of degrees. Every $i^{\underline n}$ is a multiple of $n!$, so if $2^k$ divides $n!$, the
1200/// result is zero.
1201pub trait ModPowerOf2NthDerivative {
1202 type Output;
1203
1204 /// Computes the $n$th derivative of a polynomial modulo $2^k$.
1205 ///
1206 /// $$
1207 /// f(p, n, k) = p^{(n)} \bmod 2^k.
1208 /// $$
1209 fn mod_power_of_2_nth_derivative(self, n: u64, pow: u64) -> Self::Output;
1210}
1211
1212/// Replaces a polynomial with its $n$th derivative modulo $2^k$. The coefficients must already be
1213/// reduced modulo $2^k$.
1214///
1215/// Each coefficient $a_i$ becomes $i^{\underline n}a_i \bmod 2^k$, where $i^{\underline n}$ is a
1216/// falling factorial; this can be zero even when $a_i$ is not, so the derivative can lose any
1217/// number of degrees. Every $i^{\underline n}$ is a multiple of $n!$, so if $2^k$ divides $n!$, the
1218/// result is zero.
1219pub trait ModPowerOf2NthDerivativeAssign {
1220 /// Replaces a polynomial with its $n$th derivative modulo $2^k$.
1221 ///
1222 /// $$
1223 /// p \gets p^{(n)} \bmod 2^k.
1224 /// $$
1225 fn mod_power_of_2_nth_derivative_assign(&mut self, n: u64, pow: u64);
1226}
1227
1228/// Packs the coefficients of a polynomial into a single number, placing the coefficient of $x^i$ at
1229/// bit $ib$; that is, evaluates the polynomial at $2^b$.
1230///
1231/// When every coefficient's absolute value is less than $2^b$, the coefficients occupy disjoint
1232/// $b$-bit fields, with a borrow from the next field above each negative one; this is the
1233/// representation that Kronecker substitution uses to reduce polynomial multiplication to integer
1234/// multiplication. Wider coefficients overlap the fields above them, and the result is still
1235/// $p(2^b)$.
1236pub trait BitPack {
1237 type Output;
1238
1239 /// Packs the coefficients of a polynomial into fields of `bits` bits.
1240 ///
1241 /// $$
1242 /// f(p, b) = p(2^b) = \sum_i a_i2^{ib}.
1243 /// $$
1244 fn bit_pack(self, bits: u64) -> Self::Output;
1245}
1246
1247/// Unpacks a polynomial from the fixed-width fields of a single number, reading the coefficient of
1248/// $x^i$ from bit $ib$; the result $p$ satisfies $p(2^b) = n$.
1249///
1250/// This inverts [`BitPack`] on polynomials whose coefficients fit their fields.
1251pub trait BitUnpack<T>: Sized {
1252 /// Unpacks a polynomial from fields of `bits` bits.
1253 ///
1254 /// $$
1255 /// f(n, b) = p, \quad \text{where} \quad p(2^b) = n.
1256 /// $$
1257 fn bit_unpack(n: T, bits: u64) -> Self;
1258}
1259
1260/// Computes the content of a polynomial.
1261///
1262/// For a polynomial with integer coefficients, the content is the greatest common divisor of its
1263/// coefficients. For a polynomial with rational coefficients, it is the non-negative rational $c$
1264/// for which $p/c$ is a primitive polynomial with integer coefficients. Either way it is
1265/// non-negative, and the content of the zero polynomial is zero.
1266pub trait Content {
1267 /// The type of the content.
1268 type Output;
1269
1270 /// Computes the content of a polynomial.
1271 fn content(self) -> Self::Output;
1272}
1273
1274/// Computes the primitive part of a polynomial: the polynomial divided by its content, with the
1275/// sign chosen so that the leading coefficient is non-negative.
1276///
1277/// $$
1278/// p = \operatorname{sgn}(\operatorname{lc}(p)) \operatorname{cont}(p) \operatorname{pp}(p),
1279/// $$
1280///
1281/// where $\operatorname{lc}(p)$ is the leading coefficient of $p$. The sign matters: without it the
1282/// identity fails whenever the leading coefficient is negative. The primitive part of the zero
1283/// polynomial is zero.
1284pub trait PrimitivePart {
1285 /// The type of the primitive part.
1286 type Output;
1287
1288 /// Computes the primitive part of a polynomial.
1289 fn primitive_part(self) -> Self::Output;
1290}
1291
1292/// Replaces a polynomial with its primitive part.
1293///
1294/// See [`PrimitivePart`].
1295pub trait PrimitivePartAssign {
1296 /// Replaces a polynomial with its primitive part.
1297 fn primitive_part_assign(&mut self);
1298}
1299
1300/// Computes the content and the primitive part of a polynomial together.
1301///
1302/// The primitive part is found by dividing by the content, so computing both at once finds the
1303/// content only once. See [`Content`] and [`PrimitivePart`].
1304pub trait ContentAndPrimitivePart {
1305 /// The type of the content.
1306 type Content;
1307 /// The type of the primitive part.
1308 type PrimitivePart;
1309
1310 /// Computes the content and the primitive part of a polynomial.
1311 fn content_and_primitive_part(self) -> (Self::Content, Self::PrimitivePart);
1312}
1313
1314/// Makes a polynomial monic, by dividing it by its leading coefficient.
1315///
1316/// The zero polynomial has no leading coefficient, and is left as it is.
1317pub trait MakeMonic {
1318 /// The type of the monic polynomial.
1319 type Output;
1320
1321 /// Makes a polynomial monic.
1322 fn make_monic(self) -> Self::Output;
1323}
1324
1325/// Makes a polynomial monic in place, by dividing it by its leading coefficient.
1326///
1327/// See [`MakeMonic`].
1328pub trait MakeMonicAssign {
1329 /// Makes a polynomial monic in place.
1330 fn make_monic_assign(&mut self);
1331}
1332
1333/// Makes a polynomial monic modulo $m$, by multiplying it by the inverse of its leading
1334/// coefficient.
1335///
1336/// The polynomial's coefficients must already be reduced modulo $m$. If the leading coefficient is
1337/// not invertible modulo $m$, its greatest common divisor with $m$, a nontrivial factor of $m$, is
1338/// returned as the error. The zero polynomial is left as it is.
1339pub trait ModMakeMonic<M> {
1340 /// The type of the monic polynomial.
1341 type Output;
1342 /// The type of the factor of $m$ returned when the leading coefficient is not invertible.
1343 type Factor;
1344
1345 /// Makes a polynomial monic modulo `m`.
1346 fn mod_make_monic(self, m: M) -> Result<Self::Output, Self::Factor>;
1347}
1348
1349/// Makes a polynomial monic modulo $m$ in place.
1350///
1351/// See [`ModMakeMonic`]. If the leading coefficient is not invertible, the polynomial is left
1352/// unchanged.
1353pub trait ModMakeMonicAssign<M> {
1354 /// The type of the factor of $m$ returned when the leading coefficient is not invertible.
1355 type Factor;
1356
1357 /// Makes a polynomial monic modulo `m` in place.
1358 fn mod_make_monic_assign(&mut self, m: M) -> Result<(), Self::Factor>;
1359}
1360
1361/// Evaluates a polynomial at a value.
1362///
1363/// Evaluation substitutes a value for the variable. It maps out of the polynomial rather than
1364/// staying inside it, so the type of the value decides the type of the result, and a polynomial
1365/// type may implement this trait for several value types.
1366pub trait Evaluate<T> {
1367 /// The type of the polynomial's value.
1368 type Output;
1369
1370 /// Evaluates a polynomial at `x`.
1371 ///
1372 /// $$
1373 /// f(p, x) = \sum_{i=0}^{n-1} c_i x^i,
1374 /// $$
1375 ///
1376 /// where $c_i$ is the coefficient of $x^i$ in $p$ and $n$ is its length.
1377 fn evaluate(self, x: T) -> Self::Output;
1378}
1379
1380/// Evaluates a polynomial at a value, modulo $2^k$. The polynomial's coefficients and the value
1381/// must already be reduced modulo $2^k$.
1382pub trait ModPowerOf2Evaluate<T> {
1383 /// The type of the polynomial's value.
1384 type Output;
1385
1386 /// Evaluates a polynomial at `x`, modulo $2^k$.
1387 ///
1388 /// $$
1389 /// f(p, x, k) = \sum_{i=0}^{n-1} c_i x^i \bmod 2^k,
1390 /// $$
1391 ///
1392 /// where $c_i$ is the coefficient of $x^i$ in $p$ and $n$ is its length.
1393 fn mod_power_of_2_evaluate(self, x: T, pow: u64) -> Self::Output;
1394}
1395
1396/// Evaluates a polynomial at a value, modulo $m$. The value must already be reduced modulo $m$, and
1397/// so must the polynomial's coefficients, unless an implementation says otherwise.
1398pub trait ModEvaluate<T, M = T> {
1399 /// The type of the polynomial's value.
1400 type Output;
1401
1402 /// Evaluates a polynomial at `x`, modulo `m`.
1403 ///
1404 /// $$
1405 /// f(p, x, m) = \sum_{i=0}^{n-1} c_i x^i \bmod m,
1406 /// $$
1407 ///
1408 /// where $c_i$ is the coefficient of $x^i$ in $p$ and $n$ is its length.
1409 fn mod_evaluate(self, x: T, m: M) -> Self::Output;
1410}
1411
1412/// Evaluates a polynomial at each of several values.
1413pub trait EvaluateMany<T> {
1414 /// The type of the polynomial's values.
1415 type Output;
1416
1417 /// Evaluates a polynomial at each value in `xs`, returning the values in the same order.
1418 ///
1419 /// $$
1420 /// f(p, (x_j)_{j=0}^{k-1}) = \left ( \sum_{i=0}^{n-1} c_i x_j^i \right )_{j=0}^{k-1},
1421 /// $$
1422 ///
1423 /// where $c_i$ is the coefficient of $x^i$ in $p$ and $n$ is its length.
1424 fn evaluate_many(self, xs: &[T]) -> Vec<Self::Output>;
1425}
1426
1427/// Evaluates a polynomial at each of several values, modulo $m$. The values must already be reduced
1428/// modulo $m$, and so must the polynomial's coefficients, unless an implementation says otherwise.
1429pub trait ModEvaluateMany<T, M = T> {
1430 /// The type of the polynomial's values.
1431 type Output;
1432
1433 /// Evaluates a polynomial at each value in `xs`, modulo `m`, returning the values in the same
1434 /// order.
1435 ///
1436 /// $$
1437 /// f(p, (x_j)_{j=0}^{k-1}, m) = \left ( \sum_{i=0}^{n-1} c_i x_j^i \bmod m
1438 /// \right )_{j=0}^{k-1},
1439 /// $$
1440 ///
1441 /// where $c_i$ is the coefficient of $x^i$ in $p$ and $n$ is its length.
1442 fn mod_evaluate_many(self, xs: &[T], m: M) -> Vec<Self::Output>;
1443}
1444
1445/// Evaluates a polynomial at the first terms of a geometric progression starting at 1, modulo $m$.
1446/// The ratio must already be reduced modulo $m$, and so must the polynomial's coefficients.
1447pub trait ModEvaluateGeometric<T, M = T> {
1448 /// The type of the polynomial's values.
1449 type Output;
1450
1451 /// Evaluates a polynomial at $1, q, q^2, \ldots, q^{k-1}$, modulo `m`.
1452 ///
1453 /// $$
1454 /// f(p, q, k, m) = \left ( \sum_{i=0}^{n-1} c_i q^{ij} \bmod m \right )_{j=0}^{k-1},
1455 /// $$
1456 ///
1457 /// where $c_i$ is the coefficient of $x^i$ in $p$ and $n$ is its length.
1458 fn mod_evaluate_geometric(self, q: T, k: u64, m: M) -> Vec<Self::Output>;
1459}
1460
1461/// Raises the polynomial with coefficients `xs`, which has length at least 2, to the power `e`,
1462/// which is at least 3, by left-to-right binary exponentiation with the given squaring and
1463/// multiplication, each of which returns its result without zeros at the end.
1464///
1465/// This is for powers in rings with zero divisors, such as polynomials modulo $m$, where a power
1466/// can lose its leading coefficients or vanish: the intermediate powers keep only the length they
1467/// need, and a power that vanishes ends the computation.
1468///
1469/// This is not part of the public API; it is public so that `malachite-nz` can raise its
1470/// polynomials to powers modulo a number in the same way.
1471#[doc(hidden)]
1472pub fn pow_binexp_trimmed<T>(
1473 xs: &[T],
1474 e: u64,
1475 square: impl Fn(&[T]) -> Vec<T>,
1476 mul: impl Fn(&[T], &[T]) -> Vec<T>,
1477) -> Vec<T> {
1478 // The bit of e one place below its most significant bit
1479 let mut bit = u64::power_of_2(e.floor_log_base_2()) >> 1;
1480 let mut r = square(xs);
1481 loop {
1482 if r.is_empty() {
1483 return r;
1484 }
1485 if bit & e != 0 {
1486 r = mul(&r, xs);
1487 if r.is_empty() {
1488 return r;
1489 }
1490 }
1491 bit >>= 1;
1492 if bit == 0 {
1493 return r;
1494 }
1495 r = square(&r);
1496 }
1497}