Documentation

Complexity.Computability.Circuit.Boolean.CarrySave

Carry-save addition trees and logarithmic-depth bit counting #

A 3-to-2 carry-save adder (csa3to2 w) reduces three w-bit words x, y, z to a bitwise exclusive-or word csaSum x y z and a shifted carry word csaCarry x y z in constant depth (≤ 6) and linear size (≤ 20 w), preserving the sum of their unsigned values modulo 2 ^ w (val_csaSum_add_val_csaCarry_mod). Two carry-save layers form a 4-to-2 reducer (csa4to2 w) that combines two redundant carry-save pairs (a₁, b₁) and (a₂, b₂) into one pair (s, c) in depth at most 12 and size at most 40 w.

Combining k one-bit inputs along a balanced binary tree (Circuit.balanced) of 4-to-2 reducers produces a carry-save pair whose sum modulo 2 ^ w is the Hamming weight BitString.weight x, in depth O(log k) and size O(k w). Iterating csa3to2 w with a zero third word w times (finishCircuit w w) clears a further carry bit at every step (sndBits_eval_finishCircuit_eq_false), collapsing the carry-save pair to a single w-bit binary numeral in depth O(w) and size O(w²). Taking w = ⌈log₂ (k + 1)⌉ gives a De Morgan circuit (weightCircuit k) of depth O(log k) and size O(k log k) that outputs the exact binary representation of BitString.weight x (val_eval_weightCircuit) Chandra, Stockmeyer and Vishkin, Vollmer, Chapter 1.

Main definitions #

Main results #

References #

Unsigned word values and carry-save arithmetic #

The sum of the unsigned values of a carry-save pair of w-bit words.

Instances For

    The carry of a 1-bit full adder: whether at least two of the three bits are true.

    Instances For

      The bitwise exclusive-or word of a 3-to-2 carry-save adder on w-bit words.

      Instances For

        The shifted carry word of a 3-to-2 carry-save adder on w-bit words: bit 0 is false and bit i + 1 is the full-adder carry from bit i.

        Instances For
          theorem Cslib.Circuits.Boolean.val_csaSum_add_val_csaCarry_mod {w : ℕ} (x y z : BitString w) :
          (↑((BitString.equivFin w) (csaSum x y z)) + ↑((BitString.equivFin w) (csaCarry x y z))) % 2 ^ w = (↑((BitString.equivFin w) x) + ↑((BitString.equivFin w) y) + ↑((BitString.equivFin w) z)) % 2 ^ w

          Carry-save 3-to-2 invariant: the sum and shifted carry words have the same sum of unsigned values modulo 2 ^ w as the three input words.

          theorem Cslib.Circuits.Boolean.csaCarry_eq_false_of_lt {w t : ℕ} (x y : BitString w) (hy : ∀ (i : Fin w), ↑i < t → y i = false) (i : Fin w) (hi : ↑i < t + 1) :
          csaCarry x y (fun (x : Fin w) => false) i = false

          When the third word is zero and the first t bits of y are false, the first t + 1 bits of the shifted carry word csaCarry x y 0 are false.

          3-to-2 and 4-to-2 carry-save circuits #

          Formula for bit i of csaSum on three w-bit words.

          Instances For

            Formula for maj3 on three input coordinates.

            Instances For
              @[simp]
              theorem Cslib.Circuits.Boolean.eval_maj3Formula {n : ℕ} (a b c : Fin n) (u : BitString n) :
              (maj3Formula a b c).eval interpretation u = maj3 (u a) (u b) (u c)
              @[simp]
              theorem Cslib.Circuits.Boolean.size_maj3Formula {n : ℕ} (a b c : Fin n) :
              (maj3Formula a b c).size = 5

              Formula for bit i of csaCarry on three w-bit words.

              Instances For

                3-to-2 carry-save adder: reduces three w-bit words to two w-bit words (sum, carry) with the same sum modulo 2 ^ w, using at most 20 w gates and depth at most 6.

                Instances For
                  def Cslib.Circuits.Boolean.csa4to2FirstIn (w : ℕ) :
                  Fin (w + (w + w)) → Fin (w + w + (w + w))

                  Wiring selecting the first three w-bit words of two carry-save pairs.

                  Instances For
                    def Cslib.Circuits.Boolean.csa4to2 (w : ℕ) :
                    Circuit signature (w + w + (w + w)) (w + w)

                    4-to-2 carry-save reducer: combines two carry-save pairs (a₁, b₁) and (a₂, b₂) of w-bit words into a single carry-save pair in depth at most 12 and size at most 40 w.

                    Instances For
                      theorem Cslib.Circuits.Boolean.pairVal_eval_csa4to2_mod {w : ℕ} (p₁ p₂ : BitString (w + w)) :
                      pairVal ((csa4to2 w).eval interpretation (Fin.append p₁ p₂)) % 2 ^ w = (pairVal p₁ + pairVal p₂) % 2 ^ w

                      Carry-clearing iteration #

                      def Cslib.Circuits.Boolean.finishStepIn (w : ℕ) :
                      Fin (w + (w + w)) → Fin (w + w + 1)

                      Wiring that appends w copies of a single constant wire to a (w + w)-bit carry-save pair.

                      Instances For

                        One carry-clearing step: applies csa3to2 w to (a, b, 0), clearing one more low carry bit.

                        Instances For

                          t steps of carry-clearing on a (w + w)-bit carry-save pair.

                          Instances For

                            Balanced carry-save tree for Hamming weight #

                            A carry-save pair of w-bit words all of whose bits are false, from one const false gate.

                            Instances For

                              Leaf circuit placing input bit j : Fin k into bit 0 of the first w-bit word, and false on all other wires of the (w + w)-bit carry-save pair, using one const false gate.

                              Instances For

                                Balanced binary tree of csa4to2 w reducers over all k input bits.

                                Instances For

                                  Logarithmic-depth Hamming weight circuit: outputs the ⌈log₂ (k + 1)⌉-bit binary numeral of BitString.weight x (least significant bit first), using O(k log k) gates and depth O(log k).

                                  Instances For

                                    weightCircuit k computes the exact binary numeral of BitString.weight x.

                                    theorem Cslib.Circuits.Boolean.size_weightCircuit_le (k : ℕ) :
                                    (weightCircuit k).size ≤ max 1 k + k * (40 * Nat.clog 2 (k + 1)) + Nat.clog 2 (k + 1) * (20 * Nat.clog 2 (k + 1) + 1)