Excerpts from fons's message of 2011-01-28
16:11:52 +0100:
On Fri, Jan 28, 2011 at 02:02:36PM +0100, Philipp
Überbacher wrote:
rant_begin
Why can't log mean the same thing everywhere? Why does it need to be
base e here and base 10 there? Why is there no consistency?
And why is there no proper logarithmus dualis function? Because you
can simply do log(n)/log(2)? We've just seen how well this works.
How about:
log() - base 10
ln() - base e - logarithmus naturalis
ld() - base 2 - logarithmus dualis
rant_end
Libm has log(), log10, and log2().
Took me a while to figure out that libm is part of glibc :)
Good to know that those functions are available on probably pretty much
all linux systems.
The next
obvious question is: Does the inaccuracy reliably result in
values bigger than 11?
No.
If the input is a power of two, and you expect an integer as
a result, just do
k = (int)(log2(x) + 1e-6)
log2() suffers from the same problem? I somewhat dislike the idea of
adding a constant.
or
k = (int)(log(x)/log(2) + 1e-6)
or
int m, k;
for (k = 0, m = 1; m < x; k++, m <<= 1);
which will round up if x is not a power of 2.
Neat. I thought about it myself yesterday but my ideas weren't exactly
brilliant. One idea was to divide by 2, the other to use a small
lookup table for powers of 2. I don't really know about efficiency, but
I guess bit shifting is as efficient as it gets?
Anyway, it's a neat way to avoid the problem and the rounding properties
of mult/div in case of not power of 2 could be useful as well.
Well, now I'm just being pedantic :-), but as a quick test using rdtsc
(i.e. profiling to be taken with a grain of salt):
1: log(x)/log(2)
2: (1 << k) < x
3: m < x & m <<= 1
This is 1000 iterations; cycling through x of 512, 1024, 2048, 4096 (to
prevent the compiler optimizing log(x)/log(2) to a single call
throughout the whole test). The fourth line is the sum of the iterator
in each loop.
./a.out (unoptimized)
1 3132000 cycles
2 261468 cycles
3 285273 cycles
1 50500, 2 50500, 3 50500
./a.out (-O3)
1 2598345 cycles
2 170055 cycles
3 173673 cycles
1 50500, 2 50500, 3 50500
I must admit, I'm surprised that fons way shows slightly slower in my
test!