Filtering...

signed-byte-p

books/centaur/bitops/signed-byte-p
other
(in-package "BITOPS")
other
(include-book "xdoc/top" :dir :system)
other
(include-book "ihs/basic-definitions" :dir :system)
other
(include-book "std/util/defrule" :dir :system)
other
(local (include-book "arithmetic/top-with-meta" :dir :system))
other
(local (include-book "tools/do-not" :dir :system))
other
(local (in-theory (disable signed-byte-p
      floor
      truncate
      mod
      rem)))
other
(local (do-not generalize fertilize))
other
(local (defthm signed-byte-p-forward
    (implies (signed-byte-p width x)
      (and (posp width) (integerp x)))
    :rule-classes :forward-chaining :hints (("Goal" :in-theory (enable signed-byte-p)))))
other
(local (defthm unsigned-byte-p-forward
    (implies (unsigned-byte-p width x)
      (and (natp width) (natp x)))
    :rule-classes :forward-chaining :hints (("Goal" :in-theory (enable unsigned-byte-p)))))
other
(defsection bitops/signed-byte-p
  :parents (bitops signed-byte-p
    unsigned-byte-p)
  :short "Lemmas about @(see signed-byte-p) and @(see unsigned-byte-p) that are
often useful when optimizing definitions with @(see acl2::type-spec)
declarations.")
other
(local (set-default-parents bitops/signed-byte-p))
other
(defrule basic-unsigned-byte-p-of-+
  (implies (and (unsigned-byte-p n a)
      (unsigned-byte-p n b))
    (unsigned-byte-p (+ 1 n)
      (+ a b)))
  :enable unsigned-byte-p
  :short "Adding N-bit unsigneds creates an N+1 bit unsigned."
  :long "<p>ACL2's fancy unification stuff means this works fine in the common
  case that you're dealing with quoted constants for N and N+1.  See also @(see
  basic-unsigned-byte-p-of-+-with-cin).</p>")
other
(defrule basic-unsigned-byte-p-of-+-with-cin
  (implies (and (bitp cin)
      (unsigned-byte-p n a)
      (unsigned-byte-p n b))
    (unsigned-byte-p (+ 1 n)
      (+ cin a b)))
  :rule-classes ((:rewrite) (:rewrite :corollary (implies (and (bitp cin)
          (unsigned-byte-p n a)
          (unsigned-byte-p n b))
        (unsigned-byte-p (+ 1 n)
          (+ a b cin)))))
  :enable unsigned-byte-p
  :short "Adding N-bit unsigneds with a carry bit creates an N+1 bit unsigned."
  :long "<p>ACL2's fancy unification stuff means this works fine in the common
  case that you're dealing with quoted constants for N and N+1.  See also @(see
  basic-unsigned-byte-p-of-+).</p>")
other
(defrule basic-signed-byte-p-of-+
  (implies (and (signed-byte-p n a)
      (signed-byte-p n b))
    (signed-byte-p (+ 1 n)
      (+ a b)))
  :enable signed-byte-p
  :short "Adding N-bit signeds creates an N+1 bit signed."
  :long "<p>ACL2's fancy unification stuff means this works fine in the common
  case that you're dealing with quoted constants for N and N+1.  See also @(see
  basic-signed-byte-p-of-+-with-cin).</p>")
other
(defrule basic-signed-byte-p-of-+-with-cin
  (implies (and (bitp cin)
      (signed-byte-p n a)
      (signed-byte-p n b))
    (signed-byte-p (+ 1 n)
      (+ cin a b)))
  :rule-classes ((:rewrite) (:rewrite :corollary (implies (and (bitp cin)
          (signed-byte-p n a)
          (signed-byte-p n b))
        (signed-byte-p (+ 1 n)
          (+ cin a b)))))
  :enable signed-byte-p
  :short "Adding N+1 bit signeds with a carry bit creates an N+1 bit signed."
  :long "<p>ACL2's fancy unification stuff means this works fine in the common
  case that you're dealing with quoted constants for N and N+1.  See also @(see
  basic-signed-byte-p-of-+).</p>")
other
(defrule basic-signed-byte-p-of-unary-minus
  (implies (signed-byte-p n x)
    (signed-byte-p (+ 1 n) (- x)))
  :enable signed-byte-p
  :short "Negative N-bit signed is an N+1 bit signed."
  :long "<p>The N+1 is needed in case of the minimum integer.</p>

  <p>ACL2's fancy unification stuff means this works fine in the common case
  that you're dealing with quoted constants for N and N+1.  See also @(see
  basic-signed-byte-p-of-unary-minus-2) and @(see
  basic-signed-byte-p-of-binary-minus).</p>")
other
(defrule basic-signed-byte-p-of-unary-minus-2
  (implies (unsigned-byte-p n x)
    (signed-byte-p (+ 1 n) (- x)))
  :enable (signed-byte-p unsigned-byte-p)
  :short "Negative N-bit unsigned is an N+1 bit signed."
  :long "<p>ACL2's fancy unification stuff means this works fine in the common
  case that you're dealing with quoted constants for N and N+1.  See also @(see
  basic-signed-byte-p-of-unary-minus) and @(see
  basic-signed-byte-p-of-binary-minus).</p>")
other
(defrule basic-signed-byte-p-of-binary-minus
  (implies (and (signed-byte-p n a)
      (signed-byte-p n b))
    (signed-byte-p (+ 1 n)
      (- a b)))
  :enable signed-byte-p
  :short "Subtracting N-bit signeds creates an N+1 bit signed."
  :long "<p>ACL2's fancy unification stuff means this works fine in the common
  case that you're dealing with quoted constants.</p>

  <p>You might ask, why have this rule when we have rules like @(see
  basic-signed-byte-p-of-+)?  After all, @('(- a b)') is just the same as @('(+
  a (unary-- b))').  The answer is: the rule about @('(signed-byte-p (unary--
  x))'), @(see basic-signed-byte-p-of-unary-minus), isn't very nice because of
  , and doesn't give us doesn't really give us an indirect way to get here.</p>

  <p>See also @(see basic-signed-byte-p-of-unary-minus) and @(see
  basic-signed-byte-p-of-unary-minus-2).</p>")
other
(defsection unsigned-byte-p-of-minus-when-signed-byte-p
  :short "Negating an N-bit signed creates an N-bit unsigned exactly when it
          was negative."
  (local (defthmd l1
      (implies (and (< x 0)
          (<= (- (expt 2 (+ -1 n))) x)
          (integerp x)
          (natp n))
        (<= (- x) (expt 2 (+ -1 n))))))
  (local (defthmd l2
      (implies (natp n)
        (< (expt 2 (+ -1 n)) (expt 2 n)))))
  (local (defthmd l3
      (implies (and (< x 0)
          (<= (- (expt 2 (+ -1 n))) x)
          (integerp x)
          (natp n))
        (< (- x) (expt 2 n)))
      :hints (("Goal" :in-theory (disable expt-is-increasing-for-base>1)
         :use ((:instance l1) (:instance l2))))))
  (local (in-theory (enable signed-byte-p
        unsigned-byte-p)))
  (local (defthmd l4
      (implies (and (signed-byte-p n x)
          (< x 0))
        (unsigned-byte-p n (- x)))
      :hints (("Goal" :in-theory (enable l3)))))
  (defthm unsigned-byte-p-of-minus-when-signed-byte-p
    (implies (signed-byte-p n x)
      (equal (unsigned-byte-p n (- x))
        (<= x 0)))
    :hints (("Goal" :in-theory (enable l4)
       :cases ((< x 0) (= x 0))))))
other
(defsection unsigned-byte-p-of-abs-when-signed-byte-p
  :short "Absolute value of an N-bit signed is an N-bit unsigned."
  (local (defthmd l0
      (implies (and (signed-byte-p n x)
          (< x 0))
        (unsigned-byte-p n (abs x)))))
  (local (defthmd l1
      (implies (natp n)
        (< (expt 2 (+ -1 n)) (expt 2 n)))
      :rule-classes ((:rewrite) (:linear))))
  (local (defthmd l2
      (implies (and (signed-byte-p n x)
          (<= 0 x))
        (unsigned-byte-p n (abs x)))
      :hints (("Goal" :in-theory (enable unsigned-byte-p
           signed-byte-p
           l1)))))
  (defthm unsigned-byte-p-of-abs-when-signed-byte-p
    (implies (signed-byte-p n x)
      (unsigned-byte-p n (abs x)))
    :hints (("Goal" :use ((:instance l0) (:instance l2))))))
other
(defrule signed-byte-p-of-decrement-when-natural-signed-byte-p
  (implies (and (signed-byte-p n x)
      (<= 0 x))
    (signed-byte-p n (1- x)))
  :enable (signed-byte-p)
  :short "Decrementing a positive N-bit signed creates an N-bit signed.")
other
(defsection basic-unsigned-byte-p-of-*
  :autodoc nil
  (local (defthmd lem-multiply-bound
      (implies (and (natp a1)
          (natp a2)
          (natp b1)
          (natp b2)
          (< a1 b1)
          (< a2 b2))
        (< (* a1 a2) (* b1 b2)))
      :hints (("Goal" :nonlinearp t))))
  (local (defthmd step1
      (implies (and (natp a)
          (natp b)
          (posp n1)
          (posp n2)
          (< a (expt 2 n1))
          (< b (expt 2 n2)))
        (< (* a b)
          (* (expt 2 n1) (expt 2 n2))))
      :hints (("Goal" :use ((:instance lem-multiply-bound
            (a1 a)
            (a2 b)
            (b1 (expt 2 n1))
            (b2 (expt 2 n2))))))))
  (local (defthmd upper-bound
      (implies (and (natp a)
          (natp b)
          (posp n1)
          (posp n2)
          (< a (expt 2 n1))
          (< b (expt 2 n2)))
        (< (* a b)
          (expt 2 (+ n1 n2))))
      :rule-classes ((:rewrite) (:linear))
      :hints (("Goal" :use ((:instance step1))))))
  (defrule lousy-unsigned-byte-p-of-*-mixed
    (implies (and (unsigned-byte-p n1 a)
        (unsigned-byte-p n2 b))
      (unsigned-byte-p (+ n1 n2)
        (* a b)))
    :use ((:instance upper-bound))
    :short "Multiplying N1 * N2 bit unsigneds creates an N1+N2 bit unsigned."
    :long "<p>This is a powerful theorem with a nice statement, but it rarely
           unifies with anything.  See also @(see lousy-unsigned-byte-p-of-*)
           and also @(see basic-unsigned-byte-p-of-*).</p>")
  (defrule lousy-unsigned-byte-p-of-*
    (implies (and (unsigned-byte-p n a)
        (unsigned-byte-p n b))
      (unsigned-byte-p (+ n n)
        (* a b)))
    :short "Multiplying N * N bit unsigneds creates an N+N bit unsigned."
    :long "<p>This is a common case of @(see lousy-unsigned-byte-p-of-*-mixed),
           but it also rarely unifies with anything.  See also @(see
           basic-unsigned-byte-p-of-*).</p>")
  (local (defthm crock
      (equal (+ (/ n 2) (/ n 2))
        (fix n))))
  (defrule basic-unsigned-byte-p-of-*
    (implies (and (syntaxp (quotep n))
        (natp n)
        (unsigned-byte-p (/ n 2) a)
        (unsigned-byte-p (/ n 2) b))
      (unsigned-byte-p n (* a b)))
    :use ((:instance lousy-unsigned-byte-p-of-*
       (n (/ n 2))))
    :short "Multiplying constant N * N bit unsigneds creates an N+N bit unsigned."
    :long "<p>This is a less general but more automatic @(see
            lousy-unsigned-byte-p-of-*) for reasoning about constant widths.
            The use of division here looks awful, but note the @(see syntaxp)
            hyp.  This will let us get us things like:</p>

            @({ (unsigned-byte-p 32 (* a b)) })

            <p>When we know that @('(unsigned-byte-p 16 a)') and
            @('(unsigned-byte-p 16 b)').</p>"))
other
(defsection basic-signed-byte-p-of-*
  :autodoc nil
  (local (in-theory (enable signed-byte-p)))
  (local (defthmd lem-multiply-bound
      (implies (and (natp a1)
          (natp a2)
          (natp b1)
          (natp b2)
          (< a1 b1)
          (< a2 b2))
        (< (* a1 a2) (* b1 b2)))
      :hints (("Goal" :nonlinearp t))))
  (local (defthmd step1
      (implies (and (natp a)
          (natp b)
          (posp n)
          (< a (expt 2 (+ -1 n)))
          (< b (expt 2 (+ -1 n))))
        (< (* a b)
          (* (expt 2 (+ -1 n)) (expt 2 (+ -1 n)))))
      :hints (("Goal" :use ((:instance lem-multiply-bound
            (a1 a)
            (a2 b)
            (b1 (expt 2 (+ -1 n)))
            (b2 (expt 2 (+ -1 n)))))))))
  (local (defthmd step2
      (implies (natp n)
        (equal (* (expt 2 (+ -1 n)) (expt 2 (+ -1 n)))
          (expt 2 (+ -2 n n))))))
  (local (defthmd step3
      (implies (natp n)
        (< (expt 2 (+ -2 n n))
          (expt 2 (+ -1 n n))))))
  (local (defthmd pos-case-upper-bound
      (implies (and (natp a)
          (natp b)
          (posp n)
          (< a (expt 2 (+ -1 n)))
          (< b (expt 2 (+ -1 n))))
        (< (* a b)
          (expt 2 (+ -1 n n))))
      :rule-classes ((:rewrite) (:linear))
      :hints (("Goal" :use ((:instance step1) (:instance step2)
           (:instance step3))))))
  (local (defthmd pos-case-lower-bound
      (implies (and (natp a) (natp b))
        (natp (* a b)))
      :rule-classes ((:type-prescription) (:linear :corollary (implies (and (natp a) (natp b))
            (<= 0 (* a b)))))))
  (local (defthmd pos-case
      (implies (and (natp a)
          (natp b)
          (signed-byte-p n a)
          (signed-byte-p n b))
        (signed-byte-p (+ n n)
          (* a b)))
      :hints (("Goal" :in-theory (enable pos-case-upper-bound)))))
  (local (defthmd step1b
      (implies (and (natp a)
          (posp b)
          (posp n)
          (< a (expt 2 (+ -1 n)))
          (<= b (expt 2 (+ -1 n))))
        (< (* a b)
          (* (expt 2 (+ -1 n)) (expt 2 (+ -1 n)))))
      :hints (("Goal" :use ((:instance lem-multiply-bound
            (a1 a)
            (a2 b)
            (b1 (expt 2 (+ -1 n)))
            (b2 (expt 2 (+ -1 n)))))))))
  (local (defthmd mix-case-crux
      (implies (and (natp a)
          (posp b)
          (posp n)
          (< a (expt 2 (+ -1 n)))
          (<= b (expt 2 (+ -1 n))))
        (< (* a b)
          (expt 2 (+ -1 n n))))
      :rule-classes ((:rewrite) (:linear))
      :hints (("Goal" :in-theory (disable exponents-add)
         :nonlinearp t
         :use ((:instance step1b) (:instance step2)
           (:instance step3))))))
  (local (defthmd mix-case-unwinding
      (implies (and (natp a)
          (integerp b)
          (< b 0)
          (posp n)
          (< a (expt 2 (+ -1 n)))
          (<= (- (expt 2 (+ -1 n))) b))
        (< (- (expt 2 (+ -1 n n)))
          (* a b)))
      :hints (("Goal" :use ((:instance mix-case-crux (b (- b))))))))
  (local (defthmd mix-case
      (implies (and (natp a)
          (integerp b)
          (< b 0)
          (signed-byte-p n a)
          (signed-byte-p n b))
        (signed-byte-p (+ n n)
          (* a b)))
      :hints (("Goal" :use ((:instance mix-case-unwinding))))))
  (local (defthmd step1c
      (implies (and (posp a)
          (posp b)
          (posp n)
          (<= a (expt 2 (+ -1 n)))
          (<= b (expt 2 (+ -1 n))))
        (<= (* a b)
          (* (expt 2 (+ -1 n)) (expt 2 (+ -1 n)))))))
  (local (defthmd neg-case-crux
      (implies (and (posp a)
          (posp b)
          (posp n)
          (<= a (expt 2 (+ -1 n)))
          (<= b (expt 2 (+ -1 n))))
        (<= (* a b)
          (expt 2 (+ -2 n n))))
      :rule-classes ((:rewrite) (:linear))
      :hints (("Goal" :in-theory (disable exponents-add)
         :nonlinearp t
         :use ((:instance step1c) (:instance step2)
           (:instance step3))))))
  (local (defthmd neg-case-finish
      (implies (natp n)
        (< (expt 2 (+ -2 n n))
          (expt 2 (+ -1 n n))))))
  (local (defthmd neg-case-unwinding
      (implies (and (integerp a)
          (< a 0)
          (integerp b)
          (< b 0)
          (posp n)
          (<= (- (expt 2 (+ -1 n))) a)
          (<= (- (expt 2 (+ -1 n))) b))
        (< (* a b)
          (expt 2 (+ -1 n n))))
      :rule-classes ((:rewrite) (:linear))
      :hints (("Goal" :use ((:instance neg-case-crux
            (a (- a))
            (b (- b))) (:instance neg-case-finish))))))
  (local (defthmd neg-case-lower-bound
      (implies (and (integerp a)
          (< a 0)
          (integerp b)
          (< b 0))
        (natp (* a b)))
      :rule-classes ((:type-prescription) (:linear :corollary (implies (and (< a 0)
              (< b 0)
              (integerp a)
              (integerp b))
            (<= 0 (* a b)))))
      :hints (("Goal" :nonlinearp t))))
  (local (defthmd neg-case
      (implies (and (integerp a)
          (< a 0)
          (integerp b)
          (< b 0)
          (signed-byte-p n a)
          (signed-byte-p n b))
        (signed-byte-p (+ n n)
          (* a b)))
      :hints (("Goal" :use ((:instance neg-case-unwinding))))))
  (defrule lousy-signed-byte-p-of-*
    (implies (and (signed-byte-p n a)
        (signed-byte-p n b))
      (signed-byte-p (+ n n)
        (* a b)))
    :in-theory (disable signed-byte-p)
    :use ((:instance pos-case) (:instance mix-case)
      (:instance mix-case
        (a b)
        (b a))
      (:instance neg-case))
    :short "Multiplying N * N bit signeds creates an N+N bit signed."
    :long "<p>This is a powerful rule with a nice statement, but it rarely
            unifies with anything automatically.  See also @(see
            basic-signed-byte-p-of-*) and also see @(see
            lousy-signed-byte-p-of-mixed-*).</p>")
  (local (defthm crock
      (equal (+ (/ n 2) (/ n 2))
        (fix n))))
  (defrule basic-signed-byte-p-of-*
    (implies (and (syntaxp (quotep n))
        (natp n)
        (signed-byte-p (/ n 2) a)
        (signed-byte-p (/ n 2) b))
      (signed-byte-p n (* a b)))
    :use ((:instance lousy-signed-byte-p-of-*
       (n (/ n 2))))
    :short "Multiplying constant N * N bit signeds creates an N+N bit signed."
    :long "<p>This is a less general but more automatic version of @(see
           lousy-signed-byte-p-of-*).  It's good for constant widths.</p>

           <p>The use of division here looks awful, but note the @(see syntaxp)
           hyp: we'll only do these divisions when we know @('n') is a
           constant, e.g., this will let us know that 16-bit multiplication
           gives us a 32-bit result.</p>

           <p>See also @(see basic-signed-byte-p-of-mixed-*).</p>")
  (local (defthmd su-pos-step1
      (implies (and (natp a)
          (natp b)
          (posp n)
          (< a (expt 2 (+ -1 n)))
          (< b (expt 2 n)))
        (< (* a b)
          (* (expt 2 (+ -1 n)) (expt 2 n))))
      :hints (("Goal" :use ((:instance lem-multiply-bound
            (a1 a)
            (a2 b)
            (b1 (expt 2 (+ -1 n)))
            (b2 (expt 2 n))))))))
  (local (defthmd gather-exponents
      (implies (and (integerp a)
          (natp n)
          (natp m))
        (equal (* (expt a n) (expt a m))
          (expt a (+ n m))))))
  (local (defthmd su-step2
      (implies (posp n)
        (equal (* (expt 2 (+ -1 n)) (expt 2 n))
          (expt 2 (+ -1 n n))))
      :hints (("Goal" :use ((:instance gather-exponents
            (a 2)
            (n (+ -1 n))
            (m n)))))))
  (local (defthmd su-pos-upper-bound
      (implies (and (natp a)
          (natp b)
          (posp n)
          (< a (expt 2 (+ -1 n)))
          (< b (expt 2 n)))
        (< (* a b)
          (expt 2 (+ -1 n n))))
      :rule-classes ((:rewrite) (:linear))
      :hints (("Goal" :use ((:instance su-pos-step1) (:instance su-step2))))))
  (local (defthmd su-pos-case
      (implies (and (natp a)
          (signed-byte-p n a)
          (unsigned-byte-p n b))
        (signed-byte-p (+ n n)
          (* a b)))
      :hints (("Goal" :in-theory (enable su-pos-upper-bound)))))
  (local (defthmd lem-multiply-bound-2
      (implies (and (posp a1)
          (natp a2)
          (natp b1)
          (natp b2)
          (<= a1 b1)
          (< a2 b2))
        (< (* a1 a2) (* b1 b2)))
      :hints (("Goal" :nonlinearp t))))
  (local (defthmd su-neg-step1
      (implies (and (posp a)
          (natp b)
          (posp n)
          (<= a (expt 2 (+ -1 n)))
          (< b (expt 2 n)))
        (< (* a b)
          (* (expt 2 (+ -1 n)) (expt 2 n))))
      :hints (("Goal" :use ((:instance lem-multiply-bound-2
            (a1 a)
            (a2 b)
            (b1 (expt 2 (+ -1 n)))
            (b2 (expt 2 n))))))))
  (local (defthmd su-neg-crux
      (implies (and (integerp a)
          (< a 0)
          (natp b)
          (posp n)
          (<= (- (expt 2 (+ -1 n))) a)
          (< b (expt 2 n)))
        (<= (- (expt 2 (+ -1 n n)))
          (* a b)))
      :rule-classes ((:rewrite) (:linear))
      :hints (("Goal" :use ((:instance su-neg-step1 (a (- a))) (:instance su-step2))))))
  (local (defthmd su-neg-case
      (implies (and (integerp a)
          (< a 0)
          (signed-byte-p n a)
          (unsigned-byte-p n b))
        (signed-byte-p (+ n n)
          (* a b)))
      :hints (("Goal" :use ((:instance su-neg-crux))))))
  (defrule lousy-signed-byte-p-of-mixed-*
    (implies (and (signed-byte-p n a)
        (unsigned-byte-p n b))
      (signed-byte-p (+ n n)
        (* a b)))
    :in-theory (disable unsigned-byte-p
      signed-byte-p)
    :use ((:instance su-neg-case) (:instance su-pos-case))
    :short "Multiplying N-bit signed * N-bit unsigned creates an N+N bit signed."
    :long "<p>This is a nice and general theorem but it rarely unifies
           automatically.  See also @(see basic-signed-byte-p-of-mixed-*).
           Also see @(see lousy-signed-byte-p-of-*).</p>")
  (defrule basic-signed-byte-p-of-mixed-*
    (implies (and (syntaxp (quotep n))
        (natp n)
        (or (and (signed-byte-p (/ n 2) a)
            (unsigned-byte-p (/ n 2) b))
          (and (unsigned-byte-p (/ n 2) a)
            (signed-byte-p (/ n 2) b))))
      (signed-byte-p n (* a b)))
    :in-theory (disable signed-byte-p
      unsigned-byte-p
      lousy-signed-byte-p-of-mixed-*)
    :use ((:instance lousy-signed-byte-p-of-mixed-*
       (n (/ n 2))) (:instance lousy-signed-byte-p-of-mixed-*
        (n (/ n 2))
        (a b)
        (b a)))
    :short "Multiplying constant N-bit signed * N-bit unsigned creates an N+N bit signed."
    :long "<p>This is a more automatic @(see lousy-signed-byte-p-of-mixed-*)
           for reasoning about constant widths.  The use of division here looks
           awful, but note the @(see syntaxp) hyp.</p>"))
other
(local (include-book "ihsext-basics"))
other
(local (defthm logcdr-when-non-integer
    (implies (not (integerp x))
      (equal (logcdr x) 0))
    :hints (("Goal" :in-theory (enable logcdr)))))
other
(local (defthm logtail-when-non-integer
    (implies (not (integerp x))
      (equal (logtail n x) 0))
    :hints (("Goal" :in-theory (enable logtail**)))))
other
(defrule basic-signed-byte-p-of-lognot
  (implies (unsigned-byte-p n x)
    (signed-byte-p (+ 1 n) (lognot x)))
  :enable (lognot unsigned-byte-p signed-byte-p)
  :short "Lognot of an N-bit unsigned is an N+1 bit signed.")
other
(defrule basic-signed-byte-p-of-1+lognot
  (implies (unsigned-byte-p n x)
    (signed-byte-p (+ 1 n)
      (+ 1 (lognot x))))
  :enable (lognot unsigned-byte-p signed-byte-p)
  :short "Lognot+1 (two's complement) of an N-bit unsigned is an N+1 bit signed.")
other
(defrule signed-byte-p-when-signed-byte-p-smaller
  (implies (and (signed-byte-p size1 x)
      (<= size1 (nfix size2)))
    (signed-byte-p size2 x))
  :enable signed-byte-p
  :short "An N-bit signed is an M-bit signed for any @('M >= N').")
other
(encapsulate nil
  (local (defun my-induct
      (size1 size2 x)
      (if (or (zp size1) (zp size2))
        (list size1 size2 x)
        (my-induct (- size1 1)
          (- size2 1)
          (logcdr x)))))
  (defrule signed-byte-p-when-unsigned-byte-p-smaller
    (implies (and (unsigned-byte-p size1 x)
        (< size1 (nfix size2)))
      (signed-byte-p size2 x))
    :induct (my-induct size1 size2 x)
    :enable (ihsext-recursive-redefs ihsext-inductions)
    :short "An N-bit unsigned is an M-big signed for any @('M < N')."))
other
(defsection signed-byte-p-of-loghead
  :short "An N-bit loghead is an M-bit signed for any @('M > N')."
  (local (defthm l0
      (implies (and (natp n)
          (natp size)
          (< size n))
        (signed-byte-p n
          (loghead size x)))
      :hints (("Goal" :do-not-induct t
         :in-theory (disable unsigned-byte-p-of-loghead
           signed-byte-p-when-unsigned-byte-p-smaller)
         :use ((:instance unsigned-byte-p-of-loghead
            (i x)
            (size size)
            (size1 size)) (:instance signed-byte-p-when-unsigned-byte-p-smaller
             (x (loghead size x))
             (size1 size)
             (size2 n)))))))
  (defthm signed-byte-p-of-loghead
    (implies (and (integerp m)
        (< (nfix size) m))
      (signed-byte-p m
        (loghead size x)))))
other
(local (encapsulate nil
    (local (include-book "ihs/quotient-remainder-lemmas" :dir :system))
    (local (in-theory (disable (force))))
    (defthmd truncate-is-floor-when-naturals
      (implies (and (natp a) (natp b))
        (equal (truncate a b)
          (floor a b)))
      :hints (("Goal" :in-theory (enable truncate floor))))
    (defthmd rem-is-mod-when-naturals
      (implies (and (natp a) (natp b))
        (equal (rem a b) (mod a b)))
      :hints (("Goal" :in-theory (enable rem
           mod
           truncate-is-floor-when-naturals))))
    (defthm floor-of-zero
      (equal (floor a 0) 0)
      :hints (("Goal" :in-theory (enable floor))))
    (defthm truncate-of-zero
      (equal (truncate a 0) 0)
      :hints (("Goal" :in-theory (enable truncate))))
    (defthm mod-of-zero
      (equal (mod a 0) (fix a))
      :hints (("Goal" :in-theory (enable mod))))
    (defthm rem-of-zero
      (equal (rem a 0) (fix a))
      :hints (("Goal" :in-theory (enable rem))))
    (defthm integerp-of-rem
      (implies (and (integerp a) (integerp b))
        (integerp (rem a b)))
      :hints (("Goal" :in-theory (enable rem))))
    (defthm floor-lower-bound-when-naturals
      (implies (and (natp a) (natp b))
        (<= 0 (floor a b)))
      :rule-classes ((:rewrite) (:linear)
        (:type-prescription :corollary (implies (and (natp a) (natp b))
            (natp (floor a b)))))
      :hints (("Goal" :in-theory (enable floor))))
    (defthm truncate-lower-bound-when-naturals
      (implies (and (natp a) (natp b))
        (<= 0 (truncate a b)))
      :rule-classes ((:rewrite) (:linear)
        (:type-prescription :corollary (implies (and (natp a) (natp b))
            (natp (truncate a b)))))
      :hints (("Goal" :in-theory (enable truncate-is-floor-when-naturals))))
    (defthm mod-lower-bound-when-naturals
      (implies (and (natp a) (natp b))
        (<= 0 (mod a b)))
      :rule-classes ((:rewrite) (:linear)
        (:type-prescription :corollary (implies (and (natp a) (natp b))
            (natp (mod a b))))))
    (defthm rem-lower-bound-when-naturals
      (implies (and (natp a) (natp b))
        (<= 0 (rem a b)))
      :rule-classes ((:rewrite) (:linear)
        (:type-prescription :corollary (implies (and (natp a) (natp b))
            (natp (rem a b)))))
      :hints (("Goal" :in-theory (enable rem-is-mod-when-naturals))))
    (defthm floor-of-1-when-integerp
      (implies (integerp a)
        (equal (floor a 1) a))
      :hints (("Goal" :in-theory (enable floor))))
    (defthm truncate-of-negative-1
      (implies (integerp a)
        (equal (truncate a -1) (- a)))
      :hints (("Goal" :in-theory (enable truncate))))
    (defthmd floor-strong-self-upper-bound-when-naturals
      (implies (and (natp a) (natp b))
        (equal (< (floor a b) a)
          (if (posp a)
            (not (equal b 1))
            nil)))
      :hints (("Goal" :nonlinearp t)))
    (defthmd truncate-strong-self-upper-bound-when-naturals
      (implies (and (natp a) (natp b))
        (equal (< (truncate a b) a)
          (if (posp a)
            (not (equal b 1))
            nil)))
      :hints (("Goal" :in-theory (enable truncate-is-floor-when-naturals
           floor-strong-self-upper-bound-when-naturals))))
    (defthm floor-weak-self-upper-bound-when-naturals
      (implies (and (natp a) (natp b))
        (<= (floor a b) a))
      :hints (("Goal" :cases ((< (floor a b) a))
         :in-theory (e/d (floor-strong-self-upper-bound-when-naturals)
           (floor)))))
    (defthm truncate-weak-self-upper-bound-when-naturals
      (implies (and (natp a) (natp b))
        (<= (truncate a b) a))
      :rule-classes ((:rewrite) (:linear))
      :hints (("Goal" :in-theory (enable truncate-is-floor-when-naturals))))
    (defthm mod-weak-left-upper-bound-when-naturals
      (implies (and (natp a) (posp b))
        (<= (mod a b) a))
      :rule-classes :linear)
    (defthm rem-weak-left-upper-bound-when-naturals
      (implies (and (natp a) (posp b))
        (<= (rem a b) a))
      :rule-classes :linear :hints (("Goal" :in-theory (enable rem-is-mod-when-naturals))))
    (defthm mod-strong-right-upper-bound-when-naturals
      (implies (and (natp a) (natp b))
        (equal (< (mod a b) b)
          (not (zp b))))
      :rule-classes ((:rewrite) (:linear :corollary (implies (and (natp a) (posp b))
            (< (mod a b) b)))))
    (defthm rem-strong-right-upper-bound-when-naturals
      (implies (and (natp a) (natp b))
        (equal (< (rem a b) b)
          (not (zp b))))
      :rule-classes ((:rewrite) (:linear :corollary (implies (and (natp a) (posp b))
            (< (rem a b) b))))
      :hints (("Goal" :in-theory (enable rem-is-mod-when-naturals))))
    (defthm mod-weak-global-upper-bound-when-naturals
      (implies (and (natp a) (natp b))
        (<= (mod a b) (max a b)))
      :rule-classes :linear :hints (("Goal" :use ((:instance mod-weak-left-upper-bound-when-naturals) (:instance mod-strong-right-upper-bound-when-naturals)))))
    (defthm rem-weak-global-upper-bound-when-naturals
      (implies (and (natp a) (natp b))
        (<= (rem a b) (max a b)))
      :rule-classes :linear :hints (("Goal" :in-theory (enable rem-is-mod-when-naturals))))))
other
(defrule basic-unsigned-byte-p-of-floor
  (implies (and (unsigned-byte-p n a)
      (natp b))
    (unsigned-byte-p n
      (floor a b)))
  :enable (unsigned-byte-p)
  :disable (floor-weak-self-upper-bound-when-naturals)
  :use ((:instance floor-weak-self-upper-bound-when-naturals))
  :short "Floor an N-bit unsigned by a natural creates an N-bit unsigned.")
other
(defrule basic-unsigned-byte-p-of-truncate
  (implies (and (unsigned-byte-p n a)
      (natp b))
    (unsigned-byte-p n
      (truncate a b)))
  :enable (truncate-is-floor-when-naturals)
  :disable (floor truncate unsigned-byte-p)
  :short "Truncate an N-bit unsigned by a natural creates an N-bit unsigned.")
other
(defrule basic-unsigned-byte-p-of-mod
  (implies (and (unsigned-byte-p n a)
      (natp b))
    (unsigned-byte-p n
      (mod a b)))
  :do-not-induct t
  :use ((:instance mod-weak-left-upper-bound-when-naturals))
  :enable (unsigned-byte-p)
  :disable (mod-weak-left-upper-bound-when-naturals mod-weak-global-upper-bound-when-naturals)
  :short "Mod an N-bit unsigned by a natural creates an N-bit unsigned.")
other
(defrule basic-unsigned-byte-p-of-rem
  (implies (and (unsigned-byte-p n a)
      (natp b))
    (unsigned-byte-p n
      (rem a b)))
  :enable (rem-is-mod-when-naturals)
  :disable (rem mod unsigned-byte-p)
  :short "Remainder of an N-bit unsigned by a natural creates an N-bit unsigned.")
other
(defsection basic-signed-byte-p-of-truncate
  :autodoc nil
  (local (in-theory (enable signed-byte-p)))
  (local (defthm |(< (- a) (- b))|
      (implies (and (rationalp a) (rationalp b))
        (equal (< (- a) (- b))
          (< b a)))
      :hints (("Goal" :use ((:instance <-*-right-cancel
            (x a)
            (y b)
            (z -1)))))))
  (local (defthm basic-signed-byte-p-of-floor-when-naturals
      (implies (and (signed-byte-p n a)
          (case-split (natp a))
          (case-split (natp b)))
        (signed-byte-p n
          (floor a b)))
      :hints (("Goal" :in-theory (disable basic-unsigned-byte-p-of-floor)
         :use ((:instance basic-unsigned-byte-p-of-floor
            (n (- n 1))))))))
  (local (defthm basic-signed-byte-p-of-truncate-when-naturals
      (implies (and (signed-byte-p n a)
          (case-split (natp a))
          (case-split (natp b)))
        (signed-byte-p n
          (truncate a b)))
      :hints (("Goal" :use ((:instance truncate-is-floor-when-naturals) (:instance basic-signed-byte-p-of-floor-when-naturals))))))
  (local (encapsulate nil
      (local (defthm truncate-when-positive-over-negative
          (implies (and (natp a) (negp b))
            (equal (truncate a b)
              (- (truncate a (- b)))))
          :hints (("Goal" :in-theory (enable truncate)))))
      (defthm basic-signed-byte-p-of-truncate-when-positive-over-negative
        (implies (and (signed-byte-p n a)
            (case-split (natp a))
            (case-split (negp b)))
          (signed-byte-p n
            (truncate a b))))
      (local (defthm floor-when-positive-over-negative
          (implies (and (natp a) (negp b))
            (equal (floor a b)
              (if (integerp (/ a b))
                (- (floor a (- b)))
                (+ -1 (- (floor a (- b)))))))
          :hints (("Goal" :in-theory (enable floor)))))
      (defthm basic-signed-byte-p-of-floor-when-positive-over-negative
        (implies (and (signed-byte-p n a)
            (case-split (natp a))
            (case-split (negp b)))
          (signed-byte-p n
            (floor a b)))
        :hints (("Goal" :do-not-induct t
           :use ((:instance basic-signed-byte-p-of-floor-when-naturals
              (a a)
              (b (- b))
              (n n)))
           :in-theory (disable basic-signed-byte-p-of-floor-when-naturals))))))
  (local (encapsulate nil
      (local (defthm truncate-when-negative-over-positive
          (implies (and (negp a) (natp b))
            (equal (truncate a b)
              (- (truncate (- a) b))))
          :hints (("Goal" :in-theory (enable truncate)))))
      (defthm basic-signed-byte-p-of-truncate-when-negative-over-positive
        (implies (and (signed-byte-p n a)
            (case-split (negp a))
            (case-split (posp b)))
          (signed-byte-p n
            (truncate a b))))
      (local (defthm floor-when-negative-over-positive
          (implies (and (negp a) (natp b))
            (equal (floor a b)
              (if (integerp (/ a b))
                (- (floor (- a) b))
                (+ -1 (- (floor (- a) b))))))
          :hints (("Goal" :in-theory (enable floor)))))
      (defthm basic-signed-byte-p-of-floor-when-negative-over-positive
        (implies (and (signed-byte-p n a)
            (case-split (negp a))
            (case-split (posp b)))
          (signed-byte-p n
            (floor a b)))
        :hints (("Goal" :use ((:instance basic-signed-byte-p-of-floor-when-naturals
              (a (- a))
              (b b)
              (n n)) (:instance floor-strong-self-upper-bound-when-naturals
               (a (expt 2 (+ -1 n)))
               (b b)))
           :in-theory (disable basic-signed-byte-p-of-floor-when-naturals
             floor-strong-self-upper-bound-when-naturals))))))
  (local (encapsulate nil
      (local (defthm truncate-when-both-negative
          (implies (and (negp a) (negp b))
            (equal (truncate a b)
              (truncate (- a) (- b))))
          :hints (("Goal" :in-theory (enable truncate)))))
      (local (defthmd basic-signed-byte-p-of-truncate-when-negatives-except-for-int-min
          (implies (and (signed-byte-p n a)
              (negp a)
              (negp b)
              (not (equal a (- (expt 2 (- n 1))))))
            (signed-byte-p n
              (truncate a b)))))
      (local (defthmd basic-signed-byte-p-of-truncate-int-min
          (implies (and (signed-byte-p n a)
              (equal a (- (expt 2 (- n 1))))
              (negp b)
              (not (equal b -1)))
            (signed-byte-p n
              (truncate a b)))
          :hints (("Goal" :in-theory (enable truncate-strong-self-upper-bound-when-naturals)))))
      (defthm basic-signed-byte-p-of-truncate-when-negatives
        (implies (and (signed-byte-p n a)
            (case-split (negp a))
            (case-split (negp b)))
          (equal (signed-byte-p n
              (truncate a b))
            (not (and (equal a (- (expt 2 (- n 1))))
                (equal b -1)))))
        :hints (("Goal" :do-not-induct t
           :use ((:instance basic-signed-byte-p-of-truncate-when-negatives-except-for-int-min) (:instance basic-signed-byte-p-of-truncate-int-min))
           :in-theory (enable truncate-strong-self-upper-bound-when-naturals))))
      (local (defthm floor-when-both-negative
          (implies (and (negp a) (negp b))
            (equal (floor a b)
              (floor (- a) (- b))))
          :hints (("Goal" :in-theory (enable floor)))))
      (local (defthmd basic-signed-byte-p-of-floor-when-negatives-except-for-int-min
          (implies (and (signed-byte-p n a)
              (negp a)
              (negp b)
              (not (equal a (- (expt 2 (- n 1))))))
            (signed-byte-p n
              (floor a b)))
          :hints (("Goal" :use ((:instance basic-signed-byte-p-of-floor-when-naturals
                (a (- a))
                (b (- b))))))))
      (local (defthmd basic-signed-byte-p-of-floor-int-min
          (implies (and (signed-byte-p n a)
              (equal a (- (expt 2 (- n 1))))
              (negp b)
              (not (equal b -1)))
            (signed-byte-p n
              (floor a b)))
          :hints (("Goal" :in-theory (enable floor-strong-self-upper-bound-when-naturals)))))
      (defthm basic-signed-byte-p-of-floor-when-negatives
        (implies (and (signed-byte-p n a)
            (case-split (negp a))
            (case-split (negp b)))
          (equal (signed-byte-p n
              (floor a b))
            (not (and (equal a (- (expt 2 (- n 1))))
                (equal b -1)))))
        :hints (("Goal" :do-not-induct t
           :use ((:instance basic-signed-byte-p-of-floor-when-negatives-except-for-int-min) (:instance basic-signed-byte-p-of-floor-int-min))
           :in-theory (enable floor-strong-self-upper-bound-when-naturals))))))
  (defruled basic-signed-byte-p-of-truncate-split
    (implies (and (signed-byte-p n a)
        (integerp b))
      (equal (signed-byte-p n
          (truncate a b))
        (not (and (equal a (- (expt 2 (- n 1))))
            (equal b -1)))))
    :hints (("Goal" :in-theory (disable signed-byte-p)
       :do-not '(generalize fertilize
         eliminate-destructors)
       :do-not-induct t) (and stable-under-simplificationp
        '(:in-theory (enable signed-byte-p))))
    :short "Truncate of an N-bit signed by an integer is <b>usually</b> an
            N-bit signed.  (Strong form, case splitting, disabled by default)."
    :long "<p>See also @(see basic-signed-byte-p-of-truncate), which we leave
           enabled.</p>")
  (defrule basic-signed-byte-p-of-truncate
    (implies (and (signed-byte-p n a)
        (integerp b)
        (not (and (equal a (- (expt 2 (- n 1))))
            (equal b -1))))
      (signed-byte-p n
        (truncate a b)))
    :enable basic-signed-byte-p-of-truncate-split
    :short "Truncating an N-bit signed by an integer is <b>usually</b> an N-bit
            signed.  (Weak form, enabled by default)."
    :long "<p>See also @(see basic-signed-byte-p-of-truncate-split).</p>")
  (defrule basic-signed-byte-p-of-floor-split
    (implies (and (signed-byte-p n a)
        (integerp b))
      (equal (signed-byte-p n
          (floor a b))
        (not (and (equal a (- (expt 2 (- n 1))))
            (equal b -1)))))
    :hints (("Goal" :in-theory (disable signed-byte-p)
       :do-not '(generalize fertilize
         eliminate-destructors)
       :do-not-induct t) (and stable-under-simplificationp
        '(:in-theory (enable signed-byte-p))))
    :short "Floor of an N-bit signed by an integer is <b>usually</b> an N-bit
            signed.  (Strong form, case splitting, disabled by default)."
    :long "<p>See also @(see basic-signed-byte-p-of-floor).</p>")
  (defrule basic-signed-byte-p-of-floor
    (implies (and (signed-byte-p n a)
        (integerp b)
        (not (and (equal a (- (expt 2 (- n 1))))
            (equal b -1))))
      (signed-byte-p n
        (floor a b)))
    :enable basic-signed-byte-p-of-floor-split
    :short "Floor of an N-bit signed by an integer is <b>usually</b> an N-bit
            signed.  (Weak form, enabled by default)."
    :long "<p>See also @(see basic-signed-byte-p-of-floor-split).</p>"))
other
(defsection basic-signed-byte-p-of-mod
  :autodoc nil
  (local (include-book "ihs/quotient-remainder-lemmas" :dir :system))
  (local (in-theory (enable signed-byte-p)))
  (local (defthm basic-signed-byte-p-of-mod-when-negp-b
      (implies (and (integerp a)
          (signed-byte-p n b)
          (case-split (negp b)))
        (signed-byte-p n (mod a b)))
      :hints (("Goal" :do-not-induct t
         :do-not '(generalize fertilize
           eliminate-destructors)
         :in-theory (e/d nil (mod floor))))))
  (local (defthm basic-signed-byte-p-of-mod-when-posp-b
      (implies (and (integerp a)
          (signed-byte-p n b)
          (case-split (posp b)))
        (signed-byte-p n (mod a b)))
      :hints (("Goal" :do-not-induct t
         :do-not '(generalize fertilize
           eliminate-destructors)
         :in-theory (e/d nil (mod floor))))))
  (defrule basic-signed-byte-p-of-mod
    (implies (and (signed-byte-p n a)
        (signed-byte-p n b))
      (signed-byte-p n (mod a b)))
    :short "Mod of N-bit signed by N-bit signed creates an N-bit signed.")
  (local (defthm basic-signed-byte-p-of-rem-when-negp-b
      (implies (and (integerp a)
          (signed-byte-p n b)
          (case-split (negp b)))
        (signed-byte-p n (rem a b)))
      :hints (("Goal" :do-not-induct t
         :do-not '(generalize fertilize
           eliminate-destructors)
         :in-theory (e/d nil (rem truncate))))))
  (local (defthm basic-signed-byte-p-of-rem-when-posp-b
      (implies (and (integerp a)
          (signed-byte-p n b)
          (case-split (posp b)))
        (signed-byte-p n (rem a b)))
      :hints (("Goal" :do-not-induct t
         :do-not '(generalize fertilize
           eliminate-destructors)
         :in-theory (e/d nil (rem truncate))))))
  (defrule basic-signed-byte-p-of-rem
    (implies (and (signed-byte-p n a)
        (signed-byte-p n b))
      (signed-byte-p n (rem a b)))
    :short "Rem of N-bit signed by N-bit signed creates an N-bit signed."))