Another one ctfe log2, integer and real versions:

[code]
module util.ctfelog2;

uint ctfe_ilog2(ulong arg) pure {
   assert(arg != 0);
   uint result = 0;
   while(arg >>= 1)
     result++;
   return result;
}

ulong ctfe_log2(real arg, uint fracBits) pure {
   import std.math : sqrt, SQRT2;
   uint intPart = ctfe_ilog2(cast(ulong)arg);
   ulong result = intPart;
   if(fracBits == 0 || arg == (1 << intPart))
     return result << fracBits;
   real sq = arg / (1 << intPart);
   for(uint i = fracBits; i; i--) {
     if(sq > 2) {
       result |= 1;
       sq /= 2;
     }
     sq *= sq;
     result <<= 1;
   }
   return result;
}

real ctfe_log2(real arg) pure {
   return ctfe_log2(arg, 56) / cast(real)(1UL << 56);
}

unittest {
   import std.math : log2, abs;
   for(real l = 1; l < 256; l += 0.3) {
     double d1 = ctfe_log2(l);
     double d2 = log2(l);
     assert(abs(d1 - d2) < (cast(real)1.0)/(1UL << 48));
   }
}
[/code]

Reply via email to