Skip to content

Commit a3ed53e

Browse files
authored
Avoid type aliasing and UB in mspnr_operator (#578)
1 parent b62ac4f commit a3ed53e

File tree

2 files changed

+13
-7
lines changed

2 files changed

+13
-7
lines changed

Source/astcenc_color_unquantize.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static ASTCENC_SIMD_INLINE vint4 uncontract_color(
5353
*/
5454
static ASTCENC_SIMD_INLINE int32_t safe_signed_lsh(int32_t val, int shift)
5555
{
56-
// Future: When we support C++20 can swap memcpy for std::bitcast
56+
// Future: Can use std:bit_cast with C++20
5757
uint32_t uval;
5858
std::memcpy(&uval, &val, sizeof(uint32_t));
5959
uval <<= shift;

Source/astcenccli_error_metrics.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,19 @@ static float mpsnr_operator(
6868
float val,
6969
int fstop
7070
) {
71-
if32 p;
72-
p.u = 0x3f800000 + (fstop << 23); // 0x3f800000 is 1.0f
73-
val *= p.f;
74-
val = powf(val, (1.0f / 2.2f));
75-
val *= 255.0f;
71+
// Future: Can use std:bit_cast with C++20
7672

77-
return astc::clamp(val, 0.0f, 255.0f);
73+
// Fast implementation of pow(2.0, fstop), assuming IEEE float layout
74+
// Memcpy to uint avoids ubsan complaints shift of negative int
75+
unsigned int fstopu;
76+
std::memcpy(&fstopu, &fstop, sizeof(int));
77+
uint32_t uscale = 0x3f800000 + (fstopu << 23);
78+
79+
float scale;
80+
std::memcpy(&scale, &uscale, sizeof(float));
81+
82+
val = powf(val * scale, (1.0f / 2.2f));
83+
return astc::clamp(val * 255.0f, 0.0f, 255.0f);
7884
}
7985

8086
/**

0 commit comments

Comments
 (0)