#pragma once
#include "box3d/base.h"
#include <stdbool.h>
#include <stdint.h>
#if defined( _MSC_VER ) && !defined( __clang__ )
#include <intrin.h>
static inline uint32_t b3CTZ32( uint32_t block )
{
unsigned long index;
_BitScanForward( &index, block );
return index;
}
static inline uint32_t b3CLZ32( uint32_t value )
{
#if 1
unsigned long index;
if ( _BitScanReverse( &index, value ) )
{
return 31 - index;
}
else
{
return 32;
}
#else#endif
}
static inline uint32_t b3CTZ64( uint64_t block )
{
unsigned long index;
#ifdef _WIN64
_BitScanForward64( &index, block );
#else
if ( (uint32_t)block != 0 )
{
_BitScanForward( &index, (uint32_t)block );
}
else
{
_BitScanForward( &index, (uint32_t)( block >> 32 ) );
index += 32;
}
#endif
return index;
}
static inline int b3PopCount64( uint64_t block )
{
return (int)__popcnt64( block );
}
#else
static inline uint32_t b3CTZ32( uint32_t block )
{
return __builtin_ctz( block );
}
static inline uint32_t b3CLZ32( uint32_t value )
{
return __builtin_clz( value );
}
static inline uint32_t b3CTZ64( uint64_t block )
{
return __builtin_ctzll( block );
}
static inline int b3PopCount64( uint64_t block )
{
return __builtin_popcountll( block );
}
#endif
static inline bool b3IsPowerOf2( int x )
{
return ( x & ( x - 1 ) ) == 0;
}
static inline int b3BoundingPowerOf2( int x )
{
if ( x <= 1 )
{
return 1;
}
return 32 - (int)b3CLZ32( (uint32_t)x - 1 );
}
static inline int b3RoundUpPowerOf2( int x )
{
if ( x <= 1 )
{
return 1;
}
return 1 << ( 32 - (int)b3CLZ32( (uint32_t)x - 1 ) );
}
static inline int b3LowerPowerOf2Exponent( int x )
{
B3_ASSERT( x > 0 );
int clz = (int)b3CLZ32( (uint32_t)x );
return 31 - clz;
}