Filtering...

bignum-extract

books/std/bitsets/bignum-extract
other
(in-package "BITSETS")
other
(include-book "std/util/define" :dir :system)
other
(local (include-book "ihs/logops-lemmas" :dir :system))
other
(local (in-theory (disable logand loghead unsigned-byte-p)))
other
(define bignum-extract
  :parents (ttag-bitset-members)
  :short "Extract a particular 32-bit slice of an integer."
  ((x integerp "Integer to extract from") (slice natp
      "Which 32 bit slice to extract"))
  :returns (extracted natp
    :rule-classes :type-prescription)
  :long "<p>Logically, @(call bignum-extract) is essentially:</p>

@({
   (logand (ash x (* -32 slice)) (1- (expt 2 32)))
})

<p>What does this do?  Imagine partitioning the integer @('x') into a list of
32-bit slices.  Say that the least-significant 32 bits are the 0th slice, and
so on.  The @('bignum-extract') function is just extracting the @('slice')th
slice of @('x').</p>

<p>The logical definition of @('bignum-extract') is not very efficient; when
@('x') is a bignum, the @('(ash x (* -32 slice))') term will generally require
us to create a new bignum.</p>

<p>You may <b>optionally, with a trust tag</b> load an raw Lisp replacement
which, on 64-bit CCL that takes advantage of the underlying representation of
bignums, and on other Lisps implements this function using <b>ldb</b>, which
may have or may not be more optimal.</p>"
  :verify-guards nil
  (mbe :logic (let ((x (ifix x)) (slice (nfix slice)))
      (logand (1- (expt 2 32))
        (ash x (* -32 slice))))
    :exec (the (unsigned-byte 32)
      (logand (the (unsigned-byte 32) (1- (expt 2 32)))
        (ash x (* -32 slice)))))
  ///
  (defthm unsigned-byte-p-of-bignum-extract
    (unsigned-byte-p 32
      (bignum-extract x slice)))
  (make-event `(defthm upper-bound-of-bignum-extract
      (< (bignum-extract x slice)
        ,(EXPT 2 32))
      :rule-classes :linear :hints (("Goal" :use ((:instance unsigned-byte-p-of-bignum-extract))))))
  (verify-guards bignum-extract))