Skip to content

Commit

Permalink
Merge pull request InsightSoftwareConsortium#4692 from N-Dekker/const…
Browse files Browse the repository at this point in the history
…expr-IndexRange

Add constexpr to IndexRange, and let BSplineInterpolationWeightFunction make use of it
  • Loading branch information
thewtex authored May 29, 2024
2 parents 29ea063 + 01b5ca3 commit bd87ded
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,6 @@ class ITK_TEMPLATE_EXPORT BSplineInterpolationWeightFunction
protected:
BSplineInterpolationWeightFunction() = default;
~BSplineInterpolationWeightFunction() override = default;

private:
/** Lookup table type. */
using TableType = FixedArray<IndexType, NumberOfWeights>;

/** Table mapping linear offset to indices. */
const TableType m_OffsetToIndexTable{ [] {
TableType table;
std::copy_n(ZeroBasedIndexRange<SpaceDimension>(SupportSize).cbegin(), NumberOfWeights, table.begin());
return table;
}() };
};
} // end namespace itk

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ BSplineInterpolationWeightFunction<TCoordRep, VSpaceDimension, VSplineOrder>::Ev
WeightsType & weights,
IndexType & startIndex) const
{
static constexpr auto offsetToIndexTable = [] {
FixedArray<IndexType, NumberOfWeights> table{};
auto indexIterator = ZeroBasedIndexRange<SpaceDimension>(SupportSize).cbegin();

for (size_t i{}; i < NumberOfWeights; ++i)
{
table[i] = *indexIterator;
++indexIterator;
}
return table;
}();

unsigned int j, k;

// Find the starting index of the support region
Expand Down Expand Up @@ -77,7 +89,7 @@ BSplineInterpolationWeightFunction<TCoordRep, VSpaceDimension, VSplineOrder>::Ev

for (j = 0; j < SpaceDimension; ++j)
{
weights[k] *= weights1D[j][m_OffsetToIndexTable[k][j]];
weights[k] *= weights1D[j][offsetToIndexTable[k][j]];
}
}
}
Expand Down
43 changes: 23 additions & 20 deletions Modules/Core/Common/include/itkIndexRange.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,15 @@ class IndexRange final


/** Returns a reference to the current index. */
reference operator*() const noexcept { return m_Index; }
constexpr reference operator*() const noexcept { return m_Index; }


/** Returns a pointer to the current index. */
pointer operator->() const noexcept { return &(**this); }
constexpr pointer operator->() const noexcept { return &(**this); }


/** Prefix increment ('++it'). */
const_iterator &
constexpr const_iterator &
operator++() noexcept
{
for (unsigned int i = 0; i < (VDimension - 1); ++i)
Expand All @@ -132,7 +132,7 @@ class IndexRange final

/** Postfix increment ('it++').
* \note Usually prefix increment ('++it') is preferable. */
const_iterator
constexpr const_iterator
operator++(int) noexcept
{
auto result = *this;
Expand All @@ -142,7 +142,7 @@ class IndexRange final


/** Prefix decrement ('--it'). */
const_iterator &
constexpr const_iterator &
operator--() noexcept
{
for (unsigned int i = 0; i < (VDimension - 1); ++i)
Expand All @@ -164,7 +164,7 @@ class IndexRange final

/** Postfix increment ('it--').
* \note Usually prefix increment ('--it') is preferable. */
const_iterator
constexpr const_iterator
operator--(int) noexcept
{
auto result = *this;
Expand Down Expand Up @@ -195,7 +195,7 @@ class IndexRange final


/** Returns (it1 < it2) for iterators it1 and it2. */
friend bool
friend constexpr bool
operator<(const const_iterator & lhs, const const_iterator & rhs) noexcept
{
for (unsigned int i = VDimension; i > 0; --i)
Expand All @@ -216,7 +216,7 @@ class IndexRange final


/** Returns (it1 > it2) for iterators it1 and it2. */
friend bool
friend constexpr bool
operator>(const const_iterator & lhs, const const_iterator & rhs) noexcept
{
// Implemented just like the corresponding std::rel_ops operator.
Expand All @@ -225,7 +225,7 @@ class IndexRange final


/** Returns (it1 <= it2) for iterators it1 and it2. */
friend bool
friend constexpr bool
operator<=(const const_iterator & lhs, const const_iterator & rhs) noexcept
{
// Implemented just like the corresponding std::rel_ops operator.
Expand All @@ -234,7 +234,7 @@ class IndexRange final


/** Returns (it1 >= it2) for iterators it1 and it2. */
friend bool
friend constexpr bool
operator>=(const const_iterator & lhs, const const_iterator & rhs) noexcept
{
// Implemented just like the corresponding std::rel_ops operator.
Expand All @@ -261,7 +261,9 @@ class IndexRange final
using MinIndexType = std::conditional_t<VBeginAtZero, ZeroIndex, IndexType>;

// Private constructor, only used by friend class IndexRange.
const_iterator(const IndexType & index, const MinIndexType & minIndex, const IndexType & maxIndex) noexcept
constexpr const_iterator(const IndexType & index,
const MinIndexType & minIndex,
const IndexType & maxIndex) noexcept
: // Note: Use parentheses instead of curly braces to initialize data members,
// to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
m_Index(index)
Expand Down Expand Up @@ -296,7 +298,7 @@ class IndexRange final

/** Constructs a range of indices for the specified grid size.
*/
explicit IndexRange(const SizeType & gridSize)
constexpr explicit IndexRange(const SizeType & gridSize)
: // Note: Use parentheses instead of curly braces to initialize data members,
// to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
m_MinIndex()
Expand Down Expand Up @@ -326,14 +328,14 @@ class IndexRange final


/** Returns an iterator to the first index. */
iterator
constexpr iterator
begin() const noexcept
{
return iterator(m_MinIndex, m_MinIndex, m_MaxIndex);
}

/** Returns an 'end iterator' for this range. */
iterator
constexpr iterator
end() const noexcept
{
IndexType index = m_MinIndex;
Expand All @@ -343,14 +345,14 @@ class IndexRange final

/** Returns a const iterator to the first index.
* Provides only read-only access to the index data. */
const_iterator
constexpr const_iterator
cbegin() const noexcept
{
return this->begin();
}

/** Returns a const 'end iterator' for this range. */
const_iterator
constexpr const_iterator
cend() const noexcept
{
return this->end();
Expand Down Expand Up @@ -386,7 +388,7 @@ class IndexRange final


/** Returns the size of the range, that is the number of indices. */
size_t
constexpr size_t
size() const noexcept
{
size_t result = 1;
Expand All @@ -400,7 +402,7 @@ class IndexRange final


/** Tells whether the range is empty. */
bool
constexpr bool
empty() const noexcept
{
// When an IndexRange is empty, each index value of m_MaxIndex is less than the corresponding
Expand All @@ -414,7 +416,7 @@ class IndexRange final
private:
using MinIndexType = typename iterator::MinIndexType;

static IndexType
static constexpr IndexType
CalculateMaxIndex(const MinIndexType & minIndex, const SizeType & size)
{
const bool sizeHasZeroValue = [&size] {
Expand All @@ -431,7 +433,8 @@ class IndexRange final
// Treat any size that has a zero value equally.
const SizeType normalizedSize = sizeHasZeroValue ? SizeType{ { 0 } } : size;

IndexType index;
// The `index` is initialized (`{}`), just to support C++17 constexpr.
IndexType index{};

for (unsigned int i = 0; i < VDimension; ++i)
{
Expand Down
43 changes: 21 additions & 22 deletions Modules/Core/Common/test/itkIndexRangeGTest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ template <unsigned int VDimension>
void
ExpectRangeIsEmptyWhenRegionSizeIsZero()
{
const itk::Size<VDimension> zeroSize{ { 0 } };
static constexpr itk::Size<VDimension> zeroSize{ { 0 } };

// Test when both the region index and the region size are zero:
EXPECT_TRUE(ZeroBasedIndexRange<VDimension>{ zeroSize }.empty());
EXPECT_TRUE(ImageRegionIndexRange<VDimension>{ zeroSize }.empty());
static_assert(ZeroBasedIndexRange<VDimension>{ zeroSize }.empty());
static_assert(ImageRegionIndexRange<VDimension>{ zeroSize }.empty());

// Now do the test for an arbitrary (random) region index:
const itk::Index<VDimension> randomRegionIndex = GenerateRandomIndex<VDimension>();
Expand Down Expand Up @@ -143,12 +143,12 @@ TEST(IndexRange, EquivalentBeginOrEndIteratorsCompareEqual)
{
using RangeType = IndexRange<2, true>;

RangeType range(RangeType::SizeType{ { 1, 2 } });
static constexpr RangeType range(RangeType::SizeType{ { 1, 2 } });

const RangeType::iterator begin = range.begin();
const RangeType::iterator end = range.end();
const RangeType::const_iterator cbegin = range.cbegin();
const RangeType::const_iterator cend = range.cend();
static constexpr RangeType::iterator begin = range.begin();
static constexpr RangeType::iterator end = range.end();
static constexpr RangeType::const_iterator cbegin = range.cbegin();
static constexpr RangeType::const_iterator cend = range.cend();

// An iterator object compares equal to itself:
EXPECT_EQ(begin, begin);
Expand All @@ -175,10 +175,9 @@ TEST(IndexRange, EquivalentBeginOrEndIteratorsCompareEqual)
TEST(IndexRange, BeginAndEndDoNotCompareEqualWhenSizeIsGreaterThanZero)
{
using RangeType = IndexRange<2, true>;
RangeType range(RangeType::SizeType{ { 1, 2 } });
static constexpr RangeType range(RangeType::SizeType{ { 1, 2 } });

EXPECT_TRUE(!range.empty());
EXPECT_FALSE(range.empty());
static_assert(!range.empty());

EXPECT_FALSE(range.begin() == range.end());
EXPECT_NE(range.begin(), range.end());
Expand All @@ -190,7 +189,7 @@ TEST(IndexRange, BeginAndEndDoNotCompareEqualWhenSizeIsGreaterThanZero)
TEST(IndexRange, IteratorsCanBePassedToStdVectorConstructor)
{
using RangeType = IndexRange<2, true>;
RangeType range(RangeType::SizeType{ { 1, 2 } });
static constexpr RangeType range(RangeType::SizeType{ { 1, 2 } });

// Easily store all indices of an IndexRange in an std::vector:
const std::vector<RangeType::IndexType> stdVector(range.begin(), range.end());
Expand All @@ -206,9 +205,9 @@ TEST(IndexRange, IteratorsCanBePassedToStdReverseCopy)
{
using RangeType = IndexRange<2, true>;
using IndexType = RangeType::IndexType;
RangeType range(RangeType::SizeType{ { 2, 3 } });
static constexpr RangeType range(RangeType::SizeType{ { 2, 3 } });

const unsigned int numberOfIndices = range.size();
static constexpr unsigned int numberOfIndices = range.size();

const std::vector<IndexType> stdVector(range.begin(), range.end());
std::vector<IndexType> reversedStdVector1(numberOfIndices);
Expand Down Expand Up @@ -237,7 +236,7 @@ TEST(IndexRange, IteratorsCanBePassedToStdForEach)
{
using RangeType = IndexRange<2, true>;
using IndexType = RangeType::IndexType;
RangeType range(RangeType::SizeType{ { 2, 3 } });
static constexpr RangeType range(RangeType::SizeType{ { 2, 3 } });

std::for_each(range.begin(), range.end(), [](const IndexType index) { EXPECT_TRUE(index >= IndexType()); });
}
Expand All @@ -249,7 +248,7 @@ TEST(IndexRange, CanBeUsedAsExpressionOfRangeBasedForLoop)
{
using RangeType = IndexRange<2, true>;
using IndexType = RangeType::IndexType;
RangeType range(RangeType::SizeType{ { 2, 3 } });
static constexpr RangeType range(RangeType::SizeType{ { 2, 3 } });

for (auto && index : range)
{
Expand All @@ -266,14 +265,14 @@ TEST(IndexRange, SupportsImageRegion)
using IndexType = ImageRegionIndexRangeType::IndexType;
using RegionType = itk::ImageRegion<Dimension>;

const RegionType::SizeType size = { { 2, 3 } };
const RegionType::IndexType regionIndex = { { 4, 5 } };
const RegionType imageRegion{ regionIndex, size };
static constexpr RegionType::SizeType size = { { 2, 3 } };
static constexpr RegionType::IndexType regionIndex = { { 4, 5 } };
const RegionType imageRegion{ regionIndex, size };

// Default index range, beginning at [0, 0].
const ZeroBasedIndexRange<Dimension> indexRange(size);
const auto beginOfIndexRange = indexRange.cbegin();
const auto endOfIndexRange = indexRange.cend();
static constexpr ZeroBasedIndexRange<Dimension> indexRange(size);
static constexpr auto beginOfIndexRange = indexRange.cbegin();
static constexpr auto endOfIndexRange = indexRange.cend();

const ImageRegionIndexRangeType imageRegionIndexRange(imageRegion);

Expand Down

0 comments on commit bd87ded

Please sign in to comment.