(unsigned-bit-shift-right x n)
Bitwise shift right, without sign-extension.
user=> (format "%016x" -1)
"ffffffffffffffff"
;; bit-shift-right sign extends most significant bit while right shifting.
user=> (format "%016x" (bit-shift-right -1 10))
"ffffffffffffffff"
;; unsigned-bit-shift-right fills most significant bits of result with 0.
;; No sign extension.
user=> (format "%016x" (unsigned-bit-shift-right -1 10))
"003fffffffffffff"
;; Warning: unsigned-bit-shift-right, like bit-shift-right, treats inputs as
;; type Long. Smaller types like byte, short, and int will not behave as such.
(format "0x%x" (byte -128))
; => "0x80"
(format "0x%x" (unsigned-bit-shift-right (byte -128) 1))
; => "0x7fffffffffffffc0"
(format "0x%x" (bit-shift-right (byte -128) 1))
; => "0xffffffffffffffc0"
; If you expected 0x40, you need to upcast your byte yourself, via bit-and,
; and only then shift:
(format "0x%x" (bit-shift-right (bit-and 0xff (byte -128)) 1))
; => "0x40"
;; Stein's Algorithm (Binary GCD)
;; https://en.wikipedia.org/wiki/Binary_GCD_algorithm
(defn gcd [a b]
(cond
(zero? a) b
(zero? b) a
(neg? a) (- a)
(neg? b) (- b)
(and (even? a) (even? b)) (* 2
(gcd (unsigned-bit-shift-right a 1)
(unsigned-bit-shift-right b 1)))
(and (even? a) (odd? b)) (recur (unsigned-bit-shift-right a 1) b)
(and (odd? a) (even? b)) (recur a (unsigned-bit-shift-right b 1))
(and (odd? a) (odd? b)) (recur (unsigned-bit-shift-right
(Math/abs (long (- a b))) ;; coerce to avoid reflection
1) (min a b))))