,    _
                  /|   | |
                _/_\_  >_<
               .-\-/.   |
              /  | | \_ |
              \ \| |\__(/
              /(`---')  |
             / /     \  |
          _.'  \'-'  /  |
          `----'`=-='   '    hjw
          C Thaumaturgy Center
       
       You like magic?
       
       
       Find the integer log base 2 of an integer with an 64-bit IEEE float
       
       int v; // 32-bit integer to find the log base 2 of
       int r; // result of log_2(v) goes here
       union { unsigned int u[2]; double d;} t; // temp
       t.u[__FLOAT_WORD_ORDER==LITTLE_ENDIAN] = 0x43300000;
       t.u[__FLOAT_WORD_ORDER!=LITTLE_ENDIAN] = v;
       t.d -= 4503599627370496.0;
       r = (t.u[__FLOAT_WORD_ORDER==LITTLE_ENDIAN]>> 20) - 0x3FF;
       
       The code above loads a 64-bit (IEEE-754 floating-point) double with a
       32-bit integer (with no paddding bits) by storing the integer in the
       mantissa while the exponent is set to 2 52. From this newly minted
       double, 2 52 (expressed as a double) is subtracted, which sets the
       resulting exponent to the log base 2 of the input value, v. All that
       is left is shifting the exponent bits into position (20 bits right)
       and subtracting the bias, 0x3FF (which is 1023 decimal). This
       technique only takes 5 operations, but many CPUs are slow at
       manipulating doubles, and the endianess of the architecture must be
       accommodated.
       
       Eric Cole sent me this on January 15, 2006. Evan Felix pointed out a
       typo on April 4, 2006. Vincent Lefèvre told me on July 9, 2008 to
       change the endian check to use the float's endian, which could differ
       from the integer's endian.
       
       
 (TXT) Get the full database.
 (HTM) Got some C magic? Send the spell source to 20h@r-36.net
 (DIR) << back to bitreich.org