Add 64-bit versions of core power of 2 functions

This commit is contained in:
Aaron Franke
2025-05-19 09:53:53 -07:00
parent 64b09905c7
commit f6f1df7d73
25 changed files with 161 additions and 124 deletions

View File

@@ -415,17 +415,17 @@ class CharBuffer {
char stack_buffer[256];
char *buffer = nullptr;
int capacity = 0;
int written = 0;
int64_t capacity = 0;
int64_t written = 0;
bool grow() {
if (vector.resize(next_power_of_2(1 + written)) != OK) {
if (vector.resize(next_power_of_2((uint64_t)1 + (uint64_t)written)) != OK) {
return false;
}
if (buffer == stack_buffer) { // first chunk?
for (int i = 0; i < written; i++) {
for (int64_t i = 0; i < written; i++) {
vector.write[i] = stack_buffer[i];
}
}

View File

@@ -39,7 +39,7 @@ class FileAccessCompressed : public FileAccess {
bool writing = false;
uint64_t write_pos = 0;
uint8_t *write_ptr = nullptr;
uint32_t write_buffer_size = 0;
uint64_t write_buffer_size = 0;
uint64_t write_max = 0;
uint32_t block_size = 0;
mutable bool read_eof = false;

View File

@@ -1115,8 +1115,8 @@ bool Image::is_size_po2() const {
void Image::resize_to_po2(bool p_square, Interpolation p_interpolation) {
ERR_FAIL_COND_MSG(is_compressed(), "Cannot resize in compressed image formats.");
int w = next_power_of_2(width);
int h = next_power_of_2(height);
int w = next_power_of_2((uint32_t)width);
int h = next_power_of_2((uint32_t)height);
if (p_square) {
w = h = MAX(w, h);
}

View File

@@ -38,7 +38,7 @@
void PacketPeer::set_encode_buffer_max_size(int p_max_size) {
ERR_FAIL_COND_MSG(p_max_size < 1024, "Max encode buffer must be at least 1024 bytes");
ERR_FAIL_COND_MSG(p_max_size > 256 * 1024 * 1024, "Max encode buffer cannot exceed 256 MiB");
encode_buffer_max_size = next_power_of_2(p_max_size);
encode_buffer_max_size = next_power_of_2((uint32_t)p_max_size);
encode_buffer.clear();
}
@@ -103,7 +103,7 @@ Error PacketPeer::put_var(const Variant &p_packet, bool p_full_objects) {
if (unlikely(encode_buffer.size() < len)) {
encode_buffer.resize(0); // Avoid realloc
encode_buffer.resize(next_power_of_2(len));
encode_buffer.resize(next_power_of_2((uint32_t)len));
}
uint8_t *w = encode_buffer.ptrw();
@@ -301,8 +301,8 @@ void PacketPeerStream::set_input_buffer_max_size(int p_max_size) {
ERR_FAIL_COND_MSG(p_max_size < 0, "Max size of input buffer size cannot be smaller than 0.");
// WARNING: May lose packets.
ERR_FAIL_COND_MSG(ring_buffer.data_left(), "Buffer in use, resizing would cause loss of data.");
ring_buffer.resize(nearest_shift(next_power_of_2(p_max_size + 4)) - 1);
input_buffer.resize(next_power_of_2(p_max_size + 4));
ring_buffer.resize(nearest_shift(next_power_of_2((uint32_t)p_max_size + (uint32_t)4)) - 1);
input_buffer.resize(next_power_of_2((uint32_t)p_max_size + (uint32_t)4));
}
int PacketPeerStream::get_input_buffer_max_size() const {
@@ -310,7 +310,7 @@ int PacketPeerStream::get_input_buffer_max_size() const {
}
void PacketPeerStream::set_output_buffer_max_size(int p_max_size) {
output_buffer.resize(next_power_of_2(p_max_size + 4));
output_buffer.resize(next_power_of_2((uint32_t)p_max_size + (uint32_t)4));
}
int PacketPeerStream::get_output_buffer_max_size() const {

View File

@@ -200,7 +200,7 @@ Error PacketPeerUDP::bind(int p_port, const IPAddress &p_bind_address, int p_rec
_sock->close();
return err;
}
rb.resize(nearest_shift(p_recv_buffer_size));
rb.resize(nearest_shift((uint32_t)p_recv_buffer_size));
return OK;
}

View File

@@ -79,7 +79,7 @@ Error StreamPeerGZIP::_start(bool p_compress, bool p_is_deflate, int buffer_size
ERR_FAIL_COND_V_MSG(buffer_size <= 0, ERR_INVALID_PARAMETER, "Invalid buffer size. It should be a positive integer.");
clear();
compressing = p_compress;
rb.resize(nearest_shift(buffer_size - 1));
rb.resize(nearest_shift(uint32_t(buffer_size - 1)));
buffer.resize(1024);
// Create ctx.

View File

@@ -226,8 +226,8 @@ void Geometry2D::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_re
real_t best_aspect = 1e20;
for (int i = 0; i < results.size(); i++) {
real_t h = next_power_of_2(results[i].max_h);
real_t w = next_power_of_2(results[i].max_w);
real_t h = next_power_of_2((uint32_t)results[i].max_h);
real_t w = next_power_of_2((uint32_t)results[i].max_w);
real_t aspect = h > w ? h / w : w / h;
if (aspect < best_aspect) {
best = i;

View File

@@ -123,7 +123,7 @@ StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::reserve(int p_
}
bool need_copy = string_length > 0 && buffer.is_empty();
buffer.resize(next_power_of_2(p_size));
buffer.resize(next_power_of_2((uint32_t)p_size));
if (need_copy) {
memcpy(buffer.ptrw(), short_buffer, string_length * sizeof(char32_t));
}

View File

@@ -52,25 +52,6 @@ public:
static constexpr USize MAX_INT = INT64_MAX;
private:
// Function to find the next power of 2 to an integer.
static _FORCE_INLINE_ USize next_po2(USize x) {
if (x == 0) {
return 0;
}
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
if (sizeof(USize) == 8) {
x |= x >> 32;
}
return ++x;
}
// Alignment: ↓ max_align_t ↓ USize ↓ max_align_t
// ┌────────────────────┬──┬─────────────┬──┬───────────...
// │ SafeNumeric<USize> │░░│ USize │░░│ T[]
@@ -107,7 +88,7 @@ private:
}
_FORCE_INLINE_ static USize _get_alloc_size(USize p_elements) {
return next_po2(p_elements * sizeof(T));
return next_power_of_2(p_elements * (USize)sizeof(T));
}
_FORCE_INLINE_ static bool _get_alloc_size_checked(USize p_elements, USize *out) {
@@ -122,7 +103,7 @@ private:
*out = 0;
return false;
}
*out = next_po2(o);
*out = next_power_of_2(o);
if (__builtin_add_overflow(o, static_cast<USize>(32), &p)) {
return false; // No longer allocated here.
}

View File

@@ -154,42 +154,84 @@ inline bool is_power_of_2(const T x) {
}
// Function to find the next power of 2 to an integer.
static _FORCE_INLINE_ unsigned int next_power_of_2(unsigned int x) {
if (x == 0) {
constexpr uint64_t next_power_of_2(uint64_t p_number) {
if (p_number == 0) {
return 0;
}
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
--p_number;
p_number |= p_number >> 1;
p_number |= p_number >> 2;
p_number |= p_number >> 4;
p_number |= p_number >> 8;
p_number |= p_number >> 16;
p_number |= p_number >> 32;
return ++x;
return ++p_number;
}
constexpr uint32_t next_power_of_2(uint32_t p_number) {
if (p_number == 0) {
return 0;
}
--p_number;
p_number |= p_number >> 1;
p_number |= p_number >> 2;
p_number |= p_number >> 4;
p_number |= p_number >> 8;
p_number |= p_number >> 16;
return ++p_number;
}
// Function to find the previous power of 2 to an integer.
static _FORCE_INLINE_ unsigned int previous_power_of_2(unsigned int x) {
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x - (x >> 1);
constexpr uint64_t previous_power_of_2(uint64_t p_number) {
p_number |= p_number >> 1;
p_number |= p_number >> 2;
p_number |= p_number >> 4;
p_number |= p_number >> 8;
p_number |= p_number >> 16;
p_number |= p_number >> 32;
return p_number - (p_number >> 1);
}
constexpr uint32_t previous_power_of_2(uint32_t p_number) {
p_number |= p_number >> 1;
p_number |= p_number >> 2;
p_number |= p_number >> 4;
p_number |= p_number >> 8;
p_number |= p_number >> 16;
return p_number - (p_number >> 1);
}
// Function to find the closest power of 2 to an integer.
static _FORCE_INLINE_ unsigned int closest_power_of_2(unsigned int x) {
unsigned int nx = next_power_of_2(x);
unsigned int px = previous_power_of_2(x);
return (nx - x) > (x - px) ? px : nx;
constexpr uint64_t closest_power_of_2(uint64_t p_number) {
uint64_t nx = next_power_of_2(p_number);
uint64_t px = previous_power_of_2(p_number);
return (nx - p_number) > (p_number - px) ? px : nx;
}
constexpr uint32_t closest_power_of_2(uint32_t p_number) {
uint32_t nx = next_power_of_2(p_number);
uint32_t px = previous_power_of_2(p_number);
return (nx - p_number) > (p_number - px) ? px : nx;
}
// Get a shift value from a power of 2.
static inline int get_shift_from_power_of_2(unsigned int p_bits) {
for (unsigned int i = 0; i < 32; i++) {
if (p_bits == (unsigned int)(1 << i)) {
constexpr int32_t get_shift_from_power_of_2(uint64_t p_bits) {
for (uint64_t i = 0; i < (uint64_t)64; i++) {
if (p_bits == (uint64_t)((uint64_t)1 << i)) {
return i;
}
}
return -1;
}
constexpr int32_t get_shift_from_power_of_2(uint32_t p_bits) {
for (uint32_t i = 0; i < (uint32_t)32; i++) {
if (p_bits == (uint32_t)((uint32_t)1 << i)) {
return i;
}
}
@@ -198,30 +240,44 @@ static inline int get_shift_from_power_of_2(unsigned int p_bits) {
}
template <typename T>
static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) {
--x;
static _FORCE_INLINE_ T nearest_power_of_2_templated(T p_number) {
--p_number;
// The number of operations on x is the base two logarithm
// of the number of bits in the type. Add three to account
// for sizeof(T) being in bytes.
size_t num = get_shift_from_power_of_2(sizeof(T)) + 3;
constexpr size_t shift_steps = get_shift_from_power_of_2((uint64_t)sizeof(T)) + 3;
// If the compiler is smart, it unrolls this loop.
// If it's dumb, this is a bit slow.
for (size_t i = 0; i < num; i++) {
x |= x >> (1 << i);
for (size_t i = 0; i < shift_steps; i++) {
p_number |= p_number >> (1 << i);
}
return ++x;
return ++p_number;
}
// Function to find the nearest (bigger) power of 2 to an integer.
static inline unsigned int nearest_shift(unsigned int p_number) {
for (int i = 30; i >= 0; i--) {
if (p_number & (1 << i)) {
return i + 1;
constexpr uint64_t nearest_shift(uint64_t p_number) {
uint64_t i = 63;
do {
i--;
if (p_number & ((uint64_t)1 << i)) {
return i + (uint64_t)1;
}
}
} while (i != 0);
return 0;
}
constexpr uint32_t nearest_shift(uint32_t p_number) {
uint32_t i = 31;
do {
i--;
if (p_number & ((uint32_t)1 << i)) {
return i + (uint32_t)1;
}
} while (i != 0);
return 0;
}

View File

@@ -153,9 +153,9 @@ Error AudioDriverCoreAudio::init() {
result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &strdesc, sizeof(strdesc));
ERR_FAIL_COND_V(result != noErr, FAILED);
int latency = Engine::get_singleton()->get_audio_output_latency();
uint32_t latency = Engine::get_singleton()->get_audio_output_latency();
// Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels)
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
buffer_frames = closest_power_of_2(latency * (uint32_t)mix_rate / (uint32_t)1000);
#ifdef MACOS_ENABLED
result = AudioUnitSetProperty(audio_unit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, kOutputBus, &buffer_frames, sizeof(UInt32));
@@ -456,9 +456,9 @@ Error AudioDriverCoreAudio::init_input_device() {
result = AudioUnitSetProperty(input_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, sizeof(strdesc));
ERR_FAIL_COND_V(result != noErr, FAILED);
int latency = Engine::get_singleton()->get_audio_output_latency();
uint32_t latency = Engine::get_singleton()->get_audio_output_latency();
// Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels)
capture_buffer_frames = closest_power_of_2(latency * capture_mix_rate / 1000);
capture_buffer_frames = closest_power_of_2(latency * (uint32_t)capture_mix_rate / (uint32_t)1000);
unsigned int buffer_size = capture_buffer_frames * capture_channels;
input_buf.resize(buffer_size);

View File

@@ -940,7 +940,7 @@ uint32_t RenderingDeviceDriverD3D12::_find_max_common_supported_sample_count(Vec
msql.SampleCount = (UINT)samples;
HRESULT res = device->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &msql, sizeof(msql));
if (SUCCEEDED(res) && msql.NumQualityLevels) {
int bit = get_shift_from_power_of_2(samples);
int bit = get_shift_from_power_of_2((uint32_t)samples);
ERR_FAIL_COND_V(bit == -1, 1);
mask |= (uint32_t)(1 << bit);
}

View File

@@ -1270,7 +1270,7 @@ void LightStorage::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits
ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);
ERR_FAIL_NULL(shadow_atlas);
ERR_FAIL_COND(p_size < 0);
p_size = next_power_of_2(p_size);
p_size = next_power_of_2((uint32_t)p_size);
if (p_size == shadow_atlas->size && p_16_bits == shadow_atlas->use_16_bits) {
return;
@@ -1317,7 +1317,7 @@ void LightStorage::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quad
ERR_FAIL_INDEX(p_quadrant, 4);
ERR_FAIL_INDEX(p_subdivision, 16384);
uint32_t subdiv = next_power_of_2(p_subdivision);
uint32_t subdiv = next_power_of_2((uint32_t)p_subdivision);
if (subdiv & 0xaaaaaaaa) { // sqrt(subdiv) must be integer.
subdiv <<= 1;
}
@@ -1391,7 +1391,7 @@ bool LightStorage::shadow_atlas_update_light(RID p_atlas, RID p_light_instance,
}
uint32_t quad_size = shadow_atlas->size >> 1;
int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage));
int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(uint32_t(quad_size * p_coverage)));
int valid_quadrants[4];
int valid_quadrant_count = 0;

View File

@@ -853,17 +853,17 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_
// Could not find texture to fit, create one.
int texsize = MAX(p_data->size.x * 0.125, 256);
texsize = next_power_of_2(texsize);
texsize = next_power_of_2((uint32_t)texsize);
if (p_msdf) {
texsize = MIN(texsize, 2048);
} else {
texsize = MIN(texsize, 1024);
}
if (mw > texsize) { // Special case, adapt to it?
texsize = next_power_of_2(mw);
texsize = next_power_of_2((uint32_t)mw);
}
if (mh > texsize) { // Special case, adapt to it?
texsize = next_power_of_2(mh);
texsize = next_power_of_2((uint32_t)mh);
}
ShelfPackTexture tex = ShelfPackTexture(texsize, texsize);

View File

@@ -275,7 +275,7 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_
// Could not find texture to fit, create one.
int texsize = MAX(p_data->size.x * 0.125, 256);
texsize = next_power_of_2(texsize);
texsize = next_power_of_2((uint32_t)texsize);
if (p_msdf) {
texsize = MIN(texsize, 2048);
@@ -283,10 +283,10 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_
texsize = MIN(texsize, 1024);
}
if (mw > texsize) { // Special case, adapt to it?
texsize = next_power_of_2(mw);
texsize = next_power_of_2((uint32_t)mw);
}
if (mh > texsize) { // Special case, adapt to it?
texsize = next_power_of_2(mh);
texsize = next_power_of_2((uint32_t)mh);
}
ShelfPackTexture tex = ShelfPackTexture(texsize, texsize);

View File

@@ -61,7 +61,7 @@ void WebRTCDataChannel::_bind_methods() {
}
WebRTCDataChannel::WebRTCDataChannel() {
_in_buffer_shift = nearest_shift((int)GLOBAL_GET("network/limits/webrtc/max_channel_in_buffer_kb") - 1) + 10;
_in_buffer_shift = nearest_shift(uint32_t((int)GLOBAL_GET("network/limits/webrtc/max_channel_in_buffer_kb") - 1)) + (uint32_t)10;
}
WebRTCDataChannel::~WebRTCDataChannel() {

View File

@@ -106,7 +106,7 @@ Error EMWSPeer::connect_to_url(const String &p_url, Ref<TLSOptions> p_tls_option
if (peer_sock == -1) {
return FAILED;
}
in_buffer.resize(nearest_shift(inbound_buffer_size), max_queued_packets);
in_buffer.resize(nearest_shift((uint32_t)inbound_buffer_size), max_queued_packets);
packet_buffer.resize(inbound_buffer_size);
ready_state = STATE_CONNECTING;
return OK;

View File

@@ -297,7 +297,7 @@ Error WSLPeer::_do_server_handshake() {
wslay_event_context_server_init(&wsl_ctx, &_wsl_callbacks, this);
wslay_event_config_set_no_buffering(wsl_ctx, 1);
wslay_event_config_set_max_recv_msg_length(wsl_ctx, inbound_buffer_size);
in_buffer.resize(nearest_shift(inbound_buffer_size), max_queued_packets);
in_buffer.resize(nearest_shift((uint32_t)inbound_buffer_size), max_queued_packets);
packet_buffer.resize(inbound_buffer_size);
ready_state = STATE_OPEN;
}
@@ -406,7 +406,7 @@ void WSLPeer::_do_client_handshake() {
wslay_event_context_client_init(&wsl_ctx, &_wsl_callbacks, this);
wslay_event_config_set_no_buffering(wsl_ctx, 1);
wslay_event_config_set_max_recv_msg_length(wsl_ctx, inbound_buffer_size);
in_buffer.resize(nearest_shift(inbound_buffer_size), max_queued_packets);
in_buffer.resize(nearest_shift((uint32_t)inbound_buffer_size), max_queued_packets);
packet_buffer.resize(inbound_buffer_size);
ready_state = STATE_OPEN;
break;

View File

@@ -129,7 +129,7 @@ Error AudioDriverWeb::init() {
}
mix_rate = audio_context.mix_rate;
channel_count = audio_context.channel_count;
buffer_length = closest_power_of_2((latency * mix_rate / 1000));
buffer_length = closest_power_of_2(uint32_t(latency * mix_rate / 1000));
Error err = create(buffer_length, channel_count);
if (err != OK) {
return err;

View File

@@ -4550,7 +4550,7 @@ struct AnimationCompressionDataState {
return 1;
}
}
return nearest_shift(p_delta);
return nearest_shift((uint32_t)p_delta);
}
void _compute_max_shifts(uint32_t p_from, uint32_t p_to, uint32_t *max_shifts, uint32_t &max_frame_delta_shift) const {
@@ -4561,7 +4561,7 @@ struct AnimationCompressionDataState {
for (uint32_t i = p_from + 1; i <= p_to; i++) {
int32_t frame_delta = temp_packets[i].frame - temp_packets[i - 1].frame;
max_frame_delta_shift = MAX(max_frame_delta_shift, nearest_shift(frame_delta));
max_frame_delta_shift = MAX(max_frame_delta_shift, nearest_shift((uint32_t)frame_delta));
for (uint32_t j = 0; j < components; j++) {
int32_t diff = _compute_delta16_signed(temp_packets[i - 1].data[j], temp_packets[i].data[j]);
uint32_t shift = _compute_shift_bits_signed(diff);

View File

@@ -178,7 +178,7 @@ int AudioRBResampler::get_num_of_ready_frames() {
Error AudioRBResampler::setup(int p_channels, int p_src_mix_rate, int p_target_mix_rate, int p_buffer_msec, int p_minbuff_needed) {
ERR_FAIL_COND_V(p_channels != 1 && p_channels != 2 && p_channels != 4 && p_channels != 6 && p_channels != 8, ERR_INVALID_PARAMETER);
int desired_rb_bits = nearest_shift(MAX((p_buffer_msec / 1000.0) * p_src_mix_rate, p_minbuff_needed));
int desired_rb_bits = nearest_shift((uint32_t)MAX((p_buffer_msec / 1000.0) * p_src_mix_rate, p_minbuff_needed));
bool recreate = !rb;

View File

@@ -79,7 +79,7 @@ Ref<AudioEffectInstance> AudioEffectCapture::instantiate() {
if (!buffer_initialized) {
float target_buffer_size = AudioServer::get_singleton()->get_mix_rate() * buffer_length_seconds;
ERR_FAIL_COND_V(target_buffer_size <= 0 || target_buffer_size >= (1 << 27), Ref<AudioEffectInstance>());
buffer.resize(nearest_shift((int)target_buffer_size));
buffer.resize(nearest_shift((uint32_t)target_buffer_size));
buffer_initialized = true;
}

View File

@@ -70,7 +70,7 @@ Ref<AudioStreamPlayback> AudioStreamGenerator::instantiate_playback() {
Ref<AudioStreamGeneratorPlayback> playback;
playback.instantiate();
playback->generator = this;
int target_buffer_size = _get_target_rate() * buffer_len;
uint32_t target_buffer_size = _get_target_rate() * buffer_len;
playback->buffer.resize(nearest_shift(target_buffer_size));
playback->buffer.clear();
return playback;

View File

@@ -2133,7 +2133,7 @@ void LightStorage::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits
ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);
ERR_FAIL_NULL(shadow_atlas);
ERR_FAIL_COND(p_size < 0);
p_size = next_power_of_2(p_size);
p_size = next_power_of_2((uint32_t)p_size);
if (p_size == shadow_atlas->size && p_16_bits == shadow_atlas->use_16_bits) {
return;
@@ -2170,7 +2170,7 @@ void LightStorage::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quad
ERR_FAIL_INDEX(p_quadrant, 4);
ERR_FAIL_INDEX(p_subdivision, 16384);
uint32_t subdiv = next_power_of_2(p_subdivision);
uint32_t subdiv = next_power_of_2((uint32_t)p_subdivision);
if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer
subdiv <<= 1;
}
@@ -2365,7 +2365,7 @@ bool LightStorage::shadow_atlas_update_light(RID p_atlas, RID p_light_instance,
}
uint32_t quad_size = shadow_atlas->size >> 1;
int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage));
int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(uint32_t(quad_size * p_coverage)));
int valid_quadrants[4];
int valid_quadrant_count = 0;

View File

@@ -58,35 +58,35 @@ TEST_CASE("[Math] C++ macros") {
}
TEST_CASE("[Math] Power of two functions") {
CHECK(next_power_of_2(0) == 0);
CHECK(next_power_of_2(1) == 1);
CHECK(next_power_of_2(16) == 16);
CHECK(next_power_of_2(17) == 32);
CHECK(next_power_of_2(65535) == 65536);
CHECK(next_power_of_2((uint32_t)0) == 0);
CHECK(next_power_of_2((uint32_t)1) == 1);
CHECK(next_power_of_2((uint32_t)16) == 16);
CHECK(next_power_of_2((uint32_t)17) == 32);
CHECK(next_power_of_2((uint32_t)65535) == 65536);
CHECK(previous_power_of_2(0) == 0);
CHECK(previous_power_of_2(1) == 1);
CHECK(previous_power_of_2(16) == 16);
CHECK(previous_power_of_2(17) == 16);
CHECK(previous_power_of_2(65535) == 32768);
CHECK(previous_power_of_2((uint32_t)0) == 0);
CHECK(previous_power_of_2((uint32_t)1) == 1);
CHECK(previous_power_of_2((uint32_t)16) == 16);
CHECK(previous_power_of_2((uint32_t)17) == 16);
CHECK(previous_power_of_2((uint32_t)65535) == 32768);
CHECK(closest_power_of_2(0) == 0);
CHECK(closest_power_of_2(1) == 1);
CHECK(closest_power_of_2(16) == 16);
CHECK(closest_power_of_2(17) == 16);
CHECK(closest_power_of_2(65535) == 65536);
CHECK(closest_power_of_2((uint32_t)0) == 0);
CHECK(closest_power_of_2((uint32_t)1) == 1);
CHECK(closest_power_of_2((uint32_t)16) == 16);
CHECK(closest_power_of_2((uint32_t)17) == 16);
CHECK(closest_power_of_2((uint32_t)65535) == 65536);
CHECK(get_shift_from_power_of_2(0) == -1);
CHECK(get_shift_from_power_of_2(1) == 0);
CHECK(get_shift_from_power_of_2(16) == 4);
CHECK(get_shift_from_power_of_2(17) == -1);
CHECK(get_shift_from_power_of_2(65535) == -1);
CHECK(get_shift_from_power_of_2((uint32_t)0) == -1);
CHECK(get_shift_from_power_of_2((uint32_t)1) == 0);
CHECK(get_shift_from_power_of_2((uint32_t)16) == 4);
CHECK(get_shift_from_power_of_2((uint32_t)17) == -1);
CHECK(get_shift_from_power_of_2((uint32_t)65535) == -1);
CHECK(nearest_shift(0) == 0);
CHECK(nearest_shift(1) == 1);
CHECK(nearest_shift(16) == 5);
CHECK(nearest_shift(17) == 5);
CHECK(nearest_shift(65535) == 16);
CHECK(nearest_shift((uint32_t)0) == 0);
CHECK(nearest_shift((uint32_t)1) == 1);
CHECK(nearest_shift((uint32_t)16) == 5);
CHECK(nearest_shift((uint32_t)17) == 5);
CHECK(nearest_shift((uint32_t)65535) == 16);
}
TEST_CASE_TEMPLATE("[Math] abs", T, int, float, double) {