Skip to main content

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}