Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can The 5-Op Log2(Int 32) Bit Hack be Done in Java?

Just to clarify this is NOT a homework question as I've seen similar accusations leveled against other bit-hackish questions:

That said, I have this bit hack in C:

#include <stdio.h>

const int __FLOAT_WORD_ORDER = 0;
const int __LITTLE_END = 0;

// Finds log-base 2 of 32-bit integer
int log2hack(int v)
{
  union { unsigned int u[2]; double d; } t; // temp
  t.u[0]=0;
  t.u[1]=0;
  t.d=0.0;

  t.u[__FLOAT_WORD_ORDER==__LITTLE_END] = 0x43300000;
  t.u[__FLOAT_WORD_ORDER!=__LITTLE_END] = v;
  t.d -= 4503599627370496.0;
  return (t.u[__FLOAT_WORD_ORDER==__LITTLE_END] >> 20) - 0x3FF;
}

int main ()
{
  int i = 25; //Log2n(25) = 4
  int j = 33; //Log2n(33) = 5

  printf("Log2n(25)=%i!\n",
         log2hack(25));
  printf("Log2n(33)=%i!\n",
         log2hack(33));

  return 0;
}

I want to convert this to Java. So far what I have is:

public int log2Hack(int n)
    {
        int r; // result of log_2(v) goes here
        int[] u = new int [2]; 
        double d = 0.0;
        if (BitonicSorterForArbitraryN.__FLOAT_WORD_ORDER==
                BitonicSorterForArbitraryN.LITTLE_ENDIAN) 
        {
            u[1] = 0x43300000;
            u[0] = n;
        }
        else    
        {
            u[0] = 0x43300000;
            u[1] = n;
        }
        d -= 4503599627370496.0;
        if (BitonicSorterForArbitraryN.__FLOAT_WORD_ORDER==
                BitonicSorterForArbitraryN.LITTLE_ENDIAN)
            r = (u[1] >> 20) - 0x3FF;
        else
            r = (u[0] >> 20) - 0x3FF;

        return r;
    }

(Note it's inside a bitonic sorting class of mine...)

Anyhow, when I run this for the same values 33 and 25, I get 52 in each cases.

I know Java's integers are signed, so I'm pretty sure that has something to do with why this is failing. Does anyone have any ideas how I can get this 5-op, 32-bit integer log 2 to work in Java?

P.S. For the record, the technique is not mine, I borrowed it from here: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogIEEE64Float

like image 264
Jason R. Mick Avatar asked Dec 03 '11 17:12

Jason R. Mick


1 Answers

If you're in Java, can't you simply do 31 - Integer(v).numberOfLeadingZeros()? If they implement this using __builtin_clz it should be fast.

like image 108
mtrw Avatar answered Sep 21 '22 21:09

mtrw