clojure - Right-shifting 32-bit ints -


clojure's bit-shift operations seem return 64-bit long results, 32-bit int arguments. not substantial problem bit-shift-left:

user=> (format "%08x" (unchecked-int (bit-shift-left (unchecked-int 0x12345678) 4))) "23456780" user=> (format "%08x" (unchecked-int (bit-shift-left (unchecked-int 0xf2345678) 4))) "23456780" 

however, becomes problem unsigned right-shifting of negative numbers:

user=> (format "%08x" (unchecked-int (unsigned-bit-shift-right (unchecked-int 0xf2345678) 4))) "ff234567" 

the correct answer, of course, 0f234567.

what efficient way implement 32-bit unsigned right-shifting in clojure?

this can accomplished calling int clojure.lang.numbers.unsignedshiftrightint(int, int) method uses >>> on int arguments, returning int. it's not exposed function anywhere, have intrinsic implementation (equivalent >>> in java) , can either call directly or wrap in own inlinable function:

(defn unsigned-bit-shift-right-int   {:inline (fn [x n] `(clojure.lang.numbers/unsignedshiftrightint ~x ~n))}   [x n]   (clojure.lang.numbers/unsignedshiftrightint x n)) 

this returns correct value whether gets inlined or not, of course you'd want inlined. it's make sure arguments primitive ints intrinsic can kick in.

here's compiles in clojure 1.8 in 2 possible cases inlined (the non-inlined case regular function call, nothing see there):

inlined primitive arguments:

abusing count little bit illustrate point. note iushr instruction.

  1. clojure deftype:

    (deftype foo [^int x ^int y]   clojure.lang.counted   (count [this]     (unsigned-bit-shift-right-int x y))) 
  2. bytecode:

    // method descriptor #61 ()i // stack: 2, locals: 1 public int count();    0  aload_0 [this]    1  getfield user.foo.x : int [19]    4  aload_0 [this]    5  getfield user.foo.y : int [21]    8  iushr    9  ireturn     line numbers:       [pc: 0, line: 1]       [pc: 8, line: 4]     local variable table:       [pc: 0, pc: 9] local: index: 0 type: user.foo 

inlined non-primitive arguments:

note invokestatic clojure.lang.numbers.unsignedshiftright… instruction.

  1. clojure expression:

    #(format "%08x"    (clojure.lang.numbers/unsignedshiftrightint (unchecked-int 0xf2345678) 4)) 
  2. bytecode:

    // method descriptor #11 ()ljava/lang/object; // stack: 5, locals: 1 public java.lang.object invoke();    0  getstatic user$eval16141$fn__16142.const__0 : clojure.lang.var [15]    3  invokevirtual clojure.lang.var.getrawroot() : java.lang.object [20]    6  checkcast clojure.lang.ifn [22]    9  ldc <string "%08x"> [24]   11  ldc2_w <long 4063516280> [25]   14  l2i   15  ldc2_w <long 4> [27]   18  invokestatic clojure.lang.rt.intcast(long) : int [34]   21  invokestatic clojure.lang.numbers.unsignedshiftrightint(int, int) : int [40]   24  invokestatic java.lang.integer.valueof(int) : java.lang.integer [46]   27  invokeinterface clojure.lang.ifn.invoke(java.lang.object, java.lang.object) : java.lang.object [49] [nargs: 3]   32  areturn     line numbers:       [pc: 0, line: 1]       [pc: 6, line: 1]       [pc: 14, line: 1]       [pc: 21, line: 1]       [pc: 27, line: 1]     local variable table:       [pc: 0, pc: 32] local: index: 0 type: java.lang.object 

Comments

Popular posts from this blog

sql - VB.NET Operand type clash: date is incompatible with int error -

SVG stroke-linecap doesn't work for circles in Firefox? -

python - TypeError: Scalar value for argument 'color' is not numeric in openCV -