=encoding utf8

=head1 NAME

Sidef::Types::Number::PolynomialMod - Polynomial arithmetic modulo another polynomial

=head1 DESCRIPTION

This class implements polynomial arithmetic in quotient rings, where polynomials are computed modulo another polynomial. This is particularly useful for finite field arithmetic, algebraic number theory, and cryptographic applications.

A PolynomialMod object represents a polynomial reduced modulo a given modulus polynomial, similar to how integers modulo n work but in the polynomial domain.

=head1 SYNOPSIS

    # Create a polynomial mod object
    var p = PolynomialMod([1, 2, 3], [1, 0, 1])  # (1 + 2x + 3x²) mod (1 + x²)
    
    # Arithmetic operations
    var q = PolynomialMod([2, 1], [1, 0, 1])
    say p + q      # Addition
    say p * q      # Multiplication
    say p ** 3     # Exponentiation
    
    # Evaluate at a point
    say p.eval(2)
    
    # Get the modulus
    say p.modulus
    
    # Lift to regular polynomial
    say p.lift

=head1 INHERITS

Inherits methods from:

       * Sidef::Types::Number::Polynomial

=head1 METHODS

=head2 !=

    a != b

Returns true if polynomial C<a> is not equal to polynomial C<b> modulo their common modulus.

Aliases: I<ne>

=cut

=head2 %

    a % b

Returns the remainder of polynomial C<a> divided by polynomial C<b>, computed modulo the modulus polynomial.

Aliases: I<mod>

=cut

=head2 *

    a * b

Returns the product of polynomials C<a> and C<b>, reduced modulo the modulus polynomial.

Aliases: I<mul>

=cut

=head2 **

    a ** b

Returns polynomial C<a> raised to the power C<b>, computed modulo the modulus polynomial. Supports both positive integers and negative integer exponents (computing modular inverse when needed).

Aliases: I<pow>

=cut

=head2 +

    a + b

Returns the sum of polynomials C<a> and C<b>, reduced modulo the modulus polynomial.

Aliases: I<add>

=cut

=head2 ++

    a++

Increments polynomial C<a> by 1 (adds the constant polynomial 1), reducing modulo the modulus polynomial.

Aliases: I<inc>

=cut

=head2 -

    a - b

Returns the difference of polynomials C<a> and C<b>, reduced modulo the modulus polynomial.

Aliases: I<sub>

=cut

=head2 --

    a--

Decrements polynomial C<a> by 1 (subtracts the constant polynomial 1), reducing modulo the modulus polynomial.

Aliases: I<dec>

=cut

=head2 /

    a / b

Returns the quotient of polynomial C<a> divided by polynomial C<b>, computed modulo the modulus polynomial. This computes C<a> times the modular inverse of C<b>.

Aliases: I<÷>, I<div>

=cut

=head2 //

    a // b

Returns the integer (floor) division of polynomial C<a> by polynomial C<b>, computed modulo the modulus polynomial.

Aliases: I<idiv>, I<idiv_ceil>, I<idiv_floor>, I<idiv_round>, I<idiv_trunc>

=cut

=head2 <

    a < b

Compares polynomials C<a> and C<b> lexicographically by their coefficients. Returns true if C<a> is less than C<b>.

Aliases: I<lt>

=cut

=head2 <=>

    a <=> b

Three-way comparison operator. Returns -1 if C<a> is less than C<b>, 0 if equal, and 1 if greater. Comparison is performed lexicographically on coefficients.

Aliases: I<cmp>

=cut

=head2 ==

    a == b

Returns true if polynomial C<a> equals polynomial C<b> modulo their common modulus.

Aliases: I<eq>

=cut

=head2 >

    a > b

Compares polynomials C<a> and C<b> lexicographically by their coefficients. Returns true if C<a> is greater than C<b>.

Aliases: I<gt>

=cut

=head2 ≤

    a ≤ b

Returns true if polynomial C<a> is less than or equal to polynomial C<b> lexicographically.

Aliases: I<E<lt>=>, I<le>

=cut

=head2 ≥

    a ≥ b

Returns true if polynomial C<a> is greater than or equal to polynomial C<b> lexicographically.

Aliases: I<E<gt>=>, I<ge>

=cut

=head2 abs

    x.abs

Returns the absolute value of the polynomial. For polynomials, this typically ensures the leading coefficient is positive.

=cut

=head2 binomial

    n.binomial(k)

Returns the binomial coefficient C(n, k) computed in the polynomial mod ring. This generalizes the standard binomial coefficient to polynomial quotient rings.

=cut

=head2 ceil

    x.ceil

Returns the ceiling of the polynomial. For polynomials with rational or real coefficients, this applies the ceiling function to each coefficient.

=cut

=head2 chinese

    *polynomials.chinese

Applies the Chinese Remainder Theorem to solve a system of polynomial congruences. Given polynomials with different moduli, finds a polynomial that satisfies all congruences simultaneously.

=cut

=head2 derivative

    x.derivative

Returns the formal derivative of the polynomial with respect to its variable, computed modulo the modulus polynomial.

=cut

=head2 divmod

    x.divmod(y)

Returns a pair C<(quotient, remainder)> from dividing polynomial C<x> by polynomial C<y>, computed modulo the modulus polynomial.

=cut

=head2 dump

    x.dump

Returns a detailed string representation of the polynomial mod object, showing its internal structure for debugging purposes.

=cut

=head2 eval

    x.eval(value)

Evaluates the polynomial at the given value by substituting the value for the variable and computing the result modulo the modulus polynomial.

=cut

=head2 float

    x.float

Converts the polynomial to a floating-point approximation. For polynomials, this typically evaluates at x=1 or converts coefficients to floating-point.

=cut

=head2 floor

    x.floor

Returns the floor of the polynomial. For polynomials with rational or real coefficients, this applies the floor function to each coefficient.

=cut

=head2 gcd

    x.gcd(y)

Returns the greatest common divisor of polynomials C<x> and C<y>, computed modulo the modulus polynomial using the Euclidean algorithm.

=cut

=head2 gcdext

    x.gcdext(y)

Returns the extended GCD of polynomials C<x> and C<y>. Returns a triple C<(g, u, v)> where C<g> is the GCD and C<u>, C<v> are polynomials such that C<u*x + v*y = g> (modulo the modulus polynomial).

=cut

=head2 inv

    x.inv

Returns the multiplicative inverse of polynomial C<x> modulo the modulus polynomial. This exists if and only if C<x> and the modulus are coprime.

=cut

=head2 is_mone

    x.is_mone

Returns true if the polynomial equals -1 (the constant polynomial with coefficient -1).

=cut

=head2 is_one

    x.is_one

Returns true if the polynomial equals 1 (the constant polynomial with coefficient 1), which is the multiplicative identity.

=cut

=head2 is_zero

    x.is_zero

Returns true if the polynomial is the zero polynomial, which is the additive identity.

=cut

=head2 lcm

    x.lcm(y)

Returns the least common multiple of polynomials C<x> and C<y>, computed modulo the modulus polynomial.

=cut

=head2 lift

    self.lift

Returns the underlying polynomial without the modulus constraint, "lifting" it from the quotient ring to the polynomial ring.

Aliases: I<to_poly>

=cut

=head2 modulus

    self.modulus

Returns the modulus polynomial by which all operations in this quotient ring are reduced.

=cut

=head2 neg

    x.neg

Returns the additive inverse (negation) of polynomial C<x>, which when added to C<x> gives zero.

=cut

=head2 new

    self.new(coeffs, modulus)
    PolynomialMod(coeffs, modulus)

Creates a new PolynomialMod object from a list of coefficients and a modulus polynomial. The coefficients represent the polynomial starting from the constant term.

Example:

    var p = PolynomialMod([1, 2, 3], [1, 0, 1])  # (1 + 2x + 3x²) mod (1 + x²)

Aliases: I<call>

=cut

=head2 pretty

    x.pretty

Returns a human-readable string representation of the polynomial in standard mathematical notation (e.g., "1 + 2x + 3x²").

=cut

=head2 rat

    x.rat

Converts the polynomial to rational form, ensuring all coefficients are represented as exact rational numbers.

=cut

=head2 rat_approx

    x.rat_approx

Returns a rational approximation of the polynomial, converting floating-point coefficients to nearby rational numbers.

=cut

=head2 round

    x.round(r)

Rounds each coefficient of the polynomial to C<r> decimal places (or to the nearest integer if C<r> is not specified).

=cut

=head2 sqr

    x.sqr

Returns the square of polynomial C<x> (equivalent to C<x * x>), computed modulo the modulus polynomial.

=cut

=head2 to_s

    x.to_s

Converts the polynomial to a string representation suitable for display.

Aliases: I<stringify>

=cut

=head1 EXAMPLES

    # Working in Q[x]/(x² + 1) - Gaussian integers
    var i = PolynomialMod([0, 1], [1, 0, 1])  # represents 'i' where i² = -1
    say i ** 2    # Output: -1
    say i ** 4    # Output: 1
    
    # Arithmetic in finite fields
    var a = PolynomialMod([1, 1], [1, 1, 1])  # (1 + x) mod (1 + x + x²)
    var b = PolynomialMod([1, 0, 1], [1, 1, 1])  # (1 + x²) mod (1 + x + x²)
    say a * b
    
    # Finding modular inverses
    var p = PolynomialMod([1, 2], [1, 0, 0, 1])
    say p.inv     # Multiplicative inverse
    say p * p.inv # Should be 1

=head1 SEE ALSO

L<Sidef::Types::Number::Polynomial>

=cut
