Skip to content

Commit 619f3ae

Browse files
authored
Update crop_range to clamp to domain range. (#4781)
While working on #4685 we found it was possible for a cropped range to fall outside of the given domain range. This updates crop_range to call `std::clamp` instead of min/max to ensure the resulting cropped range is within the domain. --- TYPE: BUG DESC: Update crop_range to clamp to domain range.
1 parent 9165795 commit 619f3ae

File tree

5 files changed

+48
-53
lines changed

5 files changed

+48
-53
lines changed

tiledb/sm/array_schema/dimension.cc

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ Dimension::Dimension(const std::string& name, Datatype type)
7171
set_ceil_to_tile_func();
7272
set_coincides_with_tiles_func();
7373
set_compute_mbr_func();
74-
set_crop_range_func();
7574
set_domain_range_func();
7675
set_expand_range_func();
7776
set_expand_range_v_func();
@@ -107,7 +106,6 @@ Dimension::Dimension(
107106
set_ceil_to_tile_func();
108107
set_coincides_with_tiles_func();
109108
set_compute_mbr_func();
110-
set_crop_range_func();
111109
set_domain_range_func();
112110
set_expand_range_func();
113111
set_expand_range_v_func();
@@ -355,21 +353,6 @@ Range Dimension::compute_mbr_var(
355353
return compute_mbr_var_func_(tile_off, tile_val);
356354
}
357355

358-
template <class T>
359-
void Dimension::crop_range(const Dimension* dim, Range* range) {
360-
assert(dim != nullptr);
361-
assert(!range->empty());
362-
auto dim_dom = (const T*)dim->domain().data();
363-
auto r = (const T*)range->data();
364-
T res[2] = {std::max(r[0], dim_dom[0]), std::min(r[1], dim_dom[1])};
365-
range->set_range(res, sizeof(res));
366-
}
367-
368-
void Dimension::crop_range(Range* range) const {
369-
assert(crop_range_func_ != nullptr);
370-
crop_range_func_(this, range);
371-
}
372-
373356
template <class T>
374357
uint64_t Dimension::domain_range(const Range& range) {
375358
assert(!range.empty());
@@ -1591,15 +1574,6 @@ std::string Dimension::tile_extent_str() const {
15911574
return apply_with_type(g, type_);
15921575
}
15931576

1594-
void Dimension::set_crop_range_func() {
1595-
auto g = [&](auto T) {
1596-
if constexpr (tiledb::type::TileDBNumeric<decltype(T)>) {
1597-
crop_range_func_ = crop_range<decltype(T)>;
1598-
}
1599-
};
1600-
apply_with_type(g, type_);
1601-
}
1602-
16031577
void Dimension::set_domain_range_func() {
16041578
auto g = [&](auto T) {
16051579
if constexpr (tiledb::type::TileDBFundamental<decltype(T)>) {

tiledb/sm/array_schema/dimension.h

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -487,19 +487,6 @@ class Dimension {
487487
static Range compute_mbr_var(
488488
const WriterTile& tile_off, const WriterTile& tile_val);
489489

490-
/**
491-
* Crops the input 1D range such that it does not exceed the
492-
* dimension domain.
493-
*/
494-
void crop_range(Range* range) const;
495-
496-
/**
497-
* Crops the input 1D range such that it does not exceed the
498-
* dimension domain.
499-
*/
500-
template <class T>
501-
static void crop_range(const Dimension* dim, Range* range);
502-
503490
/**
504491
* Returns the domain range (high - low + 1) of the input
505492
* 1D range. It returns 0 in case the dimension datatype
@@ -818,13 +805,7 @@ class Dimension {
818805
compute_mbr_var_func_;
819806

820807
/**
821-
* Stores the appropriate templated crop_range() function based on the
822-
* dimension datatype.
823-
*/
824-
std::function<void(const Dimension* dim, Range*)> crop_range_func_;
825-
826-
/**
827-
* Stores the appropriate templated crop_range() function based on the
808+
* Stores the appropriate templated domain_range() function based on the
828809
* dimension datatype.
829810
*/
830811
std::function<uint64_t(const Range&)> domain_range_func_;
@@ -1032,9 +1013,6 @@ class Dimension {
10321013
/** Sets the templated compute_mbr() function. */
10331014
void set_compute_mbr_func();
10341015

1035-
/** Sets the templated crop_range() function. */
1036-
void set_crop_range_func();
1037-
10381016
/** Sets the templated domain_range() function. */
10391017
void set_domain_range_func();
10401018

tiledb/sm/array_schema/domain.cc

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "tiledb/sm/enums/layout.h"
4242
#include "tiledb/sm/misc/tdb_math.h"
4343
#include "tiledb/sm/misc/utils.h"
44+
#include "tiledb/type/apply_with_type.h"
4445
#include "tiledb/type/range/range.h"
4546

4647
#include <cassert>
@@ -312,8 +313,19 @@ int Domain::cell_order_cmp(
312313
}
313314

314315
void Domain::crop_ndrange(NDRange* ndrange) const {
315-
for (unsigned d = 0; d < dim_num_; ++d)
316-
dimension_ptrs_[d]->crop_range(&(*ndrange)[d]);
316+
for (unsigned d = 0; d < dim_num_; ++d) {
317+
auto type = dimension_ptrs_[d]->type();
318+
auto g = [&](auto T) {
319+
if constexpr (tiledb::type::TileDBIntegral<decltype(T)>) {
320+
tiledb::type::crop_range<decltype(T)>(
321+
dimension_ptrs_[d]->domain(), (*ndrange)[d]);
322+
} else {
323+
throw std::invalid_argument(
324+
"Unsupported dimension datatype " + datatype_str(type));
325+
}
326+
};
327+
apply_with_type(g, type);
328+
}
317329
}
318330

319331
shared_ptr<Domain> Domain::deserialize(

tiledb/type/range/range.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "tiledb/common/tag.h"
3939
#include "tiledb/sm/enums/datatype.h"
4040

41+
#include <algorithm>
4142
#include <cmath>
4243
#include <cstring>
4344
#include <sstream>
@@ -461,8 +462,8 @@ template <
461462
void crop_range(const Range& bounds, Range& range) {
462463
auto bounds_data = (const T*)bounds.data();
463464
auto range_data = (T*)range.data();
464-
range_data[0] = std::max(bounds_data[0], range_data[0]);
465-
range_data[1] = std::min(bounds_data[1], range_data[1]);
465+
range_data[0] = std::clamp(range_data[0], bounds_data[0], bounds_data[1]);
466+
range_data[1] = std::clamp(range_data[1], bounds_data[0], bounds_data[1]);
466467
};
467468

468469
/**

tiledb/type/range/test/unit_crop_range.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ TEMPLATE_TEST_CASE(
8989
std::numeric_limits<TestType>::max()};
9090
test_crop_range<TestType>(bounds, range, bounds);
9191
}
92+
SECTION("Test crop outside lower bound") {
93+
TestType range[2]{0, 0};
94+
TestType result[2]{1, 1};
95+
test_crop_range<TestType>(bounds, range, result);
96+
}
97+
SECTION("Test crop outside upper bound") {
98+
TestType range[2]{5, 6};
99+
TestType result[2]{4, 4};
100+
test_crop_range<TestType>(bounds, range, result);
101+
}
92102
}
93103

94104
TEMPLATE_TEST_CASE(
@@ -126,6 +136,16 @@ TEMPLATE_TEST_CASE(
126136
std::numeric_limits<TestType>::max()};
127137
test_crop_range<TestType>(bounds, range, bounds);
128138
}
139+
SECTION("Test crop outside lower bound") {
140+
TestType range[2]{-6, -4};
141+
TestType result[2]{-2, -2};
142+
test_crop_range<TestType>(bounds, range, result);
143+
}
144+
SECTION("Test crop outside upper bound") {
145+
TestType range[2]{5, 6};
146+
TestType result[2]{2, 2};
147+
test_crop_range<TestType>(bounds, range, result);
148+
}
129149
}
130150

131151
TEMPLATE_TEST_CASE(
@@ -164,4 +184,14 @@ TEMPLATE_TEST_CASE(
164184
std::numeric_limits<TestType>::infinity()};
165185
test_crop_range<TestType>(bounds, range, bounds);
166186
}
187+
SECTION("Test crop outside lower bound") {
188+
TestType range[2]{-60.1f, -40.3f};
189+
TestType result[2]{-10.5f, -10.5f};
190+
test_crop_range<TestType>(bounds, range, result);
191+
}
192+
SECTION("Test crop outside upper bound") {
193+
TestType range[2]{5.1f, 6.5f};
194+
TestType result[2]{3.33f, 3.33f};
195+
test_crop_range<TestType>(bounds, range, result);
196+
}
167197
}

0 commit comments

Comments
 (0)