Documentation

Complexity.Computability.WordRAM.Multiword.Mul

Schoolbook multiplication on the checked word RAM #

The code is unrolled for fixed operand lengths. Each row adds one shifted digit product to the accumulator and appends its final carry. Leading zero updates make the active accumulator and shifted operand have the same length.

Main definitions #

Main results #

Inputs and outputs use little-endian half-word digits. Conversion from other representations is not part of the routine. Odd widths use the same floor-half radix. Widths zero and one are excluded: their floor-half radix is one and cannot represent a nonzero integer.

References #

The in-place form of LimbUpdate.program: five ordinary instructions for one multiply-add, overwriting the destination digit after reading it.

Instances For
    def Cslib.WordRAM.Multiword.Schoolbook.cellResult {r : ℕ} (x : Data (r + 4)) (a b d : Fin (r + 4)) :
    Data (r + 4)

    All workspace is included in the exact result of a cell.

    Instances For
      def Cslib.WordRAM.Multiword.Schoolbook.row {r : ℕ} (a : Fin (r + 4)) :
      List (Fin (r + 4)) → List (Fin (r + 4)) → Code Basis.standard (r + 4)

      Update a full row. The final self-copy gives the empty row a one-instruction execution.

      Instances For
        theorem Cslib.WordRAM.Multiword.Schoolbook.size_row {r : ℕ} (a : Fin (r + 4)) (bs ds : List (Fin (r + 4))) (hlen : bs.length = ds.length) :
        (row a bs ds).size = 5 * ds.length + 1

        A row has one five-instruction cell per digit and one final self-copy.

        theorem Cslib.WordRAM.Multiword.Schoolbook.exec_row {r w : ℕ} (hw : 2 ≤ w) (I : Set (Fin (r + 4))) (hI : ∀ i ∈ I, i ≠ Workspace.total ∧ i ≠ Workspace.carry) (a : Fin (r + 4)) (haI : a ∈ I) (bs ds : List (Fin (r + 4))) (hlen : bs.length = ds.length) (hbs : ∀ b ∈ bs, b ∈ I) (hds : ∀ d ∈ ds, Workspace.IsDigit d ∧ d ∉ I) (hnd : ds.Nodup) (x : Data (r + 4)) (hbase : x.regs Workspace.base = radix w) (ha : x.regs a < radix w) (hb : Bounded (radix w) x bs) (hd : Bounded (radix w) x ds) (hc : x.regs Workspace.carry < radix w) :
        ∃ (y : Data (r + 4)), Exec w (row a bs ds) x y (5 * ds.length + 1) ∧ Bounded (radix w) y ds ∧ y.regs Workspace.carry < radix w ∧ value (radix w) y ds + radix w ^ ds.length * y.regs Workspace.carry = x.regs a * value (radix w) x bs + value (radix w) x ds + x.regs Workspace.carry ∧ Workspace.Frame x y ds

        Execute an entire row, with exact reconstruction including its final carry. I is any set of preserved input registers, disjoint from the destination registers.

        def Cslib.WordRAM.Multiword.Schoolbook.rows {r : ℕ} :
        List (Fin (r + 4)) → List (Fin (r + 4)) → List (Fin (r + 4)) → List (Fin (r + 4)) → Code Basis.standard (r + 4)

        Unrolled schoolbook rows. ds is the current accumulator and os supplies one fresh high digit per remaining multiplicand digit. The multiplier gains a leading zero each row.

        Instances For

          Exact instruction count of the unrolled rows, including empty-row self-copies.

          Instances For
            theorem Cslib.WordRAM.Multiword.Schoolbook.rowCost_eq (m n : ℕ) :
            rowCost m n = 5 * (m * n + m * (m - 1) / 2) + 3 * m + 1

            The extra cells are the leading-zero updates in successive shifted rows.

            theorem Cslib.WordRAM.Multiword.Schoolbook.size_rows {r : ℕ} (as bs ds os : List (Fin (r + 4))) (hlen : bs.length = ds.length) (hos : os.length = as.length) :
            (rows as bs ds os).size = rowCost as.length bs.length
            theorem Cslib.WordRAM.Multiword.Schoolbook.rowCost_le (m n : ℕ) :
            rowCost m n ≤ 5 * m * (n + m) + 3 * m + 1

            The runtime is constant for fixed operand lengths, independently of the physical width.

            theorem Cslib.WordRAM.Multiword.Schoolbook.exec_rows {r w : ℕ} (hw : 2 ≤ w) (I : Set (Fin (r + 4))) (hI : ∀ i ∈ I, i ≠ Workspace.total ∧ i ≠ Workspace.carry) (hzI : Workspace.zero ∈ I) (as bs ds os : List (Fin (r + 4))) (hlen : bs.length = ds.length) (hos : os.length = as.length) (has : ∀ a ∈ as, a ∈ I) (hbs : ∀ b ∈ bs, b ∈ I) (hds : ∀ d ∈ ds ++ os, Workspace.IsDigit d ∧ d ∉ I) (hnd : (ds ++ os).Nodup) (x : Data (r + 4)) (hbase : x.regs Workspace.base = radix w) (hz : x.regs Workspace.zero = 0) (ha : Bounded (radix w) x as) (hb : Bounded (radix w) x bs) (hd : Bounded (radix w) x ds) :
            ∃ (y : Data (r + 4)), Exec w (rows as bs ds os) x y (rowCost as.length bs.length) ∧ Bounded (radix w) y (ds ++ os) ∧ value (radix w) y (ds ++ os) = value (radix w) x ds + value (radix w) x as * value (radix w) x bs ∧ Workspace.Frame x y (ds ++ os)

            Complete schoolbook multiplication with an arbitrary initial accumulator. The theorem constructs an execution and proves its product equation; no multiplication specification is assumed. The accumulator grows by one carry digit per row.

            Clear the initial accumulator; the empty clear uses one carry self-copy.

            Instances For
              def Cslib.WordRAM.Multiword.Schoolbook.program {r : ℕ} (as bs ds os : List (Fin (r + 4))) :

              Complete multiplication: initialize the radix and zero, clear the initial accumulator, and execute all rows. Operand and output register lists are fixed at code construction time.

              Instances For
                theorem Cslib.WordRAM.Multiword.Schoolbook.size_program {r : ℕ} (as bs ds os : List (Fin (r + 4))) (hlen : bs.length = ds.length) (hos : os.length = as.length) :
                (program as bs ds os).size = 7 + bs.length + rowCost as.length bs.length

                Exact code size, which is also the exact execution time on valid inputs.

                theorem Cslib.WordRAM.Multiword.Schoolbook.exec {r w : ℕ} (hw : 2 ≤ w) (as bs ds os : List (Fin (r + 4))) (hlen : bs.length = ds.length) (hos : os.length = as.length) (hin : ∀ i ∈ as ++ bs, Workspace.IsDigit i) (hout : ∀ i ∈ ds ++ os, Workspace.IsDigit i) (hnd : (ds ++ os).Nodup) (hdis : (ds ++ os).Disjoint (as ++ bs)) (x : Data (r + 4)) (ha : Bounded (radix w) x as) (hb : Bounded (radix w) x bs) :
                ∃ (y : Data (r + 4)), Exec w (program as bs ds os) x y (7 + bs.length + rowCost as.length bs.length) ∧ Bounded (radix w) y (ds ++ os) ∧ value (radix w) y (ds ++ os) = value (radix w) x as * value (radix w) x bs ∧ y.mem = x.mem ∧ ∀ i ∈ as ++ bs, y.regs i = x.regs i

                Multiplication of two arbitrary fixed-length little-endian digit lists. All outputs start arbitrary: initialization is part of the charged code. Every arithmetic operation uses the original physical width and checked overflow. The complete product occupies ds ++ os. The layout assumptions express only nonaliasing and reserved-register separation.

                def Cslib.WordRAM.Multiword.Schoolbook.registers {r : ℕ} (start len : ℕ) (h : start + len ≤ r) :
                List (Fin (r + 4))

                A contiguous list of digit registers, after the four reserved workspace registers.

                Instances For

                  The first operand occupies the first m digit registers.

                  Instances For

                    The second operand follows the first.

                    Instances For

                      The m + n result digits follow both operands.

                      Instances For

                        Initial zero accumulator, with the second operand's length.

                        Instances For

                          One fresh high digit for each schoolbook row.

                          Instances For

                            A concrete schoolbook program with 2 * (m + n) + 4 registers and no address words. The code and register count depend only on the limb counts, not on the physical word width.

                            Instances For
                              theorem Cslib.WordRAM.Multiword.Schoolbook.size_fixedProgram_eq (m n : ℕ) :
                              (fixedProgram m n).size = 5 * (m * n + m * (m - 1) / 2) + 3 * m + n + 8

                              Closed form of the exact instruction count, including setup and initialization.

                              theorem Cslib.WordRAM.Multiword.Schoolbook.size_fixedProgram_le {m n : ℕ} (hm : m ≤ 18) (hn : n ≤ 18) :
                              (fixedProgram m n).size ≤ 2465

                              The same constant bounds every choice of operand lengths up to eighteen digits.

                              theorem Cslib.WordRAM.Multiword.Schoolbook.exec_fixedProgram {w : ℕ} (hw : 2 ≤ w) (m n : ℕ) (x : Data (2 * (m + n) + 4)) (ha : Bounded (radix w) x (leftRegs m n)) (hb : Bounded (radix w) x (rightRegs m n)) :
                              ∃ (y : Data (2 * (m + n) + 4)), Exec w (fixedProgram m n) x y (7 + n + rowCost m n) ∧ Bounded (radix w) y (outputRegs m n) ∧ value (radix w) y (outputRegs m n) = value (radix w) x (leftRegs m n) * value (radix w) x (rightRegs m n) ∧ y.mem = x.mem ∧ ∀ i ∈ leftRegs m n ++ rightRegs m n, y.regs i = x.regs i

                              The concrete fixed-register schoolbook program multiplies all bounded operands, including zero-length operands, at every physical width at least two. The output has m + n bounded digits, reconstructs the exact product, and preserves memory and both operands.

                              theorem Cslib.WordRAM.Multiword.Schoolbook.exec_eighteen {w : ℕ} (hw : 2 ≤ w) (x : Data 76) (ha : Bounded (radix w) x (leftRegs 18 18)) (hb : Bounded (radix w) x (rightRegs 18 18)) :
                              ∃ (y : Data (2 * (18 + 18) + 4)), Exec w (fixedProgram 18 18) x y 2465 ∧ Bounded (radix w) y (outputRegs 18 18) ∧ value (radix w) y (outputRegs 18 18) = value (radix w) x (leftRegs 18 18) * value (radix w) x (rightRegs 18 18) ∧ y.mem = x.mem ∧ ∀ i ∈ leftRegs 18 18 ++ rightRegs 18 18, y.regs i = x.regs i

                              Eighteen digits per operand give a fixed 76-register, 2465-instruction program. This accommodates six physical words per operand even at odd widths, including width three.

                              def Cslib.WordRAM.Multiword.Schoolbook.input (m n : ℕ) (a : Fin m → ℕ) (b : Fin n → ℕ) :
                              Data (2 * (m + n) + 4)

                              Encode two fixed digit tuples into the concrete layout, with zero workspace and memory. This is an input encoding, not a RAM conversion routine.

                              Instances For
                                theorem Cslib.WordRAM.Multiword.Schoolbook.value_input_left (β m n : ℕ) (a : Fin m → ℕ) (b : Fin n → ℕ) :
                                value β (input m n a b) (leftRegs m n) = Nat.ofDigits β (List.ofFn a)
                                theorem Cslib.WordRAM.Multiword.Schoolbook.value_input_right (β m n : ℕ) (a : Fin m → ℕ) (b : Fin n → ℕ) :
                                value β (input m n a b) (rightRegs m n) = Nat.ofDigits β (List.ofFn b)
                                theorem Cslib.WordRAM.Multiword.Schoolbook.bounded_input_left {β : ℕ} (m n : ℕ) (a : Fin m → ℕ) (b : Fin n → ℕ) (ha : ∀ (i : Fin m), a i < β) :
                                Bounded β (input m n a b) (leftRegs m n)
                                theorem Cslib.WordRAM.Multiword.Schoolbook.bounded_input_right {β : ℕ} (m n : ℕ) (a : Fin m → ℕ) (b : Fin n → ℕ) (hb : ∀ (i : Fin n), b i < β) :
                                Bounded β (input m n a b) (rightRegs m n)
                                theorem Cslib.WordRAM.Multiword.Schoolbook.input_bounded {w : ℕ} (hw : 2 ≤ w) (m n : ℕ) (a : Fin m → ℕ) (b : Fin n → ℕ) (ha : ∀ (i : Fin m), a i < radix w) (hb : ∀ (i : Fin n), b i < radix w) :
                                Data.Bounded w (input m n a b)

                                Bounded digit tuples encode globally bounded RAM data.

                                theorem Cslib.WordRAM.Multiword.Schoolbook.six_word_product {w a b : ℕ} (hw : 2 ≤ w) (ha : a < 2 ^ (6 * w)) (hb : b < 2 ^ (6 * w)) :
                                ∃ (x : Data 76) (y : Data 76), Data.Bounded w x ∧ Data.Bounded w y ∧ Exec w (fixedProgram 18 18) x y 2465 ∧ value (radix w) x (leftRegs 18 18) = a ∧ value (radix w) x (rightRegs 18 18) = b ∧ Bounded (radix w) y (outputRegs 18 18) ∧ value (radix w) y (outputRegs 18 18) = a * b

                                Any two values smaller than six physical words have a globally bounded digit encoding on which the concrete checked program computes their full product in 2465 instructions. The encoding is specified separately; the runtime starts with the encoded operands.