Skip to content

Commit

Permalink
make a simple values() member function to avoid template magic
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Smith committed Jan 11, 2023
1 parent e1feca9 commit 107e7c4
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 73 deletions.
120 changes: 51 additions & 69 deletions modules/c++/mem/include/mem/ComplexView.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,6 @@ namespace mem
* what functionality will be needed; YAGNI.
*/

// Copy the data into a "normal" std::vector<std::complex<T>> instead of parallel arrays.
namespace details
{
template <typename TView>
inline auto copy_view(TView view)
{
using cxvalue_type = typename TView::cxvalue_type; // i.e., std::complex<float>
std::vector<cxvalue_type> retval(view.size());
for (size_t i = 0; i < view.size(); i++)
{
retval[i] = view[i];
}
return retval;
}

} // namespace details

template <typename T>
struct ComplexSpanView final
{
Expand All @@ -84,9 +67,10 @@ struct ComplexSpanView final
ComplexSpanView(ComplexSpanView&&) = default;
ComplexSpanView& operator=(ComplexSpanView&&) = default;

// This class is almost the same as std::span<const std::complex<T>> ... but don't
// provide data() as ComplexSpansView stores complex numbers in two parallel arrays.
//const value_type* data() const noexcept = delete;
// This class is almost the same as std::span<const std::complex<T>> ... but
// don't provide data() as ComplexSpansView stores complex numbers in two
// parallel arrays. Also see reals(), imags() and values(); below.
// const value_type* data() const noexcept = delete;

constexpr auto real(size_type idx) const noexcept
{
Expand All @@ -107,25 +91,32 @@ struct ComplexSpanView final
return data_.size();
}

private:
template <typename TAxisFunc>
auto copy_axis(TAxisFunc axis) const
{
// real/imag are the two axes in the complex plane
using axis_type = typename value_type::value_type; // i.e., float
std::vector<axis_type> retval(size());
for (size_t i = 0; i < size(); i++)
{
retval[i] = (this->*axis)(i); // call via pointer to member function
}
return retval;
}

public:
auto reals() const
{
using axis_type = typename value_type::value_type; // i.e., float
std::vector<axis_type> retval(size());
for (size_t i = 0; i < size(); i++)
{
retval[i] = real(i);
}
return retval;
return copy_axis(&ComplexSpanView::real);
}
auto imags() const
{
using axis_type = typename value_type::value_type; // i.e., float
std::vector<axis_type> retval(size());
for (size_t i = 0; i < size(); i++)
{
retval[i] = imag(i);
}
return retval;
return copy_axis(&ComplexSpanView::imag);
}
auto values() const
{
return std::vector<cxvalue_type>(data_.begin(), data_.end());
}

private:
Expand All @@ -137,12 +128,6 @@ inline auto make_ComplexSpanView(coda_oss::span<const std::complex<T>> s)
return ComplexSpanView<T>(s);
}

template <typename T>
inline auto copy(ComplexSpanView<T> view) // for completeness and generic code
{
return details::copy_view(view);
}

template <typename TVectorLike>
struct ComplexArrayView final
{
Expand Down Expand Up @@ -189,8 +174,12 @@ struct ComplexArrayView final
{
return view.imags();
}
auto values() const
{
return view.values();
}

private:
private:
ComplexSpanView<typename value_type::value_type> view;
};
template <typename TVectorLike>
Expand All @@ -199,12 +188,6 @@ inline auto make_ComplexArrayView(const TVectorLike& v)
return ComplexArrayView<TVectorLike>(v);
}

template <typename TVectorLike>
inline auto copy(ComplexArrayView<TVectorLike> view) // for completeness and generic code
{
return details::copy_view(view);
}

template <typename T>
struct ComplexSpansView final // "Span_s_,", i.e., two spans. Avoiding "parallel" because that can conjure up multi-threading thoughts.
{
Expand All @@ -215,8 +198,7 @@ struct ComplexSpansView final // "Span_s_,", i.e., two spans. Avoiding "parallel
ComplexSpansView() = delete;
~ComplexSpansView() = default;
using span_t = coda_oss::span<const value_type>;
ComplexSpansView(span_t reals, span_t imags) :
reals_(reals), imags_(imags)
ComplexSpansView(span_t reals, span_t imags) : reals_(reals), imags_(imags)
{
if (reals_.size() != imags_.size())
{
Expand Down Expand Up @@ -250,20 +232,28 @@ struct ComplexSpansView final // "Span_s_,", i.e., two spans. Avoiding "parallel

constexpr size_type size() const noexcept
{
assert(reals_.size() == imags_.size());
return reals_.size();
}

auto reals() const
{
return std::vector<value_type>(reals_.begin(), reals_.end());
return std::vector<value_type>(reals_.begin(), reals_.end());
}
auto imags() const
{
return std::vector<value_type>(imags_.begin(), imags_.end());
return std::vector<value_type>(imags_.begin(), imags_.end());
}
auto values() const
{
std::vector<cxvalue_type> retval(size());
for (size_t i = 0; i < size(); i++)
{
retval[i] = (*this)[i];
}
return retval;
}

private:
private:
span_t reals_;
span_t imags_;
};
Expand All @@ -273,24 +263,19 @@ inline auto make_ComplexSpansView(coda_oss::span<const T> reals, coda_oss::span<
return ComplexSpansView<T>(reals, imags);
}

template <typename T>
inline auto copy(ComplexSpansView<T> view)
{
return details::copy_view(view);
}

template <typename TVectorLike> // e.g., std::vector<float>
struct ComplexArraysView final // "Array_s_,", i.e., two arrays. Avoiding "parallel" because that can conjure up multi-threading thoughts.
{
using size_type = size_t;
using value_type = typename TVectorLike::value_type; // i.e., float
using value_type = typename TVectorLike::value_type; // i.e., float
using cxvalue_type = std::complex<value_type>;

ComplexArraysView() = delete;
~ComplexArraysView() = default;
using span_t = coda_oss::span<const value_type>;
ComplexArraysView(const TVectorLike& reals, const TVectorLike& imags) :
view(span_t(reals.data(), reals.size()), span_t(imags.data(), imags.size()))
view(span_t(reals.data(), reals.size()),
span_t(imags.data(), imags.size()))
{
}
ComplexArraysView(const ComplexArraysView&) = default;
Expand Down Expand Up @@ -325,9 +310,12 @@ struct ComplexArraysView final // "Array_s_,", i.e., two arrays. Avoiding "paral
{
return view.imags();
}
auto values() const
{
return view.values();
}


private:
private:
ComplexSpansView<value_type> view;
};
template <typename TVectorLike>
Expand All @@ -336,12 +324,6 @@ inline auto make_ComplexArraysView(const TVectorLike& reals, const TVectorLike&
return ComplexArraysView<TVectorLike>(reals, imags);
}

template <typename TVectorLike>
inline auto copy(ComplexArraysView<TVectorLike> view)
{
return details::copy_view(view);
}

}

#endif // CODA_OSS_mem_ComplexView_h_INCLUDED_
8 changes: 4 additions & 4 deletions modules/c++/mem/unittests/test_vector_pointers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,13 @@ TEST_CASE(testComplexViewFloat)

TEST_ASSERT_EQ(data.size(), view.size());
test_mem_ComplexView(testName, view);
test_cx_view(testName, copy(view));
test_cx_view(testName, view.values());
}
{
const auto view = mem::make_ComplexArrayView(cx_data());
TEST_ASSERT_EQ(cx_data().size(), view.size());
test_mem_ComplexView(testName, view);
test_cx_view(testName, copy(view));
test_cx_view(testName, view.values());
}

const std::vector<float> reals{1, 3, 5, 7};
Expand All @@ -202,13 +202,13 @@ TEST_CASE(testComplexViewFloat)

TEST_ASSERT_EQ(reals.size(), view.size());
test_mem_ComplexView(testName, view);
test_cx_view(testName, copy(view));
test_cx_view(testName, view.values());
}
{
const auto view = mem::make_ComplexArraysView(reals, imags);
TEST_ASSERT_EQ(reals.size(), view.size());
test_mem_ComplexView(testName, view);
test_cx_view(testName, copy(view));
test_cx_view(testName, view.values());
}
}

Expand Down

0 comments on commit 107e7c4

Please sign in to comment.