Skip to content

Commit ebc4a8a

Browse files
author
Dan Smith
committed
references instead of pointers
1 parent 4503448 commit ebc4a8a

4 files changed

Lines changed: 105 additions & 43 deletions

File tree

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,32 @@
1-
#ifndef __SIX_SICD_COMPLEXTOAMP8IPHS8I__
2-
#define __SIX_SICD_COMPLEXTOAMP8IPHS8I__
1+
/* =========================================================================
2+
* This file is part of six.sicd-c++
3+
* =========================================================================
4+
*
5+
* (C) Copyright 2021, Maxar Technologies, Inc.
6+
*
7+
* six.sicd-c++ is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU Lesser General Public License as published by
9+
* the Free Software Foundation; either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this program; If not,
19+
* see <http://www.gnu.org/licenses/>.
20+
*
21+
*/
22+
#ifndef SIX_six_sicd_ComplexToAMP8IPHS8I_h_INCLUDED_
23+
#define SIX_six_sicd_ComplexToAMP8IPHS8I_h_INCLUDED_
24+
#pragma once
25+
26+
#include <stdint.h>
27+
28+
#include <array>
29+
#include <complex>
330

431
#include <six/sicd/ImageData.h>
532

@@ -10,36 +37,33 @@ namespace sicd
1037
/*!
1138
* \brief A utility that's used to convert complex values into 8-bit amplitude and phase values.
1239
*/
13-
class ComplexToAMP8IPHS8I {
40+
class ComplexToAMP8IPHS8I final
41+
{
42+
explicit ComplexToAMP8IPHS8I(const six::AmplitudeTable* pAmplitudeTable);
43+
1444
public:
1545
/*!
1646
* Create a lookup structure that converts from complex to amplitude and phase.
1747
* @param pAmplitudeTable optional amplitude table.
1848
*/
19-
explicit ComplexToAMP8IPHS8I(const six::AmplitudeTable* pAmplitudeTable = nullptr);
49+
explicit ComplexToAMP8IPHS8I();
50+
explicit ComplexToAMP8IPHS8I(const six::AmplitudeTable&);
2051

2152
/*!
2253
* Get the nearest amplitude and phase value given a complex value
2354
* @param v complex value to query with
2455
* @return nearest amplitude and phase value
2556
*/
26-
ImageData::AMP8I_PHS8I_t nearest_neighbor(const std::complex<double>& v) const;
57+
ImageData::AMP8I_PHS8I_t nearest_neighbor(const std::complex<float>& v) const;
2758

2859
private:
2960
//! The sorted set of possible magnitudes order from small to large.
30-
std::array<double, UINT8_MAX + 1> magnitudes;
61+
std::array<long double, UINT8_MAX + 1> magnitudes;
3162
//! The difference in phase angle between two UINT phase values.
32-
double phase_delta;
63+
long double phase_delta;
3364
//! Unit vector rays that represent each direction that phase can point.
34-
std::array<std::complex<double>, UINT8_MAX + 1> phase_directions;
35-
36-
/*!
37-
* Get the phase of a complex value.
38-
* @param v complex value
39-
* @return phase between [0, 2PI]
40-
*/
41-
static double GetPhase(const std::complex<double>& v);
65+
std::array<std::complex<long double>, UINT8_MAX + 1> phase_directions;
4266
};
4367
}
4468
}
45-
#endif
69+
#endif // SIX_six_sicd_ComplexToAMP8IPHS8I_h_INCLUDED_

six/modules/c++/six.sicd/source/ComplexToAMP8IPHS8I.cpp

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
/* =========================================================================
2+
* This file is part of six.sicd-c++
3+
* =========================================================================
4+
*
5+
* (C) Copyright 2021, Maxar Technologies, Inc.
6+
*
7+
* six.sicd-c++ is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU Lesser General Public License as published by
9+
* the Free Software Foundation; either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this program; If not,
19+
* see <http://www.gnu.org/licenses/>.
20+
*
21+
*/
122
#include "six/sicd/ComplexToAMP8IPHS8I.h"
223

324
#include <math.h>
@@ -11,10 +32,23 @@
1132
namespace six {
1233
namespace sicd {
1334

14-
ComplexToAMP8IPHS8I::ComplexToAMP8IPHS8I(const six::AmplitudeTable *pAmplitudeTable) {
35+
/*!
36+
* Get the phase of a complex value.
37+
* @param v complex value
38+
* @return phase between [0, 2PI]
39+
*/
40+
inline double GetPhase(const std::complex<double>& v)
41+
{
42+
double phase = std::arg(v);
43+
if (phase < 0.0) phase += M_PI * 2.0; // Wrap from [0, 2PI]
44+
return phase;
45+
}
1546

47+
ComplexToAMP8IPHS8I::ComplexToAMP8IPHS8I(const six::AmplitudeTable *pAmplitudeTable)
48+
{
1649
// Be careful with indexing so that we don't wrap-around in the loops.
17-
for (uint16_t i = 0; i <= UINT8_MAX; i++) {
50+
for (uint16_t i = 0; i <= UINT8_MAX; i++)
51+
{
1852
// AmpPhase -> Complex
1953
ImageData::AMP8I_PHS8I_t v;
2054
v.first = gsl::narrow<uint8_t>(i);
@@ -36,12 +70,15 @@ ComplexToAMP8IPHS8I::ComplexToAMP8IPHS8I(const six::AmplitudeTable *pAmplitudeTa
3670
assert(p0 == 0);
3771
assert(p1 > p0);
3872
phase_delta = p1 - p0;
39-
for(size_t i = 0; i <= UINT8_MAX; i++) {
40-
double y, x;
41-
math::SinCos(p0 + gsl::narrow_cast<double>(i) * phase_delta, y, x);
73+
for(size_t i = 0; i <= UINT8_MAX; i++)
74+
{
75+
long double y, x;
76+
math::SinCos(p0 + gsl::narrow_cast<long double>(i) * phase_delta, y, x);
4277
phase_directions[i] = { x, y };
4378
}
4479
}
80+
ComplexToAMP8IPHS8I::ComplexToAMP8IPHS8I(const six::AmplitudeTable& amplitudeTable) : ComplexToAMP8IPHS8I(&amplitudeTable) {}
81+
ComplexToAMP8IPHS8I::ComplexToAMP8IPHS8I() : ComplexToAMP8IPHS8I(nullptr /*pAmplitudeTable*/) {}
4582

4683
/*!
4784
* Find the nearest element given an iterator range.
@@ -52,39 +89,35 @@ ComplexToAMP8IPHS8I::ComplexToAMP8IPHS8I(const six::AmplitudeTable *pAmplitudeTa
5289
* @return index of nearest value within the iterator range.
5390
*/
5491
template<typename TIter>
55-
static uint8_t nearest(const TIter& begin, const TIter& end, double value) {
92+
static uint8_t nearest(const TIter& begin, const TIter& end, long double value)
93+
{
5694
auto it = std::lower_bound(begin, end, value);
57-
if(it == begin) return uint8_t(0);
95+
if(it == begin) return 0;
5896
auto prev_it = std::prev(it);
5997
auto nearest = (it == end || value - *prev_it <= *it - value) ? prev_it : it;
6098
assert(std::distance(begin, nearest) <= std::numeric_limits<uint8_t>::max());
6199
return static_cast<uint8_t>(std::distance(begin, nearest));
62100
}
63101

64-
ImageData::AMP8I_PHS8I_t ComplexToAMP8IPHS8I::nearest_neighbor(const std::complex<double> &v) const {
102+
ImageData::AMP8I_PHS8I_t ComplexToAMP8IPHS8I::nearest_neighbor(const std::complex<float> &v) const
103+
{
65104
ImageData::AMP8I_PHS8I_t ans;
66105

67106
// Phase is determined via arithmetic because it's equally spaced.
68107
// There's an intentional conversion to zero when we cast 256 -> uint8. That wrap around
69108
// handles cases that are close to 2PI.
70-
ans.second = static_cast<uint8_t>(std::round(GetPhase(v) / phase_delta));
109+
ans.second = gsl::narrow_cast<uint8_t>(std::round(GetPhase(v) / phase_delta));
71110

72111
// We have to do a 1D nearest neighbor search for magnitude.
73112
// But it's not the magnitude of the input complex value - it's the projection of
74113
// the complex value onto the ray of candidate magnitudes at the selected phase.
75114
// I.e. dot product.
76-
const std::complex<double> direction = phase_directions[ans.second];
77-
const double projection = direction.real() * v.real() + direction.imag() * v.imag();
115+
auto&& direction = phase_directions[ans.second];
116+
const auto projection = direction.real() * gsl::narrow_cast<long double>(v.real()) + direction.imag() * gsl::narrow_cast<long double>(v.imag());
78117
//assert(std::abs(projection - std::abs(v)) < 1e-5); // TODO ???
79118
ans.first = nearest(magnitudes.begin(), magnitudes.end(), projection);
80119
return ans;
81120
}
82121

83-
84-
double ComplexToAMP8IPHS8I::GetPhase(const std::complex<double> &v) {
85-
double phase = std::arg(v);
86-
if (phase < 0.0) phase += M_PI * 2.0; // Wrap from [0, 2PI]
87-
return phase;
88-
}
89122
}
90123
}

six/modules/c++/six.sicd/source/ImageData.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ static const ComplexToAMP8IPHS8I* make_ComplexToAMP8IPHS8I(const six::AmplitudeT
253253
}
254254
else
255255
{
256-
pTree = std::make_unique<ComplexToAMP8IPHS8I>(pAmplitudeTable);
256+
pTree = std::make_unique<ComplexToAMP8IPHS8I>(*pAmplitudeTable);
257257
return pTree.get();
258258
}
259259
}

six/modules/c++/six.sicd/unittests/test_AMP8I_PHS8I.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -588,14 +588,16 @@ TEST_CASE(test_ComplexToAMP8IPHS8I)
588588
{
589589
// Set up a converter that has a fake amplitude table.
590590
six::AmplitudeTable amp;
591-
for(size_t i = 0; i < 256; i++) {
591+
for(size_t i = 0; i < 256; i++)
592+
{
592593
amp.index(i) = static_cast<double>(i) + 10.0;
593594
}
594-
six::sicd::ComplexToAMP8IPHS8I item(&amp);
595+
six::sicd::ComplexToAMP8IPHS8I item(amp);
595596

596597
// Generate the full 256x256 matrix of possible AMP8I_PHS8I values.
597-
struct Pairs {
598-
std::complex<double> floating;
598+
struct Pairs final
599+
{
600+
std::complex<float> floating;
599601
six::sicd::ImageData::AMP8I_PHS8I_t integral;
600602
};
601603
std::vector<Pairs> candidates;
@@ -635,20 +637,23 @@ TEST_CASE(test_ComplexToAMP8IPHS8I)
635637
//size_t bad_first = 0;
636638
//size_t bad_second = 0;
637639
//double worst_error = 0;
638-
for(size_t k = 0; k < kTests; k++) {
640+
for(size_t k = 0; k < kTests; k++)
641+
{
639642
double x = dist(eng);
640643
double y = dist(eng);
641644

642645
// Calculate the nearest neighbor quickly.
643-
const std::complex<double> input_dbl(x, y);
646+
const std::complex<float> input_dbl(x, y);
644647
const auto test_integral = item.nearest_neighbor(input_dbl);
645648

646649
// Calculate the nearest neighbor via exhaustive calculation.
647650
double min_distance = std::abs(candidates[0].floating - input_dbl);
648651
auto best = candidates[0];
649-
for(auto& i : candidates) {
650-
double e = std::abs(i.floating - input_dbl);
651-
if(e < min_distance) {
652+
for(const auto& i : candidates)
653+
{
654+
const auto e = std::abs(i.floating - input_dbl);
655+
if(e < min_distance)
656+
{
652657
min_distance = e;
653658
best = i;
654659
}

0 commit comments

Comments
 (0)