Skip to content

Commit

Permalink
Refactored RTree towards addressing #93
Browse files Browse the repository at this point in the history
  • Loading branch information
stavrospapadopoulos committed Feb 20, 2020
1 parent 6d6dce5 commit 158f529
Show file tree
Hide file tree
Showing 16 changed files with 853 additions and 838 deletions.
407 changes: 228 additions & 179 deletions test/src/unit-rtree.cc

Large diffs are not rendered by default.

177 changes: 175 additions & 2 deletions tiledb/sm/array_schema/dimension.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ Dimension::Dimension() {
set_expand_range_v_func();
set_expand_to_tile_func();
set_oob_func();
set_covered_func();
set_overlap_func();
set_overlap_ratio_func();
set_tile_num_func();
set_value_in_range_func();
}
Expand All @@ -73,7 +75,9 @@ Dimension::Dimension(const std::string& name, Datatype type)
set_expand_range_v_func();
set_expand_to_tile_func();
set_oob_func();
set_covered_func();
set_overlap_func();
set_overlap_ratio_func();
set_tile_num_func();
set_value_in_range_func();
}
Expand Down Expand Up @@ -218,7 +222,9 @@ Status Dimension::deserialize(ConstBuffer* buff, Datatype type) {
set_expand_range_v_func();
set_expand_to_tile_func();
set_oob_func();
set_covered_func();
set_overlap_func();
set_overlap_ratio_func();
set_tile_num_func();
set_value_in_range_func();

Expand Down Expand Up @@ -379,6 +385,27 @@ bool Dimension::oob(const void* coord, std::string* err_msg) const {
return oob_func_(this, coord, err_msg);
}

template <class T>
bool Dimension::covered(
const Dimension* dim, const Range& r1, const Range& r2) {
assert(dim != nullptr);
assert(!r1.empty());
assert(!r2.empty());
(void)dim; // Not used here

auto d1 = (const T*)r1.data();
auto d2 = (const T*)r2.data();
assert(d1[0] <= d1[1]);
assert(d2[0] <= d2[1]);

return d1[0] >= d2[0] && d1[1] <= d2[1];
}

bool Dimension::covered(const Range& r1, const Range& r2) const {
assert(covered_func_ != nullptr);
return covered_func_(this, r1, r2);
}

template <class T>
bool Dimension::overlap(
const Dimension* dim, const Range& r1, const Range& r2) {
Expand All @@ -397,6 +424,46 @@ bool Dimension::overlap(const Range& r1, const Range& r2) const {
return overlap_func_(this, r1, r2);
}

template <class T>
double Dimension::overlap_ratio(
const Dimension* dim, const Range& r1, const Range& r2) {
assert(dim != nullptr);
assert(!r1.empty());
assert(!r2.empty());
(void)dim; // Not used here

auto d1 = (const T*)r1.data();
auto d2 = (const T*)r2.data();
assert(d1[0] <= d1[1]);
assert(d2[0] <= d2[1]);

// No overlap
if (d1[0] > d2[1] || d1[1] < d2[0])
return 0.0;

// Compute ratio
auto overlap_start = std::max(d1[0], d2[0]);
auto overlap_end = std::min(d1[1], d2[1]);
auto overlap_range = overlap_end - overlap_start;
auto mbr_range = d2[1] - d2[0];
auto max = std::numeric_limits<double>::max();
if (std::numeric_limits<T>::is_integer) {
overlap_range += 1;
mbr_range += 1;
} else {
if (overlap_range == 0)
overlap_range = std::nextafter(overlap_range, max);
if (mbr_range == 0)
mbr_range = std::nextafter(mbr_range, max);
}
return (double)overlap_range / mbr_range;
}

double Dimension::overlap_ratio(const Range& r1, const Range& r2) const {
assert(overlap_ratio_func_ != nullptr);
return overlap_ratio_func_(this, r1, r2);
}

template <class T>
uint64_t Dimension::tile_num(const Dimension* dim, const Range& range) {
assert(dim != nullptr);
Expand Down Expand Up @@ -494,8 +561,8 @@ Status Dimension::set_domain(const void* domain) {

Status Dimension::set_tile_extent(const void* tile_extent) {
if (domain_ == nullptr)
return Status::DimensionError(
"Cannot set tile extent; Domain must be set first");
return LOG_STATUS(Status::DimensionError(
"Cannot set tile extent; Domain must be set first"));

// Note: this check was added in release 1.6.0. Older arrays may have been
// serialized with a null extent, and so it is still supported internally.
Expand Down Expand Up @@ -1085,6 +1152,59 @@ void Dimension::set_oob_func() {
}
}

void Dimension::set_covered_func() {
switch (type_) {
case Datatype::INT32:
covered_func_ = covered<int32_t>;
break;
case Datatype::INT64:
covered_func_ = covered<int64_t>;
break;
case Datatype::INT8:
covered_func_ = covered<int8_t>;
break;
case Datatype::UINT8:
covered_func_ = covered<uint8_t>;
break;
case Datatype::INT16:
covered_func_ = covered<int16_t>;
break;
case Datatype::UINT16:
covered_func_ = covered<uint16_t>;
break;
case Datatype::UINT32:
covered_func_ = covered<uint32_t>;
break;
case Datatype::UINT64:
covered_func_ = covered<uint64_t>;
break;
case Datatype::FLOAT32:
covered_func_ = covered<float>;
break;
case Datatype::FLOAT64:
covered_func_ = covered<double>;
break;
case Datatype::DATETIME_YEAR:
case Datatype::DATETIME_MONTH:
case Datatype::DATETIME_WEEK:
case Datatype::DATETIME_DAY:
case Datatype::DATETIME_HR:
case Datatype::DATETIME_MIN:
case Datatype::DATETIME_SEC:
case Datatype::DATETIME_MS:
case Datatype::DATETIME_US:
case Datatype::DATETIME_NS:
case Datatype::DATETIME_PS:
case Datatype::DATETIME_FS:
case Datatype::DATETIME_AS:
covered_func_ = covered<int64_t>;
break;
default:
covered_func_ = nullptr;
break;
}
}

void Dimension::set_overlap_func() {
switch (type_) {
case Datatype::INT32:
Expand Down Expand Up @@ -1138,6 +1258,59 @@ void Dimension::set_overlap_func() {
}
}

void Dimension::set_overlap_ratio_func() {
switch (type_) {
case Datatype::INT32:
overlap_ratio_func_ = overlap_ratio<int32_t>;
break;
case Datatype::INT64:
overlap_ratio_func_ = overlap_ratio<int64_t>;
break;
case Datatype::INT8:
overlap_ratio_func_ = overlap_ratio<int8_t>;
break;
case Datatype::UINT8:
overlap_ratio_func_ = overlap_ratio<uint8_t>;
break;
case Datatype::INT16:
overlap_ratio_func_ = overlap_ratio<int16_t>;
break;
case Datatype::UINT16:
overlap_ratio_func_ = overlap_ratio<uint16_t>;
break;
case Datatype::UINT32:
overlap_ratio_func_ = overlap_ratio<uint32_t>;
break;
case Datatype::UINT64:
overlap_ratio_func_ = overlap_ratio<uint64_t>;
break;
case Datatype::FLOAT32:
overlap_ratio_func_ = overlap_ratio<float>;
break;
case Datatype::FLOAT64:
overlap_ratio_func_ = overlap_ratio<double>;
break;
case Datatype::DATETIME_YEAR:
case Datatype::DATETIME_MONTH:
case Datatype::DATETIME_WEEK:
case Datatype::DATETIME_DAY:
case Datatype::DATETIME_HR:
case Datatype::DATETIME_MIN:
case Datatype::DATETIME_SEC:
case Datatype::DATETIME_MS:
case Datatype::DATETIME_US:
case Datatype::DATETIME_NS:
case Datatype::DATETIME_PS:
case Datatype::DATETIME_FS:
case Datatype::DATETIME_AS:
overlap_ratio_func_ = overlap_ratio<int64_t>;
break;
default:
overlap_ratio_func_ = nullptr;
break;
}
}

void Dimension::set_tile_num_func() {
switch (type_) {
case Datatype::INT32:
Expand Down
35 changes: 35 additions & 0 deletions tiledb/sm/array_schema/dimension.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,28 @@ class Dimension {
static bool oob(
const Dimension* dim, const void* coord, std::string* err_msg);

/** Return true if r1 is fully covered by r2. */
bool covered(const Range& r1, const Range& r2) const;

/** Return true if r1 is fully covered by r2. */
template <class T>
static bool covered(const Dimension* dim, const Range& r1, const Range& r2);

/** Return true if the input 1D ranges overlap. */
bool overlap(const Range& r1, const Range& r2) const;

/** Return true if the input 1D ranges overlap. */
template <class T>
static bool overlap(const Dimension* dim, const Range& r1, const Range& r2);

/** Return ratio of the overalp of the two input 1D ranges over `r2`. */
double overlap_ratio(const Range& r1, const Range& r2) const;

/** Return ratio of the overalp of the two input 1D ranges over `r2`. */
template <class T>
static double overlap_ratio(
const Dimension* dim, const Range& r1, const Range& r2);

/** Return the number of tiles the input range intersects. */
uint64_t tile_num(const Range& range) const;

Expand Down Expand Up @@ -312,13 +327,27 @@ class Dimension {
std::function<bool(const Dimension* dim, const void*, std::string*)>
oob_func_;

/**
* Stores the appropriate templated covered() function based on the
* dimension datatype.
*/
std::function<bool(const Dimension* dim, const Range&, const Range&)>
covered_func_;

/**
* Stores the appropriate templated overlap() function based on the
* dimension datatype.
*/
std::function<bool(const Dimension* dim, const Range&, const Range&)>
overlap_func_;

/**
* Stores the appropriate templated overlap_ratio() function based on the
* dimension datatype.
*/
std::function<double(const Dimension* dim, const Range&, const Range&)>
overlap_ratio_func_;

/**
* Stores the appropriate templated tile_num() function based on the
* dimension datatype.
Expand Down Expand Up @@ -431,9 +460,15 @@ class Dimension {
/** Sets the templated oob() function. */
void set_oob_func();

/** Sets the templated covered() function. */
void set_covered_func();

/** Sets the templated overlap() function. */
void set_overlap_func();

/** Sets the templated overlap_ratio() function. */
void set_overlap_ratio_func();

/** Sets the templated tile_num() function. */
void set_tile_num_func();

Expand Down
46 changes: 46 additions & 0 deletions tiledb/sm/array_schema/domain.cc
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,15 @@ void Domain::dump(FILE* out) const {
}

void Domain::expand_ndrange(const NDRange& r1, NDRange* r2) const {
assert(r2 != nullptr);

// Assign r1 to r2 if r2 is empty
if (r2->empty()) {
*r2 = r1;
return;
}

// Expand r2 along all dimensions
for (unsigned d = 0; d < dim_num_; ++d)
dimensions_[d]->expand_range(r1[d], &(*r2)[d]);
}
Expand Down Expand Up @@ -922,7 +931,22 @@ uint64_t Domain::tile_num(const NDRange& ndrange) const {
return ret;
}

bool Domain::covered(const NDRange& r1, const NDRange& r2) const {
assert(r1.size() == dim_num_);
assert(r2.size() == dim_num_);

for (unsigned d = 0; d < dim_num_; ++d) {
if (!dimensions_[d]->covered(r1[d], r2[d]))
return false;
}

return true;
}

bool Domain::overlap(const NDRange& r1, const NDRange& r2) const {
assert(r1.size() == dim_num_);
assert(r2.size() == dim_num_);

for (unsigned d = 0; d < dim_num_; ++d) {
if (!dimensions_[d]->overlap(r1[d], r2[d]))
return false;
Expand All @@ -931,6 +955,28 @@ bool Domain::overlap(const NDRange& r1, const NDRange& r2) const {
return true;
}

double Domain::overlap_ratio(const NDRange& r1, const NDRange& r2) const {
double ratio = 1.0;
assert(dim_num_ == r1.size());
assert(dim_num_ == r2.size());

for (unsigned d = 0; d < dim_num_; ++d) {
if (!dimensions_[d]->overlap(r1[d], r2[d]))
return 0.0;

ratio *= dimensions_[d]->overlap_ratio(r1[d], r2[d]);

// If ratio goes to 0, then the subarray overlap is much smaller than the
// volume of the MBR. Since we have already guaranteed that there is an
// overlap above, we should set the ratio to epsilon.
auto max = std::numeric_limits<double>::max();
if (ratio == 0)
ratio = std::nextafter(0, max);
}

return ratio;
}

template <class T>
int Domain::tile_order_cmp(
const Dimension* dim, const void* coord_a, const void* coord_b) {
Expand Down
9 changes: 9 additions & 0 deletions tiledb/sm/array_schema/domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -589,9 +589,18 @@ class Domain {
*/
uint64_t tile_num(const NDRange& ndrange) const;

/** Returns true if r1 is fully covered by r2. */
bool covered(const NDRange& r1, const NDRange& r2) const;

/** Returns true if the two ND ranges overlap. */
bool overlap(const NDRange& r1, const NDRange& r2) const;

/**
* Return ratio of the overalp of the two input ND ranges over
* the volume of `r2`.
*/
double overlap_ratio(const NDRange& r1, const NDRange& r2) const;

/**
* Checks the tile order of the input coordinates on the given dimension.
*
Expand Down
Loading

0 comments on commit 158f529

Please sign in to comment.