diff --git a/six/modules/c++/six.sicd/include/six/sicd/ImageData.h b/six/modules/c++/six.sicd/include/six/sicd/ImageData.h index 9d3b3c068..8106a4eaf 100644 --- a/six/modules/c++/six.sicd/include/six/sicd/ImageData.h +++ b/six/modules/c++/six.sicd/include/six/sicd/ImageData.h @@ -41,8 +41,6 @@ namespace six { namespace sicd { -using cx_float = six::zfloat; - class GeoData; /*! * \struct ImageData diff --git a/six/modules/c++/six.sicd/include/six/sicd/Utilities.h b/six/modules/c++/six.sicd/include/six/sicd/Utilities.h index 7be19acdb..cc3653ead 100644 --- a/six/modules/c++/six.sicd/include/six/sicd/Utilities.h +++ b/six/modules/c++/six.sicd/include/six/sicd/Utilities.h @@ -635,9 +635,9 @@ struct Utilities final // Convert the amp/phase to a complex value using the given AmplitudeTable, if any. // This call could be in a tight loop where the value of six::AmplitudeTable* is known outside of the loop; // the overloads allow clients to avoid an inner `if`-check. - static std::complex toComplex(uint8_t amplitude, uint8_t phase, const six::AmplitudeTable* pAmplitudeTable); - static std::complex toComplex(uint8_t amplitude, uint8_t phase, const six::AmplitudeTable&); - static std::complex toComplex(uint8_t amplitude, uint8_t phase); + static six::zfloat toComplex(uint8_t amplitude, uint8_t phase, const six::AmplitudeTable* pAmplitudeTable); + static six::zfloat toComplex(uint8_t amplitude, uint8_t phase, const six::AmplitudeTable&); + static six::zfloat toComplex(uint8_t amplitude, uint8_t phase); }; diff --git a/six/modules/c++/six.sicd/source/ComplexData.cpp b/six/modules/c++/six.sicd/source/ComplexData.cpp index 0e6fdf6a6..3f54b3edf 100644 --- a/six/modules/c++/six.sicd/source/ComplexData.cpp +++ b/six/modules/c++/six.sicd/source/ComplexData.cpp @@ -373,7 +373,7 @@ bool six::sicd::ComplexData::convertPixels_(std::span from_, st } // Convert the pixels from a complex to AMP8I_PHS8I. - const auto from = make_span(from_); + const auto from = make_span(from_); to = imageData->fromComplex(from); return true; // converted } diff --git a/six/modules/c++/six.sicd/source/ComplexToAMP8IPHS8I.cpp b/six/modules/c++/six.sicd/source/ComplexToAMP8IPHS8I.cpp index a24390a32..d799b3c5f 100644 --- a/six/modules/c++/six.sicd/source/ComplexToAMP8IPHS8I.cpp +++ b/six/modules/c++/six.sicd/source/ComplexToAMP8IPHS8I.cpp @@ -71,12 +71,19 @@ The resulting green point is then what's used to find the nearest magnitude via * @param v complex value * @return phase between [0, 2PI] */ -inline auto GetPhase(const std::complex& v) +inline auto GetPhase(std::complex v) { double phase = std::arg(v); if (phase < 0.0) phase += std::numbers::pi * 2.0; // Wrap from [0, 2PI] return phase; } +uint8_t six::sicd::details::ComplexToAMP8IPHS8I::getPhase(six::zfloat v) const +{ + // Phase is determined via arithmetic because it's equally spaced. + // There's an intentional conversion to zero when we cast 256 -> uint8. That wrap around + // handles cases that are close to 2PI. + return gsl::narrow_cast(std::round(GetPhase(v) / phase_delta)); +} template static std::vector make_magnitudes_(TToComplexFunc toComplex) @@ -172,11 +179,7 @@ static inline uint8_t nearest(const std::vector& magnitudes, float value) six::AMP8I_PHS8I_t six::sicd::details::ComplexToAMP8IPHS8I::nearest_neighbor(const six::zfloat &v) const { six::AMP8I_PHS8I_t retval; - - // Phase is determined via arithmetic because it's equally spaced. - // There's an intentional conversion to zero when we cast 256 -> uint8. That wrap around - // handles cases that are close to 2PI. - retval.phase = gsl::narrow_cast(std::round(GetPhase(v) / phase_delta)); + retval.phase = getPhase(v); // We have to do a 1D nearest neighbor search for magnitude. // But it's not the magnitude of the input complex value - it's the projection of @@ -230,24 +233,20 @@ static inline void transform(std::span inputs, std::span six::sicd::details::ComplexToAMP8IPHS8I::nearest_neighbors(std::span inputs) const +std::vector six::sicd::details::ComplexToAMP8IPHS8I::nearest_neighbors( + std::span inputs, const six::AmplitudeTable* pAmplitudeTable) { - const auto nearest_neighbor_ = [&](const auto& v) + // make a structure to quickly find the nearest neighbor + const auto& converter = make(pAmplitudeTable); + const auto nearest_neighbor = [&converter](const auto& v) { - return this->nearest_neighbor(v); + return converter.nearest_neighbor(v); }; std::vector retval(inputs.size()); - transform(sys::make_const_span(inputs), sys::make_span(retval), nearest_neighbor_); + transform(sys::make_const_span(inputs), sys::make_span(retval), nearest_neighbor); return retval; } -std::vector six::sicd::details::ComplexToAMP8IPHS8I::nearest_neighbors( - std::span inputs, const six::AmplitudeTable* pAmplitudeTable) -{ - // make a structure to quickly find the nearest neighbor - const auto& converter = make(pAmplitudeTable); - return converter.nearest_neighbors(inputs); -} const six::sicd::details::ComplexToAMP8IPHS8I& six::sicd::details::ComplexToAMP8IPHS8I::make(const six::AmplitudeTable* pAmplitudeTable) { diff --git a/six/modules/c++/six.sicd/source/Utilities.cpp b/six/modules/c++/six.sicd/source/Utilities.cpp index c02fdb5ea..6b8fac025 100644 --- a/six/modules/c++/six.sicd/source/Utilities.cpp +++ b/six/modules/c++/six.sicd/source/Utilities.cpp @@ -97,21 +97,21 @@ static auto toComplex_(double A, uint8_t phase) const auto angle = units::Radians{ 2 * std::numbers::pi * P }; double sin_angle, cos_angle; SinCos(angle, sin_angle, cos_angle); - std::complex S(A * cos_angle, A * sin_angle); + six::zfloat S(A * cos_angle, A * sin_angle); return S; } -std::complex six::sicd::Utilities::toComplex(uint8_t amplitude, uint8_t phase) +six::zfloat six::sicd::Utilities::toComplex(uint8_t amplitude, uint8_t phase) { // A = input_amplitude(i.e. 0 to 255) const double A = amplitude; return toComplex_(A, phase); } -std::complex six::sicd::Utilities::toComplex(uint8_t amplitude, uint8_t phase, const six::AmplitudeTable& amplitudeTable) +six::zfloat six::sicd::Utilities::toComplex(uint8_t amplitude, uint8_t phase, const six::AmplitudeTable& amplitudeTable) { const double A = amplitudeTable.index(amplitude); return toComplex_(A, phase); } -std::complex six::sicd::Utilities::toComplex(uint8_t amplitude, uint8_t phase, const six::AmplitudeTable* pAmplitudeTable) +six::zfloat six::sicd::Utilities::toComplex(uint8_t amplitude, uint8_t phase, const six::AmplitudeTable* pAmplitudeTable) { if (pAmplitudeTable != nullptr) { diff --git a/six/modules/c++/six.sicd/unittests/test_AMP8I_PHS8I.cpp b/six/modules/c++/six.sicd/unittests/test_AMP8I_PHS8I.cpp index fb26e7076..3c259c04f 100644 --- a/six/modules/c++/six.sicd/unittests/test_AMP8I_PHS8I.cpp +++ b/six/modules/c++/six.sicd/unittests/test_AMP8I_PHS8I.cpp @@ -175,7 +175,7 @@ TEST_CASE(test_8bit_ampphs) TEST_ASSERT(actuals == expecteds); - // we should now be able to convert the cx_floats back to amp/value + // we should now be able to convert the `zfloat`s back to amp/value std::vector amp8i_phs8i(actuals.size()); to_AMP8I_PHS8I(imageData, actuals, amp8i_phs8i); test_assert_eq(testName, actuals, amp8i_phs8i); diff --git a/six/modules/c++/six/include/six/AmplitudeTable.h b/six/modules/c++/six/include/six/AmplitudeTable.h index e303c7b68..99ac719d4 100644 --- a/six/modules/c++/six/include/six/AmplitudeTable.h +++ b/six/modules/c++/six/include/six/AmplitudeTable.h @@ -214,6 +214,8 @@ class ComplexToAMP8IPHS8I final //! The difference in phase angle between two UINT phase values. float phase_delta; + uint8_t getPhase(six::zfloat) const; + //! Unit vector rays that represent each direction that phase can point. std::array phase_directions; };