fix bugs in ilog2 (yoink) and add self-test+asserts.
This was SVN commit r2600.
This commit is contained in:
parent
aba23e4fdb
commit
8475c16c31
@ -25,11 +25,15 @@
|
||||
|
||||
#include "sysdep/sysdep.h"
|
||||
|
||||
#ifndef PERFORM_SELF_TEST
|
||||
#define PERFORM_SELF_TEST 0
|
||||
#endif
|
||||
|
||||
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
u32 fnv_hash(const void* buf, const size_t len)
|
||||
u32 fnv_hash(const void* buf, size_t len)
|
||||
{
|
||||
u32 h = 0x811c9dc5u;
|
||||
// give distinct values for different length 0 buffers.
|
||||
@ -65,7 +69,7 @@ u32 fnv_hash(const void* buf, const size_t len)
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
u64 fnv_hash64(const void* buf, const size_t len)
|
||||
u64 fnv_hash64(const void* buf, size_t len)
|
||||
{
|
||||
u64 h = 0xCBF29CE484222325ull;
|
||||
// give distinct values for different length 0 buffers.
|
||||
@ -101,7 +105,7 @@ u64 fnv_hash64(const void* buf, const size_t len)
|
||||
// special version for strings: first converts to lowercase
|
||||
// (useful for comparing mixed-case filenames).
|
||||
// note: still need <len>, e.g. to support non-0-terminated strings
|
||||
u32 fnv_lc_hash(const char* str, const size_t len)
|
||||
u32 fnv_lc_hash(const char* str, size_t len)
|
||||
{
|
||||
u32 h = 0x811c9dc5u;
|
||||
// give distinct values for different length 0 buffers.
|
||||
@ -135,44 +139,53 @@ u32 fnv_lc_hash(const char* str, const size_t len)
|
||||
|
||||
|
||||
|
||||
bool is_pow2(const long n)
|
||||
bool is_pow2(uint n)
|
||||
{
|
||||
return (n != 0l) && !(n & (n-1l));
|
||||
// 0 would pass the test below but isn't a POT.
|
||||
if(n == 0)
|
||||
return false;
|
||||
return (n & (n-1l)) == 0;
|
||||
}
|
||||
|
||||
|
||||
// return -1 if not an integral power of 2,
|
||||
// otherwise the base2 logarithm
|
||||
|
||||
int ilog2(const int n)
|
||||
int ilog2(uint n)
|
||||
{
|
||||
int bit_index; // return value
|
||||
|
||||
#if CPU_IA32
|
||||
|
||||
__asm
|
||||
{
|
||||
mov ecx, [n]
|
||||
or eax, -1 // return value
|
||||
or eax, -1 // return value if not a POT
|
||||
test ecx, ecx
|
||||
jz not_pot
|
||||
lea edx, [ecx-1]
|
||||
test ecx, edx // power of 2?
|
||||
jnz skip
|
||||
test ecx, edx
|
||||
jnz not_pot
|
||||
bsf eax, ecx
|
||||
skip:
|
||||
mov [n], eax
|
||||
not_pot:
|
||||
mov [bit_index], eax
|
||||
}
|
||||
|
||||
return n;
|
||||
|
||||
#else
|
||||
|
||||
if(n || n & (n-1))
|
||||
if(!is_pow2(n))
|
||||
return -1;
|
||||
|
||||
int i = 1, j = 0;
|
||||
for(; i != n; i += i, j++)
|
||||
;
|
||||
return j;
|
||||
bit_index = 0;
|
||||
// note: compare against n directly because it is known to be a POT.
|
||||
for(uint bit_value = 1; bit_value != n; bit_value *= 2)
|
||||
bit_index++;
|
||||
|
||||
#endif
|
||||
|
||||
debug_assert(-1 <= bit_index && bit_index < sizeof(int)*CHAR_BIT);
|
||||
debug_assert(bit_index == -1 || n == (1u << bit_index));
|
||||
return bit_index;
|
||||
}
|
||||
|
||||
|
||||
@ -193,7 +206,7 @@ uint log2(uint x)
|
||||
|
||||
int ilog2(const float x)
|
||||
{
|
||||
const u32 i = (u32&)x;
|
||||
const u32 i = *(u32*)&x;
|
||||
u32 biased_exp = (i >> 23) & 0xff;
|
||||
return (int)biased_exp - 127;
|
||||
}
|
||||
@ -454,3 +467,35 @@ int match_wildcardw(const wchar_t* s, const wchar_t* w)
|
||||
|
||||
return (*w == '\0');
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// built-in self test
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if PERFORM_SELF_TEST
|
||||
namespace test {
|
||||
|
||||
static void test_log2()
|
||||
{
|
||||
debug_assert(ilog2(0) == -1);
|
||||
debug_assert(ilog2(3) == -1);
|
||||
debug_assert(ilog2(0xffffffff) == -1);
|
||||
debug_assert(ilog2(1) == 0);
|
||||
debug_assert(ilog2(256) == 8);
|
||||
debug_assert(ilog2(0x80000000) == 31);
|
||||
}
|
||||
|
||||
static int run_tests()
|
||||
{
|
||||
test_log2();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy = run_tests();
|
||||
|
||||
} // namespace test
|
||||
#endif // #if PERFORM_SELF_TEST
|
||||
|
@ -309,12 +309,12 @@ const size_t GiB = 1ul << 30;
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
extern u32 fnv_hash(const void* buf, const size_t len = 0);
|
||||
extern u64 fnv_hash64(const void* buf, const size_t len = 0);
|
||||
extern u32 fnv_hash(const void* buf, size_t len = 0);
|
||||
extern u64 fnv_hash64(const void* buf, size_t len = 0);
|
||||
|
||||
// special version for strings: first converts to lowercase
|
||||
// (useful for comparing mixed-case filenames)
|
||||
extern u32 fnv_lc_hash(const char* str, const size_t len = 0);
|
||||
extern u32 fnv_lc_hash(const char* str, size_t len = 0);
|
||||
|
||||
// hash (currently FNV) of a filename
|
||||
typedef u32 FnHash;
|
||||
@ -332,11 +332,11 @@ extern u64 movzx_64le(const u8* p, size_t size);
|
||||
extern i64 movsx_64le(const u8* p, size_t size);
|
||||
|
||||
|
||||
extern bool is_pow2(long n);
|
||||
extern bool is_pow2(uint n);
|
||||
|
||||
// return -1 if not an integral power of 2,
|
||||
// otherwise the base2 logarithm
|
||||
extern int ilog2(const int n);
|
||||
extern int ilog2(uint n);
|
||||
|
||||
// return log base 2, rounded up.
|
||||
extern uint log2(uint x);
|
||||
|
@ -535,9 +535,9 @@ int poll(struct pollfd /* fds */[], int /* nfds */, int /* timeout */)
|
||||
// used by mprotect.
|
||||
static DWORD win32_prot(int prot)
|
||||
{
|
||||
// this covers all possible combinations of read|write|exec
|
||||
// this covers all 8 combinations of read|write|exec
|
||||
// (note that "none" means all flags are 0).
|
||||
switch(prot)
|
||||
switch(prot & (PROT_READ|PROT_WRITE|PROT_EXEC))
|
||||
{
|
||||
case PROT_NONE:
|
||||
return PAGE_NOACCESS;
|
||||
@ -558,7 +558,7 @@ static DWORD win32_prot(int prot)
|
||||
case PROT_READ|PROT_WRITE|PROT_EXEC:
|
||||
return PAGE_EXECUTE_READWRITE;
|
||||
default:
|
||||
return 0;
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -687,7 +687,7 @@ void* mmap(void* user_start, size_t len, int prot, int flags, int fd, off_t ofs)
|
||||
}
|
||||
|
||||
fail:
|
||||
return MAP_FAILED;
|
||||
return (void*)MAP_FAILED;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user