2020-08-04 02:39:09 +01:00
|
|
|
|
#pragma once
|
|
|
|
|
|
2020-10-31 01:55:20 +00:00
|
|
|
|
#include "../Common.h"
|
2020-08-04 02:39:09 +01:00
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
|
|
namespace Feather::Math
|
|
|
|
|
{
|
|
|
|
|
// de Bruijn Sequence: B(2, 5) = 0000 0111 0111 1100 1011 0101 0011 0001. Contains all 32 distinct 5-bit strings.
|
|
|
|
|
constexpr uint32_t DE_BRUIJN_SEQ = 0x077CB531U;
|
|
|
|
|
|
|
|
|
|
constexpr int MULTIPLY_DE_BRUIJN_BIT_POSITION[32] = {0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9};
|
|
|
|
|
|
|
|
|
|
// Is x a power of two?
|
|
|
|
|
inline constexpr bool IsPowerOf2(int x)
|
|
|
|
|
{
|
|
|
|
|
return x != 0 && (x & (x - 1)) == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Smallest number 2^z that is greater than or equal to x
|
|
|
|
|
// Precondition: x > 0
|
|
|
|
|
inline constexpr int RoundToPowerOf2(int x)
|
|
|
|
|
{
|
|
|
|
|
x--;
|
|
|
|
|
|
|
|
|
|
x |= x >> 1;
|
|
|
|
|
x |= x >> 2;
|
|
|
|
|
x |= x >> 4;
|
|
|
|
|
x |= x >> 8;
|
|
|
|
|
x |= x >> 16;
|
|
|
|
|
return x + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline constexpr int CeilLog2(int x)
|
|
|
|
|
{
|
|
|
|
|
// Ensure x is power of 2
|
|
|
|
|
x = IsPowerOf2(x) ? x : RoundToPowerOf2(x);
|
|
|
|
|
|
|
|
|
|
// The de Bruijn sequence contains all 32 distinct 5-bit strings
|
|
|
|
|
// 27 is 32 - 5 and 0x1F (31) is the lower 5 bits 0001 1111
|
|
|
|
|
return MULTIPLY_DE_BRUIJN_BIT_POSITION[(int)((int64_t)x * DE_BRUIJN_SEQ >> 27) & 0x1F];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// log base 2
|
|
|
|
|
inline constexpr int Log2(int x)
|
|
|
|
|
{
|
|
|
|
|
return CeilLog2(x) - (IsPowerOf2(x) ? 0 : 1);
|
|
|
|
|
}
|
2020-10-31 01:55:20 +00:00
|
|
|
|
|
|
|
|
|
// Divide and round up
|
|
|
|
|
template<typename T>
|
|
|
|
|
inline constexpr T CeilDiv(const T a, const T b)
|
|
|
|
|
{
|
|
|
|
|
return (a / b) + (a % b != 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|