Skip to content

Instantly share code, notes, and snippets.

@nxnfufunezn
Forked from CAFxX/log10.c
Last active September 13, 2015 10:53
Show Gist options
  • Save nxnfufunezn/b4f663fe47e0db505974 to your computer and use it in GitHub Desktop.
Save nxnfufunezn/b4f663fe47e0db505974 to your computer and use it in GitHub Desktop.
Fast integer log10 in C
#include <stdint.h>
/*
Fast 64bit integer log10
WARNING: calling ilog10c(0) yields undefined behaviour!
On x64 this compiles down to:
pushq %rbp
movq %rsp, %rbp
bsrq %rdi, %rax
xorq $63, %rax
movl %eax, %ecx
xorl $63, %ecx
leal (%rcx,%rcx,2), %ecx
movl $3435973837, %edx
imulq %rcx, %rdx
shrq $35, %rdx
leaq _ilog10c.thr(%rip), %rcx
cmpq %rdi, (%rcx,%rax,8)
setbe %al
movzbl %al, %eax
addl %edx, %eax
popq %rbp
ret
*/
uint32_t ilog10c(uint64_t v) {
static const uint64_t thr[64] = {
10000000000000000000ULL, 0, 0, 0, 1000000000000000000ULL, 0, 0, 100000000000000000ULL, 0, 0,
10000000000000000ULL, 0, 0, 0, 1000000000000000ULL, 0, 0, 100000000000000ULL, 0, 0,
10000000000000ULL, 0, 0, 0, 1000000000000ULL, 0, 0, 100000000000ULL, 0, 0,
10000000000ULL, 0, 0, 0, 1000000000ULL, 0, 0, 100000000ULL, 0, 0,
10000000ULL, 0, 0, 0, 1000000ULL, 0, 0, 100000ULL, 0, 0,
10000ULL, 0, 0, 0, 1000ULL, 0, 0, 100ULL, 0, 0,
10ULL, 0, 0, 0
};
uint32_t lz = __builtin_clzll(v);
return (63 - lz) * 3 / 10 + (v >= thr[lz]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment