From 42d858e67d4415a61389984f8b3d774a71c7d82a Mon Sep 17 00:00:00 2001 From: "J. Daniel Smith" Date: Mon, 24 Jul 2023 13:48:51 -0400 Subject: [PATCH] Squashed 'externals/coda-oss/' changes from 710754a00..5f1e5d353 5f1e5d353 Merge branch 'main' into cpp17 034d52c86 overloads to byte-swap type::Complex are too much trouble (#707) git-subtree-dir: externals/coda-oss git-subtree-split: 5f1e5d3537f7faeb92b3ca1b6849aa0d4d9e400d --- modules/c++/sys/include/sys/ByteSwap.h | 145 ++++--------------- modules/c++/sys/unittests/test_byte_swap.cpp | 42 +----- modules/c++/types/include/types/Complex.h | 29 ---- 3 files changed, 33 insertions(+), 183 deletions(-) diff --git a/modules/c++/sys/include/sys/ByteSwap.h b/modules/c++/sys/include/sys/ByteSwap.h index 4e26fb37d..67fd4f167 100644 --- a/modules/c++/sys/include/sys/ByteSwap.h +++ b/modules/c++/sys/include/sys/ByteSwap.h @@ -35,7 +35,6 @@ #include #include "config/Exports.h" -#include "types/Complex.h" #include "ByteSwapValue.h" #include "Runnable.h" @@ -89,48 +88,25 @@ inline void check_elemSize(size_t elemSize) // Repackage into a span; the size is 2* because for byte-swapping // we want to look at this as an array of `T`, not `std::complex`. -template -inline auto make_cx_span(coda_oss::span s) -{ - using value_type = typename TComplex::value_type; // i.e., T from std::complex - const void* const p_ = s.data(); - auto const p = static_cast(p_); - const auto sz = s.size() * 2; // real and imag - return sys::make_span(p, sz); -} -template -inline auto make_cx_span(coda_oss::span s) -{ - using value_type = typename TComplex::value_type; // i.e., T from std::complex - void* const p_ = s.data(); - auto const p = static_cast(p_); - const auto sz = s.size() * 2; // real and imag - return sys::make_span(p, sz); -} - template inline auto make_span(coda_oss::span> s) { static_assert(std::is_floating_point::value, "std::complex should use floating-point"); - return make_cx_span(s); + + const void* const p_ = s.data(); + auto const p = static_cast(p_); + const auto sz = s.size() * 2; // real and imag + return sys::make_span(p, sz); } template inline auto make_span(coda_oss::span> s) { static_assert(std::is_floating_point::value, "std::complex should use floating-point"); - return make_cx_span(s); -} -// Support our own complex type too :-(; it's used (too much) in SIX. -template -inline auto make_span(coda_oss::span> s) -{ - return make_cx_span(s); -} -template -inline auto make_span(coda_oss::span> s) -{ - return make_cx_span(s); + void* const p_ = s.data(); + auto const p = static_cast(p_); + const auto sz = s.size() * 2; // real and imag + return sys::make_span(p, sz); } } @@ -143,27 +119,14 @@ inline void byteSwap(T* buffer, size_t elemSize, size_t numElems) void* const buffer_ = buffer; byteSwap(buffer_, elemSize, numElems); } -namespace details -{ -template -inline void byteSwapCx(TComplex* buffer, size_t elemSize, size_t numElems) // dont't want `T` as `std::complex<...>` -{ - using value_type = typename TComplex::value_type; // i.e., T from std::complex - check_elemSize(elemSize); - void* const buffer_ = buffer; - byteSwap(buffer_, elemSize, numElems); -} -} template inline void byteSwap(std::complex* buffer, size_t elemSize, size_t numElems) // dont't want `T` as `std::complex<...>` { static_assert(std::is_floating_point::value, "std::complex should use floating-point"); - details::byteSwapCx(buffer, elemSize, numElems); -} -template -inline void byteSwap(types::Complex* buffer, size_t elemSize, size_t numElems) // dont't want `T` as `std::complex<...>` -{ - details::byteSwapCx(buffer, elemSize, numElems); + + details::check_elemSize(elemSize); + void* const buffer_ = buffer; + byteSwap(buffer_, elemSize, numElems); } template @@ -180,11 +143,6 @@ inline auto byteSwap(coda_oss::span> buffer) { return byteSwap(details::make_span(buffer)); } -template -inline auto byteSwap(coda_oss::span> buffer) -{ - return byteSwap(details::make_span(buffer)); -} /*! * Swap bytes into output buffer. Note that a complex pixel @@ -233,28 +191,15 @@ inline void byteSwap(const T* buffer, size_t elemSize, size_t numElems, U* outpu void* const outputBuffer_ = outputBuffer; byteSwap(buffer_, elemSize, numElems, outputBuffer_); } -namespace details -{ -template -inline void byteSwapCx(const TComplex* buffer, size_t elemSize, size_t numElems, U* outputBuffer) // dont't want `T` as `std::complex<...>` -{ - using value_type = typename TComplex::value_type; // i.e., T from std::complex - check_elemSize(elemSize); - const void* const buffer_ = buffer; - void* const outputBuffer_ = outputBuffer; - byteSwap(buffer_, elemSize, numElems, outputBuffer_); -} -} template inline void byteSwap(const std::complex* buffer, size_t elemSize, size_t numElems, U* outputBuffer) // dont't want `T` as `std::complex<...>` { static_assert(std::is_floating_point::value, "std::complex should use floating-point"); - details::byteSwapCx(buffer, elemSize, numElems, outputBuffer); -} -template -inline void byteSwap(const types::Complex* buffer, size_t elemSize, size_t numElems, U* outputBuffer) // dont't want `T` as `std::complex<...>` -{ - details::byteSwapCx(buffer, elemSize, numElems, outputBuffer); + + details::check_elemSize(elemSize); + const void* const buffer_ = buffer; + void* const outputBuffer_ = outputBuffer; + byteSwap(buffer_, elemSize, numElems, outputBuffer_); } template @@ -269,11 +214,6 @@ inline auto byteSwap(coda_oss::span> buffer, coda_oss::spa { return byteSwap(details::make_span(buffer), outputBuffer); } -template -inline auto byteSwap(coda_oss::span> buffer, coda_oss::span outputBuffer) -{ - return byteSwap(details::make_span(buffer), outputBuffer); -} template inline auto byteSwap(coda_oss::span buffer) @@ -288,62 +228,29 @@ inline auto byteSwap(coda_oss::span> buffer) { return byteSwap(details::make_span(buffer)); } -template -inline auto byteSwap(coda_oss::span> buffer) -{ - return byteSwap(details::make_span(buffer)); -} // With buffer byte-swap now in place, we can safely byte-swap std::complex. // This signature is from ByteSwapValue.h -namespace details -{ -template -inline auto byteSwapCxValue(TComplex z) -{ - using value_type = typename TComplex::value_type; // i.e., T from std::complex - - // C++ mandates that `std::complex` be the same as `T cx[2]`; that is - // the structure is contiguous. https://en.cppreference.com/w/cpp/numeric/complex - const auto& z_ = reinterpret_cast(z); - return byteSwap(sys::make_span(z_)); -} -} template inline auto byteSwapValue(std::complex z) { static_assert(std::is_floating_point::value, "std::complex should use floating-point"); - return details::byteSwapCxValue(z); -} -template -inline auto byteSwapValue(types::Complex z) -{ - return details::byteSwapCxValue(z); + + // C++ mandates that `std::complex` be the same as `T cx[2]`; that is + // the structure is contiguous. https://en.cppreference.com/w/cpp/numeric/complex + const auto& z_ = reinterpret_cast(z); + return byteSwap(make_span(z_)); } -namespace details -{ -template -inline auto byteSwapCx(TComplex val) +template +inline auto byteSwap(std::complex val) { const auto bytes = byteSwapValue(val); assert(bytes.size() == sizeof(val)); const void* const pBytes = bytes.data(); - auto const pRetVal = static_cast(pBytes); + auto const pRetVal = static_cast*>(pBytes); return *pRetVal; } -} -template -inline auto byteSwap(std::complex val) -{ - return details::byteSwapCx(val); -} -template -inline auto byteSwap(types::Complex val) -{ - return details::byteSwapCx(val); -} - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/c++/sys/unittests/test_byte_swap.cpp b/modules/c++/sys/unittests/test_byte_swap.cpp index 51591a3b7..2d784428b 100644 --- a/modules/c++/sys/unittests/test_byte_swap.cpp +++ b/modules/c++/sys/unittests/test_byte_swap.cpp @@ -245,43 +245,15 @@ TEST_CASE(testByteSwapValues) TEST_CASE(testByteSwapCxValue) { - { - using value_type = std::complex; - const value_type cx{3.14f, -31.4f}; // using raw bytes can lean to `nan`s - auto const pValue = &cx; + using value_type = std::complex; + const value_type cx{3.14f, -31.4f}; // using raw bytes can lean to `nan`s + auto const pValue = &cx; - auto swap = sys::byteSwap(*pValue); - TEST_ASSERT_NOT_EQ(*pValue, swap); // technically a bit goofy as the bits may not represent `T`s + auto swap = sys::byteSwap(*pValue); + TEST_ASSERT_NOT_EQ(*pValue, swap); // technically a bit goofy as the bits may not represent `T`s - swap = sys::byteSwap(swap); // swap back - TEST_ASSERT_EQ(*pValue, swap); - } - { - using value_type = types::Complex; - const void* const pValue_ = four_bytes; // two int16_t - auto const pValue = static_cast(pValue_); - - auto swap = sys::byteSwap(*pValue); - TEST_ASSERT_NOT_EQ(*pValue, swap); - - // .real() and .imag() are swapped individually - const void* const pSwap_ = &swap; - auto pSwapBytes = static_cast(pSwap_); - TEST_ASSERT(four_bytes[0] == pSwapBytes[1]); - TEST_ASSERT(four_bytes[1] == pSwapBytes[0]); - TEST_ASSERT(four_bytes[2] == pSwapBytes[3]); - TEST_ASSERT(four_bytes[3] == pSwapBytes[2]); - - swap = sys::byteSwap(swap); // swap back - TEST_ASSERT_EQ(*pValue, swap); - - auto buffer = std::as_writable_bytes(sys::make_span(&swap, 1)); - sys::byteSwap(sys::make_span(pValue, 1), buffer); - TEST_ASSERT(four_bytes[0] == buffer[1]); - TEST_ASSERT(four_bytes[1] == buffer[0]); - TEST_ASSERT(four_bytes[2] == buffer[3]); - TEST_ASSERT(four_bytes[3] == buffer[2]); - } + swap = sys::byteSwap(swap); // swap back + TEST_ASSERT_EQ(*pValue, swap); } TEST_CASE(testByteSwap12) diff --git a/modules/c++/types/include/types/Complex.h b/modules/c++/types/include/types/Complex.h index 8b2218ff4..cefa90a83 100644 --- a/modules/c++/types/include/types/Complex.h +++ b/modules/c++/types/include/types/Complex.h @@ -165,37 +165,8 @@ inline auto abs(const Complex& z) // https://en.cppreference.com/w/cpp/numeri return abs(details::cast(z)); } -// Control whether ComplexInteger is std::complex or Complex. -// If it is std::complex, then a types::ComplexInteger overload normally can't be -// used as it will be the same as std::complex -#ifdef CODA_OSS_types_FORCE_unique_ComplexInteger // bypass checks below -#define CODA_OSS_types_unique_ComplexInteger 1 -#endif -#ifdef CODA_OSS_types_NO_unique_ComplexInteger -#ifdef CODA_OSS_types_unique_ComplexInteger -#error "CODA_OSS_types_unique_ComplexInteger already #define'd" -#endif -#define CODA_OSS_types_unique_ComplexInteger 0 -#endif - -#ifndef CODA_OSS_types_unique_ComplexInteger -// If the warning about using std::complex has been turned off, we might -// as well use std:complex. -#ifdef _SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING -#define CODA_OSS_types_unique_ComplexInteger 0 -#endif -#endif - -#ifndef CODA_OSS_types_unique_ComplexInteger -#define CODA_OSS_types_unique_ComplexInteger 1 -#endif - template -#if CODA_OSS_types_unique_ComplexInteger using ComplexInteger = Complex; -#else -using ComplexInteger = std::complex; -#endif namespace details {