Documentation

Interval.UInt128

UInt128: 128-bit integers #

Definitions and basics #

@[unbox]
structure UInt128 :
Instances For
    theorem UInt128.ext {x y : UInt128} (lo : x.lo = y.lo) (hi : x.hi = y.hi) :
    x = y
    theorem UInt128.ext_iff {x y : UInt128} :
    x = y x.lo = y.lo x.hi = y.hi
    def instDecidableEqUInt128.decEq (x✝ x✝¹ : UInt128) :
    Decidable (x✝ = x✝¹)
    Equations
    Instances For
      Equations
      Instances For
        Equations
        Instances For
          Equations
          Instances For
            Equations
            Equations
            @[irreducible]
            Equations
            Instances For
              Equations
              Instances For
                @[simp]
                @[simp]
                @[simp]
                theorem UInt128.zero_lo :
                lo 0 = 0
                @[simp]
                theorem UInt128.zero_hi :
                hi 0 = 0
                theorem UInt128.toNat_def {x : UInt128} :
                x.toNat = x.hi.toNat * 2 ^ 64 + x.lo.toNat
                @[simp]
                theorem UInt128.toReal_zero :
                0 = 0
                @[simp]
                theorem UInt128.toReal_one :
                1 = 1
                theorem UInt128.lt_size (x : UInt128) :
                x.toNat < 2 ^ 128
                theorem UInt128.coe_nonneg (x : UInt128) :
                0 x
                theorem UInt128.coe_lt_size (x : UInt128) :
                x < 2 ^ 128
                noncomputable instance instCoeTailUInt128ZMod {n : } :
                Equations
                @[simp]
                theorem UInt128.toNat_max :
                max.toNat = 2 ^ 128 - 1
                @[simp]
                theorem Nat.mod_mul_eq_mul_mod_128 (a : ) :
                a * 2 ^ 64 % 2 ^ 128 = a % 2 ^ 64 * 2 ^ 64
                @[simp]
                @[simp]
                theorem UInt128.eq_zero_iff (x : UInt128) :
                x = 0 x.toNat = 0
                @[simp]
                theorem UInt128.toNat_lo {x : UInt128} (h : x.toNat < 2 ^ 64) :
                def UInt128.blt (x y : UInt128) :
                Equations
                Instances For
                  @[simp]
                  theorem UInt128.toNat_lt (x : UInt128) :
                  x.toNat < 2 ^ 128

                  Wrap around conversion from ℕ, ℤ to UInt128 #

                  @[irreducible]
                  Equations
                  Instances For
                    @[irreducible]
                    Equations
                    Instances For
                      @[simp]
                      theorem UInt128.toNat_ofNat (x : ) :
                      (ofNat x).toNat = x % 2 ^ 128
                      @[simp]
                      theorem UInt128.ofInt_toInt (x : UInt128) :
                      ofInt x.toNat = x
                      @[simp]
                      theorem UInt128.toInt_ofInt (x : ) :
                      (ofInt x).toNat = x % 2 ^ 128
                      @[simp]
                      @[simp]
                      theorem UInt128.ofInt_pow :
                      ofInt (2 ^ 128) = 0

                      128-bit increment #

                      @[irreducible]
                      Equations
                      Instances For
                        @[simp]
                        theorem UInt128.toNat_succ {x : UInt128} (h : x.toNat 2 ^ 128 - 1) :
                        theorem UInt128.toNat_succ' (x : UInt128) :
                        x.succ.toNat = if x.toNat = 2 ^ 128 - 1 then 0 else x.toNat + 1
                        theorem UInt128.coe_succ {x : UInt128} (h : x 2 ^ 128 - 1) :
                        x.succ = x + 1

                        Complement #

                        Equations
                        theorem UInt128.complement_def (x : UInt128) :
                        ~~~x = { lo := ~~~x.lo, hi := ~~~x.hi }
                        theorem UInt128.toNat_complement {x : UInt128} :
                        (~~~x).toNat = 2 ^ 128 - 1 - x.toNat

                        Twos complement negation #

                        Equations
                        @[simp]
                        theorem UInt128.neg_zero :
                        -0 = 0
                        theorem UInt128.toNat_neg (x : UInt128) :
                        (-x).toNat = if x = 0 then 0 else 2 ^ 128 - x.toNat
                        @[simp]
                        theorem UInt128.neg_ofInt (x : ) :

                        ofInt commutes with -

                        128-bit addition and (twos complement) subtraction #

                        @[irreducible]
                        Equations
                        Instances For
                          Equations
                          theorem UInt128.add_def (x y : UInt128) :
                          x + y = x.add y
                          theorem UInt128.sub_def (x y : UInt128) :
                          x - y = x + -y
                          theorem UInt128.toNat_add (x y : UInt128) :
                          (x + y).toNat = (x.toNat + y.toNat) % 2 ^ 128

                          add is modular

                          @[simp]
                          theorem UInt128.add_ofInt (x y : ) :
                          ofInt x + ofInt y = ofInt (x + y)

                          ofInt commutes with +

                          @[simp]
                          theorem UInt128.sub_ofInt (x y : ) :
                          ofInt x - ofInt y = ofInt (x - y)

                          ofInt commutes with -

                          UInt128 inherits the additive group structure from

                          Equations
                          • One or more equations did not get rendered due to their size.

                          64 → 128 bit multiplication #

                          We define the product of two UInt64s, as a 128-bit int. Let s = 2^32. Then we have

                          x = x1 s + x0 y = y1 s + y0 x y = x1 y1 s^2 + (x1 y0 + x0 y1) s + x0 y0

                          Using addc, we have

                          x y = x1 y1 s^2 + (x1 y0 + x0 y1) s + x0 y0 a1, a3 = addc (x1 y0) (x0 y1) x y = (a3 s + x1 y1) s^2 + a1 s + x0 y0 b1, b2 = split a1 x y = (a3 s + x1 y1 + b2) s^2 + b1 s + x0 y0 c0, c2 = addc (x0 y0) b1 x y = (a3 s + x1 y1 + b2 + c2) s^2 + c0

                          @[irreducible]
                          def mul128 (x y : UInt64) :

                          All the bits of two UInt64 multiplied together

                          Equations
                          • One or more equations did not get rendered due to their size.
                          Instances For
                            theorem mul_lt_32 {x y : } (xl : x < 2 ^ 32) (yl : y < 2 ^ 32) :
                            theorem toNat_mul128_mod (x y : UInt64) :
                            (mul128 x y).toNat % 2 ^ 128 = x.toNat * y.toNat % 2 ^ 128

                            mul128 is correct mod 2^128

                            @[simp]
                            theorem toNat_mul128 (x y : UInt64) :

                            mul128 is correct

                            128 bit shifting #

                            @[irreducible]

                            Multiply by 2^(s % 128), discarding overflow bits

                            Equations
                            • One or more equations did not get rendered due to their size.
                            Instances For
                              @[irreducible]

                              Divide by 2^(s % 128), rounding down

                              Equations
                              • One or more equations did not get rendered due to their size.
                              Instances For
                                @[irreducible]

                                Divide by 2^s, rounding up or down

                                Equations
                                Instances For
                                  @[irreducible]

                                  Multiply by 2^s, saturating at UInt128.max if we overflow

                                  Equations
                                  Instances For
                                    theorem UInt128.testBit_eq {x : UInt128} {i : } :

                                    testBit for UInt128

                                    theorem UInt128.testBit_eq_zero {x : UInt128} {i : } (h : 128 i) :

                                    testBit is zero for large i

                                    theorem tb_eq {x : UInt64} {i j : } (ij : i = j 64 i 64 j) :
                                    theorem tb_ne {x y : UInt64} {i j : } (il : 64 i) (jl : 64 j) :
                                    theorem false_tb {x : UInt64} {i : } (il : 64 i) :
                                    theorem tb_false {x : UInt64} {i : } (il : 64 i) :
                                    theorem p64 :
                                    theorem p127 :
                                    UInt64.toNat 127 = 127
                                    theorem p128 :
                                    UInt64.toNat 128 = 128
                                    theorem p64s :
                                    (2 ^ 64 - 1).toNat = 2 ^ 64 - 1
                                    theorem ts0 {t : } (h : t < 64) :
                                    theorem ts1 {t : } (h : t < 128) :
                                    theorem shift0 {t : } (t0 : t 0) (t64 : t < 64) :
                                    (64 - UInt64.ofNat t).toNat % 64 = 64 - t
                                    theorem t127 {t : } (h : t < 128) :
                                    t &&& 127 = t
                                    theorem t127' {t : } (h : t < 128) :
                                    theorem e0 {t : } (t0 : t 0) (t64 : t < 64) :
                                    (64 - UInt64.ofNat t).toNat % 64 = 64 - t
                                    theorem e1 {t : } (h : t < 64) :
                                    64 - (64 - t) = t
                                    theorem e2 {t i : } (h : t < 64) :
                                    i - (64 - t) = i + t - 64
                                    theorem e3 {t : } (t64 : 64 t) (t128 : t < 128) :
                                    (UInt64.ofNat t - 64).toNat % 64 = t - 64
                                    theorem e4 {t i : } (h : 64 t) :
                                    i + (t - 64) = i + t - 64
                                    theorem e6 {t : } (t0 : t 0) (t64 : t < 64) :
                                    (64 - UInt64.ofNat t).toNat % 64 = 64 - t
                                    theorem e7 {t i : } (hi : 64 i) (ht : t < 64) :
                                    i - 64 + (64 - t) = i - t
                                    theorem e8 {t i : } (ht : 64 t) :
                                    i - 64 - (t - 64) = i - t
                                    theorem e9 {t : } (h : t < 128) :
                                    (128 - UInt64.ofNat t).toNat = 128 - t
                                    theorem e10 :
                                    128 &&& 127 = 0
                                    theorem a1 {t i : } (t0 : t 0) (i64 : i < 64) :
                                    i + t - 64 < t
                                    theorem a2 {x : UInt128} {t : } {x0 : x 0} (h : 128 t) :
                                    ¬x.toNat * 2 ^ t 2 ^ 128 - 1
                                    theorem a4 {t i : } (hi : i < 64) (ht : 64 t) :
                                    ¬t i
                                    theorem a5 {t i : } (hi : i < 64) (ti : t < 64) :
                                    i - t < 64 - t
                                    theorem UInt128.toNat_shiftLeft (x : UInt128) {s : UInt64} (sl : s < 128) :
                                    (x <<< s).toNat = x.toNat * 2 ^ s.toNat % 2 ^ 128

                                    shiftLeft is multiplication mod 2^128.

                                    theorem UInt128.toNat_shiftLeft' (x : UInt128) {s : UInt64} :
                                    (x <<< s).toNat = x.toNat * 2 ^ (s.toNat % 128) % 2 ^ 128

                                    shiftLeft is multiplication mod 2^128.

                                    @[simp]
                                    theorem UInt128.shiftLeft_zero (x : UInt128) :
                                    x <<< 0 = x

                                    Shifting left by zero does nothing

                                    @[simp]
                                    theorem UInt128.zero_shiftLeft (s : UInt64) :
                                    0 <<< s = 0

                                    Shifting zero does nothing

                                    theorem UInt128.toNat_shiftRight (x : UInt128) {s : UInt64} (sl : s < 128) :
                                    (x >>> s).toNat = x.toNat / 2 ^ s.toNat

                                    shiftRight rounds down

                                    theorem UInt128.toNat_shiftRight' (x : UInt128) {s : UInt64} :
                                    (x >>> s).toNat = x.toNat / 2 ^ (s.toNat % 128)

                                    shiftRight rounds down

                                    theorem UInt128.coe_shiftRight (x : UInt128) {s : UInt64} (sl : s < 128) :
                                    ↑(x >>> s) = ↑(x.toNat / 2 ^ s.toNat)
                                    theorem UInt128.toInt_shiftRightRound (x : UInt128) (s : UInt64) (up : Bool) :
                                    (x.shiftRightRound s up).toNat = (↑x.toNat).rdiv (2 ^ s.toNat) up

                                    shiftRightRound.toNat = rdiv

                                    theorem UInt128.approx_shiftRightRound (x : UInt128) (s : UInt64) (up : Bool) :
                                    Rounds (↑(x.shiftRightRound s up)) (x / 2 ^ s.toNat) up

                                    shiftRightRound rounds as desired

                                    @[simp]
                                    theorem UInt128.zero_shiftRight {s : UInt64} :
                                    0 >>> s = 0
                                    @[simp]
                                    @[simp]

                                    log2 #

                                    @[irreducible]
                                    Equations
                                    Instances For
                                      @[simp]
                                      theorem UInt128.log2_le_127 (x : UInt128) :
                                      x.log2 127
                                      @[simp]
                                      @[simp]
                                      theorem UInt128.log2_zero :
                                      log2 0 = 0
                                      @[simp]
                                      theorem UInt128.toNat_lo_of_log2_lt {x : UInt128} (h : x.toNat.log2 < 64) :
                                      theorem UInt128.toNat_hi_shiftRightRound_le_hi {y s : UInt64} {up : Bool} :
                                      ({ lo := 0, hi := y }.shiftRightRound s up).hi.toNat y.toNat

                                      Shifting some high bits down produces a small value