Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*.o
*.a
__pycache__
pve
Scratch
Proto

Expand Down
9 changes: 3 additions & 6 deletions Source/astcenc_color_unquantize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,11 @@ static ASTCENC_SIMD_INLINE vint4 uncontract_color(
*
* @return The shifted value.
*/
static ASTCENC_SIMD_INLINE int32_t safe_signed_lsh(int32_t val, int shift)
static ASTCENC_SIMD_INLINE int safe_signed_lsh(int val, int shift)
{
// Future: Can use std:bit_cast with C++20
uint32_t uval;
std::memcpy(&uval, &val, sizeof(uint32_t));
unsigned int uval = astc::int_as_uint(val);
uval <<= shift;
std::memcpy(&val, &uval, sizeof(uint32_t));
return val;
return astc::uint_as_int(uval);
}

void rgba_delta_unpack(
Expand Down
6 changes: 2 additions & 4 deletions Source/astcenc_decompress_symbolic.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
// Copyright 2011-2024 Arm Limited
// Copyright 2011-2025 Arm Limited
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
Expand Down Expand Up @@ -163,9 +163,7 @@ void unpack_weights(
*/
static float error_color_nan()
{
if32 v;
v.u = 0xFFFFE000U;
return v.f;
return astc::uint_as_float(0xFFFFE000u);
}

/* See header for documentation. */
Expand Down
16 changes: 8 additions & 8 deletions Source/astcenc_entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,19 +136,19 @@ static const std::array<astcenc_preset_config, 6> preset_configs_low {{
/**
* @brief Validate CPU floating point meets assumptions made in the codec.
*
* The codec is written with the assumption that a float threaded through the @c if32 union will be
* stored and reloaded as a 32-bit IEEE-754 float with round-to-nearest rounding. This is always the
* case in an IEEE-754 compliant system, however not every system or compilation mode is actually
* IEEE-754 compliant. This normally fails if the code is compiled with fast math enabled.
* The codec is written with the assumption that float bit patterns are valid
* IEEE754 values that are stored and reloaded with round-to-nearest rounding.
* This is always the case in an IEEE-754 compliant system, however not every
* system or compilation mode is actually IEEE-754 compliant. This normally
* fails if the code is compiled with fast math enabled, for example.
*
* @return Return @c ASTCENC_SUCCESS if validated, otherwise an error on failure.
* @return Return @c ASTCENC_SUCCESS if validated, an error on failure.
*/
static astcenc_error validate_cpu_float()
{
if32 p;
volatile float xprec_testval = 2.51f;
p.f = xprec_testval + 12582912.0f;
float q = p.f - 12582912.0f;
float store = xprec_testval + 12582912.0f;
float q = store - 12582912.0f;

if (q != 3.0f)
{
Expand Down
92 changes: 73 additions & 19 deletions Source/astcenc_mathlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <cassert>
#include <cstdint>
#include <cmath>
#include <cstring>

#ifndef ASTCENC_POPCNT
#if defined(__POPCNT__)
Expand Down Expand Up @@ -123,14 +124,6 @@
to future vectorization.
============================================================================ */

// Union for manipulation of float bit patterns
typedef union
{
uint32_t u;
int32_t s;
float f;
} if32;

// These are namespaced to avoid colliding with C standard library functions.
namespace astc
{
Expand Down Expand Up @@ -359,9 +352,10 @@ static inline int flt2int_rd(float v)
*/
static inline int float_as_int(float v)
{
union { int a; float b; } u;
u.b = v;
return u.a;
// Future: Can use std:bit_cast with C++20
int iv;
std::memcpy(&iv, &v, sizeof(float));
return iv;
}

/**
Expand All @@ -373,9 +367,70 @@ static inline int float_as_int(float v)
*/
static inline float int_as_float(int v)
{
union { int a; float b; } u;
u.a = v;
return u.b;
// Future: Can use std:bit_cast with C++20
float fv;
std::memcpy(&fv, &v, sizeof(int));
return fv;
}

/**
* @brief SP float bit-interpreted as an unsigned integer.
*
* @param v The value to bitcast.
*
* @return The converted value.
*/
static inline unsigned int float_as_uint(float v)
{
// Future: Can use std:bit_cast with C++20
unsigned int iv;
std::memcpy(&iv, &v, sizeof(float));
return iv;
}

/**
* @brief Unsigned integer bit-interpreted as an SP float.
*
* @param v The value to bitcast.
*
* @return The converted value.
*/
static inline float uint_as_float(unsigned int v)
{
// Future: Can use std:bit_cast with C++20
float fv;
std::memcpy(&fv, &v, sizeof(unsigned int));
return fv;
}

/**
* @brief Signed int bit-interpreted as an unsigned integer.
*
* @param v The value to bitcast.
*
* @return The converted value.
*/
static inline unsigned int int_as_uint(int v)
{
// Future: Can use std:bit_cast with C++20
unsigned int uv;
std::memcpy(&uv, &v, sizeof(int));
return uv;
}

/**
* @brief Unsigned integer bit-interpreted as a signed integer.
*
* @param v The value to bitcast.
*
* @return The converted value.
*/
static inline int uint_as_int(unsigned int v)
{
// Future: Can use std:bit_cast with C++20git p
int sv;
std::memcpy(&sv, &v, sizeof(unsigned int));
return sv;
}

/**
Expand Down Expand Up @@ -412,11 +467,10 @@ static inline float sqrt(float v)
*/
static inline float frexp(float v, int* expo)
{
if32 p;
p.f = v;
*expo = ((p.u >> 23) & 0xFF) - 126;
p.u = (p.u & 0x807fffff) | 0x3f000000;
return p.f;
unsigned int iv = astc::float_as_uint(v);
*expo = ((iv >> 23) & 0xFF) - 126;
iv = (iv & 0x807fffff) | 0x3f000000;
return astc::uint_as_float(iv);
}

/**
Expand Down
9 changes: 3 additions & 6 deletions Source/astcenc_mathlib_softfloat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,17 +395,14 @@ static sf16 sf32_to_sf16(sf32 inp, roundmode rmode)
/* convert from soft-float to native-float */
float sf16_to_float(uint16_t p)
{
if32 i;
i.u = sf16_to_sf32(p);
return i.f;
return astc::uint_as_float(sf16_to_sf32(p));
}

/* convert from native-float to soft-float */
uint16_t float_to_sf16(float p)
{
if32 i;
i.f = p;
return sf32_to_sf16(i.u, SF_NEARESTEVEN);
unsigned int ip = astc::float_as_uint(p);
return sf32_to_sf16(ip, SF_NEARESTEVEN);
}

#endif
10 changes: 2 additions & 8 deletions Source/astcenccli_error_metrics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,10 @@ static float mpsnr_operator(
float val,
int fstop
) {
// Future: Can use std:bit_cast with C++20

// Fast implementation of pow(2.0, fstop), assuming IEEE float layout
// Memcpy to uint avoids ubsan complaints shift of negative int
unsigned int fstopu;
std::memcpy(&fstopu, &fstop, sizeof(int));
uint32_t uscale = 0x3f800000 + (fstopu << 23);

float scale;
std::memcpy(&scale, &uscale, sizeof(float));
unsigned int uscale = 0x3f800000u + (astc::int_as_uint(fstop) << 23);
float scale = astc::uint_as_float(uscale);

val = powf(val * scale, (1.0f / 2.2f));
return astc::clamp(val * 255.0f, 0.0f, 255.0f);
Expand Down
13 changes: 9 additions & 4 deletions Source/cmake_core.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -189,21 +189,26 @@ macro(astcenc_set_properties ASTCENC_TARGET_NAME ASTCENC_VENEER_TYPE)
if(${ASTCENC_ASAN})
target_compile_options(${ASTCENC_TARGET_NAME}
PRIVATE
$<${is_gnu_fe}:-fsanitize=address>)
$<${is_gnu_fe}:-fsanitize=address>
$<${is_gnu_fe}:-fno-sanitize-recover=all>)

target_link_options(${ASTCENC_TARGET_NAME}
PRIVATE
$<${is_gnu_fe}:-fsanitize=address>)
$<${is_gnu_fe}:-fsanitize=address>
$<${is_clang}:-fuse-ld=lld>)

endif()

if(${ASTCENC_UBSAN})
target_compile_options(${ASTCENC_TARGET_NAME}
PRIVATE
$<${is_gnu_fe}:-fsanitize=undefined>)
$<${is_gnu_fe}:-fsanitize=undefined>
$<${is_gnu_fe}:-fno-sanitize-recover=all>)

target_link_options(${ASTCENC_TARGET_NAME}
PRIVATE
$<${is_gnu_fe}:-fsanitize=undefined>)
$<${is_gnu_fe}:-fsanitize=undefined>
$<${is_clang}:-fuse-ld=lld>)
endif()

if(NOT ${ASTCENC_INVARIANCE})
Expand Down