Documentation

TauCeti.Algebra.Polynomial.Coeff.List

Polynomials from a list of coefficients, and division by a monic polynomial #

Polynomial is a Finsupp, so none of its arithmetic reduces in the kernel. A polynomial presented instead by the list of its coefficients does compute, and this file sets up the translation, together with the one algorithm a computation on such lists needs: division by a monic polynomial.

TauCeti.Polynomial.ofCoeffList l is the polynomial whose coefficients are the entries of l, read from the highest degree down, so that it inverts Mathlib's Polynomial.coeffList (TauCeti.Polynomial.coeffList_ofCoeffList and TauCeti.Polynomial.ofCoeffList_coeffList). Its defining recursion is Horner's, ofCoeffList (l ++ [a]) = ofCoeffList l * X + C a, and every proof below runs along it. It is a noncomputable specification map: the lists are what compute.

TauCeti.Polynomial.mulCoeffList multiplies two such lists by convolving their coefficients, and TauCeti.Polynomial.ofCoeffList_mulCoeffList identifies the result with the product polynomial.

TauCeti.Polynomial.divModByMonicList t l is long division of ofCoeffList l by the monic polynomial X ^ t.length + ofCoeffList t, carried out as the usual synthetic division: a window of t.length remainder coefficients is carried along the dividend, and at each step the coefficient shifted out of the window is the next quotient coefficient and is used to clear the window against the divisor. Presenting the divisor by the list t of the coefficients below its leading one makes it monic by construction, so TauCeti.Polynomial.ofCoeffList_divByMonicList and TauCeti.Polynomial.ofCoeffList_modByMonicList, which identify the two outputs with Mathlib's /ₘ and %ₘ, need no hypotheses at all. Like Mathlib's /ₘ and %ₘ, the division needs no commutativity: the window is cleared by x - y * c, with the quotient coefficient c on the right, which is what matches Mathlib's convention f = g * q + r with the divisor on the left.

The division definitions are @[expose]d, since a consumer computing with them in another module reduces them in the kernel.

noncomputable def TauCeti.Polynomial.ofCoeffList {R : Type u_1} [Semiring R] (l : List R) :

The polynomial whose coefficients are the entries of l, highest degree first: ofCoeffList [a, b, c] = C a * X ^ 2 + C b * X + C c. This is Horner's rule, and it inverts Mathlib's Polynomial.coeffList (TauCeti.Polynomial.coeffList_ofCoeffList).

Equations
Instances For
    @[simp]

    The empty list of coefficients defines the zero polynomial.

    @[simp]

    The Horner recursion defining TauCeti.Polynomial.ofCoeffList: appending the coefficient a at the bottom multiplies the polynomial so far by X and adds the constant C a.

    @[simp]
    theorem TauCeti.Polynomial.coeff_ofCoeffList {R : Type u_1} [Semiring R] (l : List R) (i : ℕ) :

    The coefficients of TauCeti.Polynomial.ofCoeffList l are the entries of l read backwards.

    theorem TauCeti.Polynomial.eval₂_ofCoeffList {R : Type u_1} [Semiring R] {S : Type u_2} [Semiring S] (f : R →+* S) (r : S) (l : List R) :
    Polynomial.eval₂ f r (ofCoeffList l) = List.foldl (fun (y : S) (a : R) => y * r + f a) 0 l

    Evaluating TauCeti.Polynomial.ofCoeffList l is Horner's rule run directly on the list.

    A list of n coefficients defines a polynomial of degree less than n.

    @[simp]

    Splitting off the leading coefficient of a list of coefficients.

    A leading zero coefficient may be dropped. This is not a simp lemma: simp already gets there through TauCeti.Polynomial.ofCoeffList_cons.

    @[simp]

    A list of zeros defines the zero polynomial.

    Splitting off the leading coefficient of a nonempty list of coefficients.

    The top coefficient of TauCeti.Polynomial.ofCoeffList l is the head of l.

    theorem TauCeti.Polynomial.natDegree_ofCoeffList {R : Type u_1} [Semiring R] {l : List R} (h : l = [] ∨ l.headD 0 ≠ 0) :

    A list with no leading zero has exactly one more entry than the degree of the polynomial it defines. The empty list is allowed: it defines 0, of degree 0.

    A list with no leading zero has its head as the leading coefficient of the polynomial it defines. The empty list is allowed: it defines 0, whose leading coefficient is 0.

    theorem TauCeti.Polynomial.eq_of_length_eq_of_ofCoeffList_eq {R : Type u_1} [Semiring R] {l l' : List R} (hlen : l.length = l'.length) (h : ofCoeffList l = ofCoeffList l') :
    l = l'

    Two lists of the same length define the same polynomial only if they are equal. This is not injectivity of TauCeti.Polynomial.ofCoeffList, which discards leading zeros.

    theorem TauCeti.Polynomial.coeffList_ofCoeffList {R : Type u_1} [Semiring R] {l : List R} (h : l = [] ∨ l.headD 0 ≠ 0) :

    TauCeti.Polynomial.ofCoeffList inverts Mathlib's Polynomial.coeffList on the lists that arise as coefficient lists, namely those with no leading zero.

    @[simp]

    TauCeti.Polynomial.ofCoeffList is a left inverse of Mathlib's Polynomial.coeffList: every polynomial is recovered from its coefficient list.

    def TauCeti.Polynomial.mulCoeffList {R : Type u_1} [Semiring R] (l m : List R) :

    Multiplication of descending coefficient lists, by convolving them in ascending degree order. The output has the usual l.length + m.length - 1 slots; if either input is empty, all of those slots are zero. This is @[expose]d, since a consumer computing with it in another module reduces it in the kernel.

    Equations
    Instances For

      TauCeti.Polynomial.mulCoeffList lists the coefficients of a product of polynomials.

      The divisor X ^ t.length + ofCoeffList t has degree exactly t.length.

      A monic polynomial is X ^ n plus the polynomial of its remaining coefficients. This is how a computed coefficient list is recognized as a divisor for TauCeti.Polynomial.divByMonicList.

      @[simp]
      theorem TauCeti.Polynomial.ofCoeffList_map_mul_left {R : Type u_1} [Semiring R] (c : R) (l : List R) :
      ofCoeffList (List.map (fun (x : R) => c * x) l) = Polynomial.C c * ofCoeffList l

      Scaling every coefficient on the left scales the polynomial.

      @[simp]
      theorem TauCeti.Polynomial.ofCoeffList_map_neg {R : Type u_1} [Ring R] (l : List R) :
      ofCoeffList (List.map (fun (x : R) => -x) l) = -ofCoeffList l

      Negating every coefficient negates the polynomial.

      theorem TauCeti.Polynomial.ofCoeffList_zipWith_sub {R : Type u_1} [Ring R] (c : R) {l l' : List R} (h : l.length = l'.length) :
      ofCoeffList (List.zipWith (fun (x y : R) => x - y * c) l l') = ofCoeffList l - ofCoeffList l' * Polynomial.C c

      Subtracting a right multiple of one list of coefficients from another, entrywise.

      def TauCeti.Polynomial.divModByMonicStep {R : Type u_1} [Ring R] (t : List R) (qr : List R × List R) (a : R) :

      One step of synthetic division by the monic polynomial X ^ t.length + ofCoeffList t: the pair qr holds the quotient coefficients found so far together with a window of t.length remainder coefficients, and a is the next coefficient of the dividend.

      Equations
      Instances For
        @[simp]
        theorem TauCeti.Polynomial.divModByMonicStep_fst {R : Type u_1} [Ring R] (t : List R) (qr : List R × List R) (a : R) :
        (divModByMonicStep t qr a).1 = qr.1 ++ [(qr.2 ++ [a]).headD 0]

        One step of synthetic division appends the coefficient shifted out of the remainder window to the quotient.

        @[simp]
        theorem TauCeti.Polynomial.divModByMonicStep_snd {R : Type u_1} [Ring R] (t : List R) (qr : List R × List R) (a : R) :
        (divModByMonicStep t qr a).2 = List.zipWith (fun (x y : R) => x - y * (qr.2 ++ [a]).headD 0) (qr.2 ++ [a]).tail t

        One step of synthetic division clears the remaining window against the divisor.

        def TauCeti.Polynomial.divModByMonicList {R : Type u_1} [Ring R] (t l : List R) :

        Long division of the polynomial with coefficient list l by the monic polynomial X ^ t.length + ofCoeffList t, by synthetic division. The first component is the coefficient list of the quotient, the second that of the remainder.

        Equations
        Instances For
          def TauCeti.Polynomial.divByMonicList {R : Type u_1} [Ring R] (t l : List R) :

          The quotient of ofCoeffList l by the monic polynomial X ^ t.length + ofCoeffList t, as a coefficient list.

          Equations
          Instances For
            def TauCeti.Polynomial.modByMonicList {R : Type u_1} [Ring R] (t l : List R) :

            The remainder of ofCoeffList l on division by the monic polynomial X ^ t.length + ofCoeffList t, as a coefficient list.

            Equations
            Instances For
              @[simp]

              Dividing the zero polynomial leaves the empty quotient and the zero remainder window.

              @[simp]

              The division sweeps the dividend from the top coefficient down, one step per coefficient.

              The remainder window keeps the length of the divisor's degree throughout the division.

              @[simp]

              The computed remainder has the length of the divisor's degree.

              The division identity for synthetic division: at every stage of the sweep, the part of the dividend read so far is the divisor times the quotient found so far, plus the remainder window.

              @[simp]

              Synthetic division computes the quotient: the first output of TauCeti.Polynomial.divModByMonicList is Mathlib's /ₘ by the monic divisor.

              @[simp]

              Synthetic division computes the remainder: the second output of TauCeti.Polynomial.divModByMonicList is Mathlib's %ₘ by the monic divisor.