diff --git a/externals/nitro/externals/coda-oss/modules/c++/sys/include/sys/ByteSwap.h b/externals/nitro/externals/coda-oss/modules/c++/sys/include/sys/ByteSwap.h deleted file mode 100644 index 67fd4f167..000000000 --- a/externals/nitro/externals/coda-oss/modules/c++/sys/include/sys/ByteSwap.h +++ /dev/null @@ -1,308 +0,0 @@ -/* ========================================================================= - * This file is part of sys-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2014, MDA Information Systems LLC - * (C) Copyright 2023, Maxar Technologies, Inc. - * - * sys-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#pragma once -#ifndef CODA_OSS_sys_ByteSwap_h_INCLUDED_ -#define CODA_OSS_sys_ByteSwap_h_INCLUDED_ - -#include -#include - -#include -#include -#include -#include -#include - -#include "config/Exports.h" - -#include "ByteSwapValue.h" -#include "Runnable.h" -#include "SysInt.h" - -namespace sys -{ -/*! - * Swap bytes in-place. Note that a complex pixel - * is equivalent to two floats so elemSize and numElems - * must be adjusted accordingly. - * - * \param [inout] buffer to transform - * \param elemSize - * \param numElems - */ -coda_oss::span CODA_OSS_API byteSwap(coda_oss::spanbuffer, size_t elemSize); -void CODA_OSS_API byteSwap(void* buffer, size_t elemSize, size_t numElems); - -// If the caller has given us bytes, assume she knows what she's doing; i.e., don't check sizeof(T) -template -inline void byteSwap_(TByte* buffer, size_t elemSize, size_t numElems) -{ - void* const buffer_ = buffer; - byteSwap(buffer_, elemSize, numElems); -} -inline void byteSwap(coda_oss::byte* buffer, size_t elemSize, size_t numElems) -{ - return byteSwap_(buffer, elemSize, numElems); -} -inline void byteSwap(byte* buffer, size_t elemSize, size_t numElems) -{ - return byteSwap_(buffer, elemSize, numElems); -} -inline void byteSwap(ubyte* buffer, size_t elemSize, size_t numElems) -{ - return byteSwap_(buffer, elemSize, numElems); -} - -namespace details -{ -template -inline void check_elemSize(size_t elemSize) -{ - static_assert(is_byte_swappable(), "T should not be a 'struct'"); - if (sizeof(T) != elemSize) - { - throw std::invalid_argument("'elemSize' != sizeof(T)"); - } -} - -// 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_span(coda_oss::span> s) -{ - static_assert(std::is_floating_point::value, "std::complex should use floating-point"); - - 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"); - - 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); -} - -} - -// Otherwise, we can sanity-check the `elemSize` parameter -template -inline void byteSwap(T* buffer, size_t elemSize, size_t numElems) -{ - details::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::check_elemSize(elemSize); - void* const buffer_ = buffer; - byteSwap(buffer_, elemSize, numElems); -} - -template -inline auto byteSwap(coda_oss::span buffer) -{ - static_assert(!std::is_const::value, "T cannot be 'const'"); - static_assert(details::is_byte_swappable(), "T should not be a 'struct'"); - return byteSwap(as_writable_bytes(buffer), sizeof(T)); -} - -// Take care of treating std::complex as T[] -template -inline auto byteSwap(coda_oss::span> buffer) -{ - return byteSwap(details::make_span(buffer)); -} - -/*! - * Swap bytes into output buffer. Note that a complex pixel - * is equivalent to two floats so elemSize and numElems - * must be adjusted accordingly. - * - * \param buffer to transform - * \param elemSize - * \param numElems - * \param[out] outputBuffer buffer to write swapped elements to - */ -coda_oss::span CODA_OSS_API byteSwap(coda_oss::span buffer, - size_t elemSize, coda_oss::span outputBuffer); -void CODA_OSS_API byteSwap(const void* buffer, size_t elemSize, size_t numElems, void* outputBuffer); - -// If the caller has given us bytes, assume she knows what she's doing; i.e., don't check sizeof(T) -template -inline void byteSwap_(const TByte* buffer, size_t elemSize, size_t numElems, U* outputBuffer) -{ - const void* const buffer_ = buffer; - void* const outputBuffer_ = outputBuffer; - byteSwap(buffer_, elemSize, numElems, outputBuffer_); -} -template -inline void byteSwap(const coda_oss::byte* buffer, size_t elemSize, size_t numElems, U* outputBuffer) -{ - byteSwap_(buffer, elemSize, numElems, outputBuffer); -} -template -inline void byteSwap(const byte* buffer, size_t elemSize, size_t numElems, U* outputBuffer) -{ - byteSwap_(buffer, elemSize, numElems, outputBuffer); -} -template -inline void byteSwap(const ubyte* buffer, size_t elemSize, size_t numElems, U* outputBuffer) -{ - byteSwap_(buffer, elemSize, numElems, outputBuffer); -} - -// Otherwise, we can sanity-check the `elemSize` parameter -template -inline void byteSwap(const T* buffer, size_t elemSize, size_t numElems, U* outputBuffer) -{ - details::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::check_elemSize(elemSize); - const void* const buffer_ = buffer; - void* const outputBuffer_ = outputBuffer; - byteSwap(buffer_, elemSize, numElems, outputBuffer_); -} - -template -inline auto byteSwap(coda_oss::span buffer, coda_oss::span outputBuffer) -{ - static_assert(details::is_byte_swappable(), "T should not be a 'struct'"); - return byteSwap(as_bytes(buffer), sizeof(T), outputBuffer); -} -// Take care of treating std::complex as T[] -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) -{ - std::vector retval(buffer.size_bytes()); - std::ignore = byteSwap(buffer, make_span(retval)); - return retval; -} -// Take care of treating std::complex as T[] -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 -template -inline auto byteSwapValue(std::complex z) -{ - static_assert(std::is_floating_point::value, "std::complex should use floating-point"); - - // 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_)); -} -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); - return *pRetVal; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -struct ByteSwapRunnable final : public sys::Runnable -{ - ByteSwapRunnable(void* buffer, size_t elemSize, size_t startElement, size_t numElements) noexcept : - mBuffer(static_cast(buffer) + startElement * elemSize), - mElemSize(elemSize), mNumElements(numElements) - { - } - void run() override - { - byteSwap(mBuffer, mElemSize, mNumElements); - } - - virtual ~ByteSwapRunnable() = default; - ByteSwapRunnable(const ByteSwapRunnable&) = delete; - ByteSwapRunnable& operator=(const ByteSwapRunnable&) = delete; - ByteSwapRunnable(ByteSwapRunnable&&) = delete; - ByteSwapRunnable& operator=(ByteSwapRunnable&&) = delete; - -private: - void* const mBuffer; - const size_t mElemSize; - const size_t mNumElements; -}; - -struct ByteSwapCopyRunnable final : public sys::Runnable -{ - ByteSwapCopyRunnable(const void* buffer, size_t elemSize, size_t startElement, size_t numElements, void* outputBuffer) noexcept : - mBuffer(static_cast(buffer) + startElement * elemSize), - mElemSize(elemSize), mNumElements(numElements), - mOutputBuffer(static_cast(outputBuffer) + startElement * elemSize) - { - } - void run() override - { - byteSwap(mBuffer, mElemSize, mNumElements, mOutputBuffer); - } - - virtual ~ByteSwapCopyRunnable() = default; - ByteSwapCopyRunnable(const ByteSwapCopyRunnable&) = delete; - ByteSwapCopyRunnable& operator=(const ByteSwapCopyRunnable&) = delete; - ByteSwapCopyRunnable(ByteSwapCopyRunnable&&) = delete; - ByteSwapCopyRunnable& operator=(ByteSwapCopyRunnable&&) = delete; - -private: - const void* const mBuffer; - const size_t mElemSize; - const size_t mNumElements; - void* const mOutputBuffer; -}; - -} -#endif // CODA_OSS_sys_ByteSwap_h_INCLUDED_ diff --git a/externals/nitro/externals/coda-oss/modules/c++/sys/unittests/test_byte_swap.cpp b/externals/nitro/externals/coda-oss/modules/c++/sys/unittests/test_byte_swap.cpp deleted file mode 100644 index 2d784428b..000000000 --- a/externals/nitro/externals/coda-oss/modules/c++/sys/unittests/test_byte_swap.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/* ========================================================================= - * This file is part of sys-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2017, MDA Information Systems LLC - * - * sys-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#include "TestCase.h" - -#include -#include -#include // std::endian -#include -#include -#include - -#include -#include - -TEST_CASE(testEndianness) -{ - /*const*/ auto native = std::endian::native; // "const" causes "conditional expression is constant." - - if (native == std::endian::big) { } - else if (native == std::endian::little) { } - else - { - TEST_FAIL_MSG("Mixed-endian not supported!"); - } - - const bool isBigEndianSystem = sys::isBigEndianSystem(); - - if (native == std::endian::big) - { - TEST_ASSERT(isBigEndianSystem); - } - else - { - TEST_ASSERT(!isBigEndianSystem); - } - if (native == std::endian::little) - { - TEST_ASSERT(!isBigEndianSystem); - } - else - { - TEST_ASSERT(isBigEndianSystem); - } - - - if (isBigEndianSystem) - { - TEST_ASSERT(native == std::endian::big); - } - else - { - TEST_ASSERT(native == std::endian::little); - } -} - -template -static std::vector make_origValues(size_t NUM_PIXELS) -{ - ::srand(334); - - std::vector retval(NUM_PIXELS); - for (size_t ii = 0; ii < NUM_PIXELS; ++ii) - { - const auto value = static_cast(::rand()) / RAND_MAX * - std::numeric_limits::max(); - retval[ii] = static_cast(value); - } - return retval; -} - -TEST_CASE(testByteSwapV) -{ - constexpr size_t NUM_PIXELS = 10000; - const auto origValues = make_origValues (NUM_PIXELS); - - // Byte swap the old-fashioned way - auto values1(origValues); - sys::byteSwap(values1.data(), sizeof(uint64_t), NUM_PIXELS); - - // Byte swap into output buffer - std::vector swappedValues2(origValues.size()); - sys::byteSwap(origValues.data(), sizeof(uint64_t), NUM_PIXELS, swappedValues2.data()); - - // Everything should match - for (size_t ii = 0; ii < NUM_PIXELS; ++ii) - { - TEST_ASSERT_EQ(values1[ii], swappedValues2[ii]); - } -} - -TEST_CASE(testByteSwapCxV) -{ - constexpr size_t NUM_PIXELS = 10000; - using value_type = std::complex; - const auto origValues = make_origValues(NUM_PIXELS); - - constexpr auto elemSize = sizeof(value_type) / 2; - constexpr auto numElems = NUM_PIXELS * 2; - - // Byte swap the old-fashioned way - auto values1(origValues); - sys::byteSwap(values1.data(), elemSize, numElems); - - // Byte swap into output buffer - std::vector swappedValues2(origValues.size()); - sys::byteSwap(origValues.data(), elemSize, numElems, swappedValues2.data()); - - // Everything should match - for (size_t ii = 0; ii < NUM_PIXELS; ++ii) - { - using int_type = uint64_t; - static_assert(sizeof(int_type) == sizeof(value_type), "Unknown sizeof(std::complex)"); - - // If these values are byte-swapped, they could be bogus. - const void* const pValue1_ = &(values1[ii]); - const void* const pSwappedValue2_ = &(swappedValues2[ii]); - - auto const pValue1 = static_cast(pValue1_); - auto const pSwappedValue2 = static_cast(pSwappedValue2_); - - TEST_ASSERT_EQ(*pValue1, *pSwappedValue2); - } -} - -template -inline std::span as_span(const std::vector& bytes) -{ - const void* const pBytes_ = bytes.data(); - auto const p = static_cast(pBytes_); - const auto sz = bytes.size() / sizeof(T); - return sys::make_span(p, sz); -} - -TEST_CASE(testByteSwap) -{ - constexpr size_t NUM_PIXELS = 10000; - const auto origValues = make_origValues(NUM_PIXELS); - const auto origValues_ = sys::make_span(origValues); - - auto values1(origValues); - sys::byteSwap(sys::make_span(values1)); - - // Byte swap into output buffer - std::vector swappedValues2(origValues.size()); - sys::byteSwap(origValues_, sys::as_writable_bytes(swappedValues2)); - - // std::vector returned - const auto swappedValues3_ = sys::byteSwap(origValues_); - const auto swappedValues3 = as_span(swappedValues3_); - - // Everything should match - for (size_t ii = 0; ii < NUM_PIXELS; ++ii) - { - TEST_ASSERT_EQ(values1[ii], swappedValues2[ii]); - TEST_ASSERT_EQ(values1[ii], swappedValues3[ii]); - } -} - -// 0xnn is an `int` which can't be used to initialize std::byte w/o a cast -#define CODA_OSS_define_byte(v) constexpr static std::byte v = static_cast(0 ## v) -CODA_OSS_define_byte(x00); -CODA_OSS_define_byte(x11); -CODA_OSS_define_byte(x22); -CODA_OSS_define_byte(x33); -CODA_OSS_define_byte(x44); -CODA_OSS_define_byte(x55); -CODA_OSS_define_byte(x66); -CODA_OSS_define_byte(x77); -CODA_OSS_define_byte(x88); -CODA_OSS_define_byte(x99); -CODA_OSS_define_byte(xAA); -CODA_OSS_define_byte(xBB); -CODA_OSS_define_byte(xCC); -CODA_OSS_define_byte(xDD); -CODA_OSS_define_byte(xEE); -CODA_OSS_define_byte(xFF); -#undef CODA_OSS_define_byte - -static constexpr std::byte two_bytes[]{x00, xFF}; -static constexpr std::byte four_bytes[]{x00, x11, xEE, xFF}; -static constexpr std::byte eight_bytes[]{x00, x11, x22, x33, xCC, xDD, xEE, xFF}; -static constexpr std::byte sixteen_bytes[]{x00, x11, x22, x33, x44, x55, x66, x77, x88, x99, xAA, xBB, xCC, xDD, xEE, xFF}; - -template -static void test_assert_eq_swapped(const std::string& testName, size_t sz, - const TByteSpanLike1& pValueBytes, const TByteSpanLike2& pResultBytes) -{ - for (size_t i = 0, j = sz; i < sz && j > 0; i++, j--) - { - TEST_ASSERT(pResultBytes[i] == pValueBytes[j - 1]); - } -} - -template -static void testByteSwapValues_(const std::string& testName, const void* pBytes) -{ - auto pUInt = static_cast(pBytes); - auto swap = sys::byteSwap(*pUInt); - TEST_ASSERT_NOT_EQ(*pUInt, swap); - - const void* pResult_ = &swap; - auto const pResultBytes = static_cast(pResult_); - auto const pValueBytes = static_cast(pBytes); - test_assert_eq_swapped(testName, sizeof(TUInt), pResultBytes, pValueBytes); - - swap = sys::byteSwap(swap); // swap back - TEST_ASSERT_EQ(*pUInt, swap); - - // swap as an "array" of one value - sys::byteSwap(pUInt, sizeof(TUInt), 1, &swap); - TEST_ASSERT_NOT_EQ(*pUInt, swap); - sys::byteSwap(&swap, sizeof(TUInt), 1); // swap back - TEST_ASSERT_EQ(*pUInt, swap); - - const auto resultBytes = sys::byteSwapValue(*pUInt); - TEST_ASSERT_EQ(resultBytes.size(), sizeof(TUInt)); - test_assert_eq_swapped(testName, sizeof(TUInt), resultBytes.data(), pValueBytes); -} -TEST_CASE(testByteSwapValues) -{ - testByteSwapValues_(testName, two_bytes); - testByteSwapValues_(testName, four_bytes); - testByteSwapValues_(testName, eight_bytes); -} - -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; - - 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); -} - -TEST_CASE(testByteSwap12) -{ - // test a goofy element size - constexpr std::byte twelve_bytes[]{ - x00, x11, x22, x33, x44, x55, - x99, xAA, xBB, xDD, xEE, xFF}; - const auto pValueBytes = sys::as_bytes(twelve_bytes); - constexpr auto extent_twelve_bytes = std::extent::value; - - std::vector swappedValues(extent_twelve_bytes); - auto pResultBytes = sys::make_span(swappedValues); - - auto elemSize = 12; - auto numElements = swappedValues.size() / elemSize; - sys::byteSwap(twelve_bytes, elemSize, numElements, pResultBytes.data()); - test_assert_eq_swapped(testName, elemSize, pResultBytes, pValueBytes); - - // swap as a SINGLE 12-byte value - const auto result = sys::details::swapBytes(pValueBytes, pResultBytes); - test_assert_eq_swapped(testName, elemSize, result, pValueBytes); - - elemSize = 6; // note that an ODD size doesn't work correctly - numElements = swappedValues.size() / elemSize; - sys::byteSwap(twelve_bytes, elemSize, numElements, swappedValues.data()); - test_assert_eq_swapped(testName, elemSize, &(pResultBytes[0]), &(pValueBytes[0])); - test_assert_eq_swapped(testName, elemSize, &(pResultBytes[6]), &(pValueBytes[6])); - - sys::byteSwap(swappedValues.data(), elemSize, numElements); // swap back - for (size_t i = 0; i < swappedValues.size(); i++) - { - TEST_ASSERT(pResultBytes[i] == pValueBytes[i]); - } -} - -template -static inline void six_byteSwap(const void* in, T& out) -{ - auto const inBytes = sys::make_span(in, sizeof(T)); - out = sys::byteSwapValue(inBytes); -} -TEST_CASE(testSixByteSwap) -{ - const int i = 123; - int i_swapped; - six_byteSwap(&i, i_swapped); - TEST_ASSERT_NOT_EQ(i, i_swapped); - - int result; - six_byteSwap(&i_swapped, result); - TEST_ASSERT_EQ(i, result); -} - -TEST_MAIN( - TEST_CHECK(testEndianness); - TEST_CHECK(testByteSwapV); - TEST_CHECK(testByteSwapCxV); - TEST_CHECK(testByteSwap); - TEST_CHECK(testByteSwapValues); - TEST_CHECK(testByteSwapCxValue); - TEST_CHECK(testByteSwap12); - TEST_CHECK(testSixByteSwap); - ) diff --git a/externals/nitro/externals/coda-oss/modules/c++/types/include/types/Complex.h b/externals/nitro/externals/coda-oss/modules/c++/types/include/types/Complex.h deleted file mode 100644 index cefa90a83..000000000 --- a/externals/nitro/externals/coda-oss/modules/c++/types/include/types/Complex.h +++ /dev/null @@ -1,204 +0,0 @@ -/* ========================================================================= - * This file is part of types-c++ - * ========================================================================= - * - * (C) Copyright 2004 - 2014, MDA Information Systems LLC - * (C) Copyright 2023, Maxar Technologies, Inc. - * - * types-c++ is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; If not, - * see . - * - */ - -#pragma once -#ifndef CODA_OSS_types_Complex_h_INCLUDED_ -#define CODA_OSS_types_Complex_h_INCLUDED_ - -#include - -#include -#include -#include - -#include "config/disable_compiler_warnings.h" -#include "coda_oss/CPlusPlus.h" - -namespace types -{ -/*! - * \class Complex - * \brief Our own implementation of std::complex for SIX and friends. - * - * `std::complex` is no longer valid C++; provide a (partial) work-around. - * See https://en.cppreference.com/w/cpp/numeric/complex for details. - * - * SIX (and others) mostly use `std::complex` as a convenient - * package for two values; very little "complex math" is done using integers. - */ -template -struct Complex final -{ - using value_type = T; - static_assert(!std::is_floating_point::value, "Use std::complex for floating-point."); - static_assert(std::is_signed::value, "T should be a signed integer."); - - Complex(value_type re = 0, value_type im = 0) : z{re, im} { } - Complex(const Complex&) = default; - Complex& operator=(const Complex&) = default; - Complex(Complex&&) = default; - Complex& operator=(Complex&&) = default; - ~Complex() = default; - - // If someone already has a std::complex, is there any harm in creating ours? - Complex(const std::complex& other) : Complex(other.real(), other.imag()) { } - Complex& operator=(const std::complex& other) - { - real(other.real()); - imag(other.imag()); - return *this; - } - - #if defined(CODA_OSS_types_Complex_implicit_cast) || defined(_SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING) - CODA_OSS_disable_warning_push - #ifdef _MSC_VER - #pragma warning(disable : 4996) // '...': warning STL4037: The effect of instantiating the template std::complex for any type other than float, double, or long double is unspecified. You can define _SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING to suppress this warning. - #endif - // Better interop with existing code? Creates ambiguities? - operator const std::complex&() const - { - const void* const pThis = this; - return *static_cast*>(pThis); - } - operator std::complex&() - { - void* const pThis = this; - return *static_cast*>(pThis); - } - CODA_OSS_disable_warning_pop - #endif // CODA_OSS_types_Complex_implicit_cast || _SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING - - value_type real() const - { - return z[0]; - } - void real(value_type value) - { - z[0] = value; - } - - value_type imag() const - { - return z[1]; - } - void imag(value_type value) - { - z[1] = value; - } - -private: - value_type z[2]{0, 0}; -}; - -namespace details -{ -CODA_OSS_disable_warning_push -#ifdef _MSC_VER -#pragma warning(disable : 4996) // '...': warning STL4037: The effect of instantiating the template std::complex for any type other than float, double, or long double is unspecified. You can define _SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING to suppress this warning. -#endif -// Getting different results with GCC vs MSVC :-( So just use -// std::complex Assume by the time we're actually using C++23 with a -// compiler that enforces this restriction, "something" will be different. -template -inline const std::complex& cast(const Complex& z) -{ - const void* const pZ_ = &z; - return *static_cast*>(pZ_); -} -template -inline std::complex& cast(Complex& z) -{ - void* const pZ_ = &z; - return *static_cast*>(pZ_); -} -CODA_OSS_disable_warning_pop -} - -// https://en.cppreference.com/w/cpp/numeric/complex/operator_ltltgtgt -template -inline auto& operator<<(std::basic_ostream& o, const Complex& z) -{ - return o << details::cast(z); -} -template -inline auto& operator>>(std::basic_istream& o, Complex& z) -{ - return o >> details::cast(z); -} - -// https://en.cppreference.com/w/cpp/numeric/complex/operator_cmp -template -inline bool operator==(const Complex& lhs, const Complex& rhs) -{ - return (lhs.real() == rhs.real()) && (lhs.imag() == rhs.imag()); -} -template -inline bool operator!=(const Complex& lhs, const Complex& rhs) -{ - return !(lhs == rhs); -} - -// Keep functions like abs() to a minimum; complex math probably shouldn't be done with integers. -template -inline auto abs(const Complex& z) // https://en.cppreference.com/w/cpp/numeric/complex/abs -{ - return abs(details::cast(z)); -} - -template -using ComplexInteger = Complex; - -namespace details -{ -// This circumlocution is to prevent clients from doing `ComplexReal`. -// (And also to use the word "circumlocution." :-) ) -template struct ComplexReal -{ - static_assert(std::is_floating_point::value, "T must be floating-point."); - using type = std::complex; -}; -} // namespace details -template -using ComplexReal = typename details::ComplexReal::type; - -// This might be more trouble than it's worth: there really isn't that much code -// that is generic for both integer and real complex types; recall that the primary -// use of `std::complex` is a "convenient package" for two values. -// -//Have the compiler pick between std::complex and Complex -//template -//using complex = std::conditional_t::value, ComplexReal, ComplexInteger>; -static_assert(sizeof(std::complex) == sizeof(Complex), "sizeof(sizeof(std::complex) != sizeof(Complex)"); -static_assert(std::is_same, ComplexReal>::value, "should be std::complex"); - -// Convenient aliases -using zfloat = ComplexReal; // i.e., std::complex -using zdouble = ComplexReal; // i.e., std::complex -//using zlong_double = ComplexReal; // i.e., std::complex -using zint8_t = ComplexInteger; // Complex -using zint16_t = ComplexInteger; // Complex -using zint32_t = ComplexInteger; // Complex -using zint64_t = ComplexInteger; // Complex -} - -#endif // CODA_OSS_types_Complex_h_INCLUDED_