diff --git a/Docs/ChangeLog-5x.md b/Docs/ChangeLog-5x.md index eb2f5bf9..234512e8 100644 --- a/Docs/ChangeLog-5x.md +++ b/Docs/ChangeLog-5x.md @@ -17,6 +17,8 @@ The 5.5.0 release is a minor maintenance release. * **Update:** Update stb_image to v1.30. * **Update:** Update Wuffs to v0.3.4. * **Update:** Update TinyEXR to v1.0.13. + * **Bug fix:** Core library now correctly detects LDR error blocks when + compiled for AVX2 and returns max magenta rather than black. * **Bug fix:** Front-end wrapper now uses C++ RAII to manage lifetime of memory and file handles, fixing a number of resource leaks when on an error handling path. diff --git a/Source/UnitTest/test_simd.cpp b/Source/UnitTest/test_simd.cpp index 00595162..b72563d1 100644 --- a/Source/UnitTest/test_simd.cpp +++ b/Source/UnitTest/test_simd.cpp @@ -462,6 +462,30 @@ TEST(SuiteVfloat4, swz2) EXPECT_EQ(r.lane<1>(), 2.0f); } +/** @brief Test vfloat4 eq. */ +TEST(SuiteVfloat4, veq) +{ + // NaN should not be equal for anything + vfloat4 a(qnan, qnan, qnan, qnan); + EXPECT_FALSE(any(a == a)); + + // Non-NaN should be equal for everything + vfloat4 b(0.0f, 0.2f, -0.0f, -0.4f); + EXPECT_TRUE(all(b == b)); +} + +/** @brief Test vfloat4 neq. */ +TEST(SuiteVfloat4, vneq) +{ + // NaN should be unequal for everything + vfloat4 a(qnan, qnan, qnan, qnan); + EXPECT_TRUE(all(a != a)); + + // Non-NaN should not be unequal for anything + vfloat4 b(0.0f, 0.2f, -0.0f, -0.4f); + EXPECT_FALSE(any(b != b)); +} + /** @brief Test vfloat4 add. */ TEST(SuiteVfloat4, vadd) { @@ -2166,6 +2190,30 @@ TEST(SuiteVfloat8, Loada) EXPECT_EQ(ra[7], 7.0f); } +/** @brief Test vfloat8 eq. */ +TEST(SuiteVfloat8, veq) +{ + // NaN should not be equal for anything + vfloat8 a = vfloat8_lit(qnan, qnan, qnan, qnan, qnan, qnan, qnan, qnan); + EXPECT_FALSE(any(a == a)); + + // Non-NaN should be equal for everything + vfloat8 b = vfloat8_lit(0.0f, 0.2f, -0.0f, -0.4f, 0.0f, 0.2f, -0.0f, -0.4f); + EXPECT_TRUE(all(b == b)); +} + +/** @brief Test vfloat8 neq. */ +TEST(SuiteVfloat8, vneq) +{ + // NaN should be unequal for everything + vfloat8 a = vfloat8_lit(qnan, qnan, qnan, qnan, qnan, qnan, qnan, qnan); + EXPECT_TRUE(all(a != a)); + + // Non-NaN should not be unequal for anything + vfloat8 b = vfloat8_lit(0.0f, 0.2f, -0.0f, -0.4f, 0.0f, 0.2f, -0.0f, -0.4f); + EXPECT_FALSE(any(b != b)); +} + /** @brief Test vfloat8 add. */ TEST(SuiteVfloat8, vadd) { diff --git a/Source/astcenc_vecmathlib_avx2_8.h b/Source/astcenc_vecmathlib_avx2_8.h index af4ecf78..8776b9cb 100644 --- a/Source/astcenc_vecmathlib_avx2_8.h +++ b/Source/astcenc_vecmathlib_avx2_8.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2019-2025 Arm Limited +// Copyright 2019-2026 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 @@ -640,6 +640,8 @@ ASTCENC_SIMD_INLINE vfloat8 operator/(float a, vfloat8 b) /** * @brief Overload: vector by vector equality. + * + * Returns vector of false mask values if a or b is NaN. */ ASTCENC_SIMD_INLINE vmask8 operator==(vfloat8 a, vfloat8 b) { @@ -648,10 +650,12 @@ ASTCENC_SIMD_INLINE vmask8 operator==(vfloat8 a, vfloat8 b) /** * @brief Overload: vector by vector inequality. + * + * Returns vector of true mask values if a or b is NaN. */ ASTCENC_SIMD_INLINE vmask8 operator!=(vfloat8 a, vfloat8 b) { - return vmask8(_mm256_cmp_ps(a.m, b.m, _CMP_NEQ_OQ)); + return vmask8(_mm256_cmp_ps(a.m, b.m, _CMP_NEQ_UQ)); } /** diff --git a/Source/astcenc_vecmathlib_neon_4.h b/Source/astcenc_vecmathlib_neon_4.h index f31063d9..73d47dc9 100644 --- a/Source/astcenc_vecmathlib_neon_4.h +++ b/Source/astcenc_vecmathlib_neon_4.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2019-2024 Arm Limited +// Copyright 2019-2026 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 @@ -674,6 +674,8 @@ ASTCENC_SIMD_INLINE vfloat4 operator/(vfloat4 a, vfloat4 b) /** * @brief Overload: vector by vector equality. + * + * Returns vector of false mask values if a or b is NaN. */ ASTCENC_SIMD_INLINE vmask4 operator==(vfloat4 a, vfloat4 b) { @@ -682,6 +684,8 @@ ASTCENC_SIMD_INLINE vmask4 operator==(vfloat4 a, vfloat4 b) /** * @brief Overload: vector by vector inequality. + * + * Returns vector of true mask values if a or b is NaN. */ ASTCENC_SIMD_INLINE vmask4 operator!=(vfloat4 a, vfloat4 b) { diff --git a/Source/astcenc_vecmathlib_none_4.h b/Source/astcenc_vecmathlib_none_4.h index 5c6a77eb..5e4157e0 100644 --- a/Source/astcenc_vecmathlib_none_4.h +++ b/Source/astcenc_vecmathlib_none_4.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2019-2025 Arm Limited +// Copyright 2019-2026 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 @@ -764,6 +764,8 @@ ASTCENC_SIMD_INLINE vfloat4 operator/(vfloat4 a, vfloat4 b) /** * @brief Overload: vector by vector equality. + * + * Returns vector of false mask values if a or b is NaN. */ ASTCENC_SIMD_INLINE vmask4 operator==(vfloat4 a, vfloat4 b) { @@ -775,6 +777,8 @@ ASTCENC_SIMD_INLINE vmask4 operator==(vfloat4 a, vfloat4 b) /** * @brief Overload: vector by vector inequality. + * + * Returns vector of true mask values if a or b is NaN. */ ASTCENC_SIMD_INLINE vmask4 operator!=(vfloat4 a, vfloat4 b) { diff --git a/Source/astcenc_vecmathlib_rvv_n.h b/Source/astcenc_vecmathlib_rvv_n.h index bb032f24..8c47ef86 100644 --- a/Source/astcenc_vecmathlib_rvv_n.h +++ b/Source/astcenc_vecmathlib_rvv_n.h @@ -648,6 +648,8 @@ ASTCENC_SIMD_INLINE vfloat operator/(float a, vfloat b) /** * @brief Overload: vector by vector equality. + * + * Returns vector of false mask values if a or b is NaN. */ ASTCENC_SIMD_INLINE vmask operator==(vfloat a, vfloat b) { @@ -656,6 +658,8 @@ ASTCENC_SIMD_INLINE vmask operator==(vfloat a, vfloat b) /** * @brief Overload: vector by vector inequality. + * + * Returns vector of true mask values if a or b is NaN. */ ASTCENC_SIMD_INLINE vmask operator!=(vfloat a, vfloat b) { diff --git a/Source/astcenc_vecmathlib_sse_4.h b/Source/astcenc_vecmathlib_sse_4.h index 7cf165b1..d91faa2e 100644 --- a/Source/astcenc_vecmathlib_sse_4.h +++ b/Source/astcenc_vecmathlib_sse_4.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2019-2024 Arm Limited +// Copyright 2019-2026 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 @@ -724,6 +724,8 @@ ASTCENC_SIMD_INLINE vfloat4 operator/(vfloat4 a, vfloat4 b) /** * @brief Overload: vector by vector equality. + * + * Returns vector of false mask values if a or b is NaN. */ ASTCENC_SIMD_INLINE vmask4 operator==(vfloat4 a, vfloat4 b) { @@ -732,6 +734,8 @@ ASTCENC_SIMD_INLINE vmask4 operator==(vfloat4 a, vfloat4 b) /** * @brief Overload: vector by vector inequality. + * + * Returns vector of true mask values if a or b is NaN. */ ASTCENC_SIMD_INLINE vmask4 operator!=(vfloat4 a, vfloat4 b) { diff --git a/Source/astcenc_vecmathlib_sve_8.h b/Source/astcenc_vecmathlib_sve_8.h index 9f18853f..4408c81b 100644 --- a/Source/astcenc_vecmathlib_sve_8.h +++ b/Source/astcenc_vecmathlib_sve_8.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2019-2024 Arm Limited +// Copyright 2019-2026 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 @@ -615,6 +615,8 @@ ASTCENC_SIMD_INLINE vfloat8 operator/(float a, vfloat8 b) /** * @brief Overload: vector by vector equality. + * + * Returns vector of false mask values if a or b is NaN. */ ASTCENC_SIMD_INLINE vmask8 operator==(vfloat8 a, vfloat8 b) { @@ -623,6 +625,8 @@ ASTCENC_SIMD_INLINE vmask8 operator==(vfloat8 a, vfloat8 b) /** * @brief Overload: vector by vector inequality. + * + * Returns vector of true mask values if a or b is NaN. */ ASTCENC_SIMD_INLINE vmask8 operator!=(vfloat8 a, vfloat8 b) {