1 /**
2 * @file dimension.cc
3 *
4 * @section LICENSE
5 *
6 * The MIT License
7 *
8 * @copyright Copyright (c) 2017-2021 TileDB, Inc.
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
27 *
28 * @section DESCRIPTION
29 *
30 * This file implements class Dimension.
31 */
32
33 #include "tiledb/sm/array_schema/dimension.h"
34 #include "tiledb/common/logger.h"
35 #include "tiledb/sm/buffer/buffer.h"
36 #include "tiledb/sm/enums/datatype.h"
37 #include "tiledb/sm/enums/filter_type.h"
38 #include "tiledb/sm/misc/utils.h"
39
40 #include <bitset>
41 #include <cassert>
42 #include <cmath>
43 #include <iostream>
44
45 using namespace tiledb::common;
46
blank()47 tiledb::common::blank<tiledb::sm::Dimension>::blank()
48 : tiledb::sm::Dimension{"", tiledb::sm::Datatype::INT32} {
49 }
50
51 namespace tiledb {
52 namespace sm {
53
54 /* ********************************* */
55 /* CONSTRUCTORS & DESTRUCTORS */
56 /* ********************************* */
57
Dimension(const std::string & name,Datatype type)58 Dimension::Dimension(const std::string& name, Datatype type)
59 : name_(name)
60 , type_(type) {
61 cell_val_num_ = (datatype_is_string(type)) ? constants::var_num : 1;
62 set_ceil_to_tile_func();
63 set_check_range_func();
64 set_adjust_range_oob_func();
65 set_coincides_with_tiles_func();
66 set_compute_mbr_func();
67 set_crop_range_func();
68 set_domain_range_func();
69 set_expand_range_func();
70 set_expand_range_v_func();
71 set_expand_to_tile_func();
72 set_oob_func();
73 set_covered_func();
74 set_overlap_func();
75 set_overlap_ratio_func();
76 set_split_range_func();
77 set_splitting_value_func();
78 set_tile_num_func();
79 set_map_to_uint64_func();
80 set_map_to_uint64_2_func();
81 set_map_to_uint64_3_func();
82 set_map_from_uint64_func();
83 set_smaller_than_func();
84 }
85
Dimension(const Dimension * dim)86 Dimension::Dimension(const Dimension* dim) {
87 assert(dim != nullptr);
88
89 cell_val_num_ = dim->cell_val_num_;
90 filters_ = dim->filters_;
91 name_ = dim->name();
92 type_ = dim->type_;
93
94 // Set fuctions
95 adjust_range_oob_func_ = dim->adjust_range_oob_func_;
96 ceil_to_tile_func_ = dim->ceil_to_tile_func_;
97 check_range_func_ = dim->check_range_func_;
98 coincides_with_tiles_func_ = dim->coincides_with_tiles_func_;
99 compute_mbr_func_ = dim->compute_mbr_func_;
100 crop_range_func_ = dim->crop_range_func_;
101 domain_range_func_ = dim->domain_range_func_;
102 expand_range_v_func_ = dim->expand_range_v_func_;
103 expand_range_func_ = dim->expand_range_func_;
104 expand_to_tile_func_ = dim->expand_to_tile_func_;
105 oob_func_ = dim->oob_func_;
106 covered_func_ = dim->covered_func_;
107 overlap_func_ = dim->overlap_func_;
108 overlap_ratio_func_ = dim->overlap_ratio_func_;
109 split_range_func_ = dim->split_range_func_;
110 splitting_value_func_ = dim->splitting_value_func_;
111 tile_num_func_ = dim->tile_num_func_;
112 map_to_uint64_func_ = dim->map_to_uint64_func_;
113 map_to_uint64_2_func_ = dim->map_to_uint64_2_func_;
114 map_to_uint64_3_func_ = dim->map_to_uint64_3_func_;
115 map_from_uint64_func_ = dim->map_from_uint64_func_;
116 smaller_than_func_ = dim->smaller_than_func_;
117
118 domain_ = dim->domain();
119 tile_extent_ = dim->tile_extent();
120 }
121
122 /* ********************************* */
123 /* API */
124 /* ********************************* */
125
cell_val_num() const126 unsigned int Dimension::cell_val_num() const {
127 return cell_val_num_;
128 }
129
set_cell_val_num(unsigned int cell_val_num)130 Status Dimension::set_cell_val_num(unsigned int cell_val_num) {
131 // Error checkls
132 if (datatype_is_string(type_) && cell_val_num != constants::var_num)
133 return LOG_STATUS(
134 Status::DimensionError("Cannot set non-variable number of values per "
135 "coordinate for a string dimension"));
136 if (!datatype_is_string(type_) && cell_val_num != 1)
137 return LOG_STATUS(Status::DimensionError(
138 "Cannot set number of values per coordinate; Currently only one value "
139 "per coordinate is supported"));
140
141 cell_val_num_ = cell_val_num;
142
143 return Status::Ok();
144 }
145
coord_size() const146 uint64_t Dimension::coord_size() const {
147 return datatype_size(type_);
148 }
149
coord_to_str(const QueryBuffer & buff,uint64_t i) const150 std::string Dimension::coord_to_str(const QueryBuffer& buff, uint64_t i) const {
151 std::stringstream ss;
152
153 // Fixed sized
154 if (!var_size()) {
155 auto cbuff = (const unsigned char*)buff.buffer_;
156 auto coord = cbuff + i * coord_size();
157
158 switch (type_) {
159 case Datatype::INT32:
160 ss << *((int32_t*)coord);
161 break;
162 case Datatype::INT64:
163 ss << *((int64_t*)coord);
164 break;
165 case Datatype::INT8:
166 ss << *((int8_t*)coord);
167 break;
168 case Datatype::UINT8:
169 ss << *((uint8_t*)coord);
170 break;
171 case Datatype::INT16:
172 ss << *((int16_t*)coord);
173 break;
174 case Datatype::UINT16:
175 ss << *((uint16_t*)coord);
176 break;
177 case Datatype::UINT32:
178 ss << *((uint32_t*)coord);
179 break;
180 case Datatype::UINT64:
181 ss << *((uint64_t*)coord);
182 break;
183 case Datatype::FLOAT32:
184 ss << *((float*)coord);
185 break;
186 case Datatype::FLOAT64:
187 ss << *((double*)coord);
188 break;
189 case Datatype::DATETIME_YEAR:
190 case Datatype::DATETIME_MONTH:
191 case Datatype::DATETIME_WEEK:
192 case Datatype::DATETIME_DAY:
193 case Datatype::DATETIME_HR:
194 case Datatype::DATETIME_MIN:
195 case Datatype::DATETIME_SEC:
196 case Datatype::DATETIME_MS:
197 case Datatype::DATETIME_US:
198 case Datatype::DATETIME_NS:
199 case Datatype::DATETIME_PS:
200 case Datatype::DATETIME_FS:
201 case Datatype::DATETIME_AS:
202 case Datatype::TIME_HR:
203 case Datatype::TIME_MIN:
204 case Datatype::TIME_SEC:
205 case Datatype::TIME_MS:
206 case Datatype::TIME_US:
207 case Datatype::TIME_NS:
208 case Datatype::TIME_PS:
209 case Datatype::TIME_FS:
210 case Datatype::TIME_AS:
211 ss << *((int64_t*)coord);
212 break;
213 default:
214 break;
215 }
216 } else { // Var-sized
217 assert(type_ == Datatype::STRING_ASCII);
218 auto offs = (const uint64_t*)buff.buffer_;
219 auto offs_size = *(buff.buffer_size_);
220 auto var_size = *(buff.buffer_var_size_);
221 auto vars = (const char*)buff.buffer_var_;
222 auto coord = &vars[offs[i]];
223 auto next_off = ((i + 1) * constants::cell_var_offset_size == offs_size) ?
224 var_size :
225 offs[i + 1];
226 auto coord_size = next_off - offs[i];
227 auto coord_str = std::string(coord, coord_size);
228 ss << coord_str;
229 }
230
231 return ss.str();
232 }
233
deserialize(ConstBuffer * buff,uint32_t version,Datatype type)234 Status Dimension::deserialize(
235 ConstBuffer* buff, uint32_t version, Datatype type) {
236 // Load dimension name
237 uint32_t dimension_name_size;
238 RETURN_NOT_OK(buff->read(&dimension_name_size, sizeof(uint32_t)));
239 name_.resize(dimension_name_size);
240 RETURN_NOT_OK(buff->read(&name_[0], dimension_name_size));
241
242 // Applicable only to version >= 5
243 if (version >= 5) {
244 // Load type
245 uint8_t type;
246 RETURN_NOT_OK(buff->read(&type, sizeof(uint8_t)));
247 type_ = (Datatype)type;
248
249 // Load cell_val_num_
250 RETURN_NOT_OK(buff->read(&cell_val_num_, sizeof(uint32_t)));
251
252 // Load filter pipeline
253 RETURN_NOT_OK(filters_.deserialize(buff));
254 } else {
255 type_ = type;
256 }
257
258 // Load domain
259 uint64_t domain_size = 0;
260 if (version >= 5) {
261 RETURN_NOT_OK(buff->read(&domain_size, sizeof(uint64_t)));
262 } else {
263 domain_size = 2 * coord_size();
264 }
265 if (domain_size != 0) {
266 std::vector<uint8_t> tmp(domain_size);
267 RETURN_NOT_OK(buff->read(&tmp[0], domain_size));
268 domain_ = Range(&tmp[0], domain_size);
269 }
270
271 // Load tile extent
272 tile_extent_.assign_as_void();
273 uint8_t null_tile_extent;
274 RETURN_NOT_OK(buff->read(&null_tile_extent, sizeof(uint8_t)));
275 if (null_tile_extent == 0) {
276 tile_extent_.resize(coord_size());
277 RETURN_NOT_OK(buff->read(tile_extent_.data(), coord_size()));
278 }
279
280 set_ceil_to_tile_func();
281 set_check_range_func();
282 set_adjust_range_oob_func();
283 set_coincides_with_tiles_func();
284 set_compute_mbr_func();
285 set_crop_range_func();
286 set_domain_range_func();
287 set_expand_range_func();
288 set_expand_range_v_func();
289 set_expand_to_tile_func();
290 set_oob_func();
291 set_covered_func();
292 set_overlap_func();
293 set_overlap_ratio_func();
294 set_split_range_func();
295 set_splitting_value_func();
296 set_tile_num_func();
297 set_map_to_uint64_func();
298 set_map_to_uint64_2_func();
299 set_map_to_uint64_3_func();
300 set_map_from_uint64_func();
301 set_smaller_than_func();
302
303 return Status::Ok();
304 }
305
domain() const306 const Range& Dimension::domain() const {
307 return domain_;
308 }
309
dump(FILE * out) const310 void Dimension::dump(FILE* out) const {
311 if (out == nullptr)
312 out = stdout;
313 // Retrieve domain and tile extent strings
314 std::string domain_s = domain_str();
315 std::string tile_extent_s = tile_extent_str();
316
317 // Dump
318 fprintf(out, "### Dimension ###\n");
319 fprintf(out, "- Name: %s\n", name_.c_str());
320 fprintf(out, "- Type: %s\n", datatype_str(type_).c_str());
321 if (!var_size())
322 fprintf(out, "- Cell val num: %u\n", cell_val_num_);
323 else
324 fprintf(out, "- Cell val num: var\n");
325 fprintf(out, "- Domain: %s\n", domain_s.c_str());
326 fprintf(out, "- Tile extent: %s\n", tile_extent_s.c_str());
327 fprintf(out, "- Filters: %u", (unsigned)filters_.size());
328 filters_.dump(out);
329 fprintf(out, "\n");
330 }
331
filters() const332 const FilterPipeline& Dimension::filters() const {
333 return filters_;
334 }
335
name() const336 const std::string& Dimension::name() const {
337 return name_;
338 }
339
340 template <class T>
ceil_to_tile(const Dimension * dim,const Range & r,uint64_t tile_num,ByteVecValue * v)341 void Dimension::ceil_to_tile(
342 const Dimension* dim, const Range& r, uint64_t tile_num, ByteVecValue* v) {
343 assert(dim != nullptr);
344 assert(!r.empty());
345 assert(dim->tile_extent());
346
347 auto tile_extent = *(const T*)dim->tile_extent().data();
348 auto dim_dom = (const T*)dim->domain().data();
349 auto r_t = (const T*)r.data();
350
351 T mid = tile_coord_low(tile_num + 1, r_t[0], tile_extent);
352 uint64_t div = tile_idx(mid, dim_dom[0], tile_extent);
353 T floored_mid = tile_coord_low(div, dim_dom[0], tile_extent);
354 assert(v != nullptr);
355 v->assign_as<T>(
356 (std::is_integral<T>::value) ?
357 floored_mid - 1 :
358 static_cast<T>(
359 std::nextafter(floored_mid, std::numeric_limits<T>::lowest())));
360 }
361
ceil_to_tile(const Range & r,uint64_t tile_num,ByteVecValue * v) const362 void Dimension::ceil_to_tile(
363 const Range& r, uint64_t tile_num, ByteVecValue* v) const {
364 assert(ceil_to_tile_func_ != nullptr);
365 ceil_to_tile_func_(this, r, tile_num, v);
366 }
367
check_range(const Range & range) const368 Status Dimension::check_range(const Range& range) const {
369 // Inapplicable to string domains
370 if (type_ == Datatype::STRING_ASCII)
371 return Status::Ok();
372
373 assert(check_range_func_ != nullptr);
374 std::string err_msg;
375 auto ret = check_range_func_(this, range, &err_msg);
376 if (!ret)
377 return LOG_STATUS(Status::DimensionError(err_msg));
378 return Status::Ok();
379 }
380
adjust_range_oob(Range * range) const381 Status Dimension::adjust_range_oob(Range* range) const {
382 // Inapplicable to string domains
383 if (type_ == Datatype::STRING_ASCII)
384 return Status::Ok();
385
386 assert(adjust_range_oob_func_ != nullptr);
387 adjust_range_oob_func_(this, range);
388 return Status::Ok();
389 }
390
391 template <class T>
coincides_with_tiles(const Dimension * dim,const Range & r)392 bool Dimension::coincides_with_tiles(const Dimension* dim, const Range& r) {
393 assert(dim != nullptr);
394 assert(!r.empty());
395 assert(dim->tile_extent());
396
397 auto dim_domain = (const T*)dim->domain().data();
398 auto tile_extent = *(const T*)dim->tile_extent().data();
399 auto d = (const T*)r.data();
400 auto rounded_1 = Dimension::round_to_tile(d[0], dim_domain[0], tile_extent);
401 auto rounded_2 =
402 Dimension::round_to_tile(T(d[1] + 1), dim_domain[0], tile_extent);
403 return (rounded_1 == d[0]) && (rounded_2 == T(d[1] + 1));
404 }
405
coincides_with_tiles(const Range & r) const406 bool Dimension::coincides_with_tiles(const Range& r) const {
407 assert(coincides_with_tiles_func_ != nullptr);
408 return coincides_with_tiles_func_(this, r);
409 }
410
411 template <class T>
compute_mbr(const Tile & tile,Range * mbr)412 Status Dimension::compute_mbr(const Tile& tile, Range* mbr) {
413 assert(mbr != nullptr);
414 auto cell_num = tile.cell_num();
415 assert(cell_num > 0);
416
417 void* tile_buffer = tile.buffer()->data();
418 assert(tile_buffer != nullptr);
419
420 // Initialize MBR with the first tile values
421 const T* const data = static_cast<T*>(tile_buffer);
422 T res[] = {data[0], data[0]};
423 mbr->set_range(res, sizeof(res));
424
425 // Expand the MBR with the rest tile values
426 for (uint64_t c = 1; c < cell_num; ++c)
427 expand_range_v<T>(&data[c], mbr);
428
429 return Status::Ok();
430 }
431
compute_mbr(const Tile & tile,Range * mbr) const432 Status Dimension::compute_mbr(const Tile& tile, Range* mbr) const {
433 assert(compute_mbr_func_ != nullptr);
434 return compute_mbr_func_(tile, mbr);
435 }
436
437 template <>
compute_mbr_var(const Tile & tile_off,const Tile & tile_val,Range * mbr)438 Status Dimension::compute_mbr_var<char>(
439 const Tile& tile_off, const Tile& tile_val, Range* mbr) {
440 assert(mbr != nullptr);
441 auto d_val_size = tile_val.size();
442 auto cell_num = tile_off.cell_num();
443 assert(cell_num > 0);
444
445 void* tile_buffer_off = tile_off.buffer()->data();
446 assert(tile_buffer_off != nullptr);
447
448 void* tile_buffer_val = tile_val.buffer()->data();
449 assert(tile_buffer_val != nullptr);
450
451 uint64_t* const d_off = static_cast<uint64_t*>(tile_buffer_off);
452 char* const d_val = static_cast<char*>(tile_buffer_val);
453
454 // Initialize MBR with the first tile values
455 auto size_0 = (cell_num == 1) ? d_val_size : d_off[1];
456 mbr->set_range_var(d_val, size_0, d_val, size_0);
457
458 // Expand the MBR with the rest tile values
459 for (uint64_t c = 1; c < cell_num; ++c) {
460 auto size =
461 (c == cell_num - 1) ? d_val_size - d_off[c] : d_off[c + 1] - d_off[c];
462 expand_range_var_v(&d_val[d_off[c]], size, mbr);
463 }
464
465 return Status::Ok();
466 }
467
compute_mbr_var(const Tile & tile_off,const Tile & tile_val,Range * mbr) const468 Status Dimension::compute_mbr_var(
469 const Tile& tile_off, const Tile& tile_val, Range* mbr) const {
470 assert(compute_mbr_var_func_ != nullptr);
471 return compute_mbr_var_func_(tile_off, tile_val, mbr);
472 }
473
474 template <class T>
crop_range(const Dimension * dim,Range * range)475 void Dimension::crop_range(const Dimension* dim, Range* range) {
476 assert(dim != nullptr);
477 assert(!range->empty());
478 auto dim_dom = (const T*)dim->domain().data();
479 auto r = (const T*)range->data();
480 T res[2] = {std::max(r[0], dim_dom[0]), std::min(r[1], dim_dom[1])};
481 range->set_range(res, sizeof(res));
482 }
483
crop_range(Range * range) const484 void Dimension::crop_range(Range* range) const {
485 assert(crop_range_func_ != nullptr);
486 crop_range_func_(this, range);
487 }
488
489 template <class T>
domain_range(const Range & range)490 uint64_t Dimension::domain_range(const Range& range) {
491 assert(!range.empty());
492
493 // Inapplicable to real domains
494 if (!std::is_integral<T>::value)
495 return std::numeric_limits<uint64_t>::max();
496
497 auto r = (const T*)range.data();
498 uint64_t ret = r[1] - r[0];
499 if (ret == std::numeric_limits<uint64_t>::max()) // overflow
500 return ret;
501 ++ret;
502
503 return ret;
504 }
505
domain_range(const Range & range) const506 uint64_t Dimension::domain_range(const Range& range) const {
507 assert(domain_range_func_ != nullptr);
508 return domain_range_func_(range);
509 }
510
511 template <class T>
expand_range_v(const void * v,Range * r)512 void Dimension::expand_range_v(const void* v, Range* r) {
513 assert(v != nullptr);
514 assert(r != nullptr);
515 assert(!r->empty());
516 auto rt = (const T*)r->data();
517 auto vt = (const T*)v;
518 T res[2] = {std::min(rt[0], *vt), std::max(rt[1], *vt)};
519 r->set_range(res, sizeof(res));
520 }
521
expand_range_v(const void * v,Range * r) const522 void Dimension::expand_range_v(const void* v, Range* r) const {
523 assert(expand_range_v_func_ != nullptr);
524 expand_range_v_func_(v, r);
525 }
526
expand_range_var_v(const char * v,uint64_t v_size,Range * r)527 void Dimension::expand_range_var_v(const char* v, uint64_t v_size, Range* r) {
528 assert(v != nullptr);
529 assert(r != nullptr);
530
531 auto start = r->start_str();
532 auto end = r->end_str();
533 auto v_str = std::string(v, v_size);
534
535 r->set_str_range(
536 (v_str < start) ? v_str : start, (v_str > end) ? v_str : end);
537 }
538
539 template <class T>
expand_range(const Range & r1,Range * r2)540 void Dimension::expand_range(const Range& r1, Range* r2) {
541 assert(!r1.empty());
542 assert(!r2->empty());
543 auto d1 = (const T*)r1.data();
544 auto d2 = (const T*)r2->data();
545 T res[2] = {std::min(d1[0], d2[0]), std::max(d1[1], d2[1])};
546 r2->set_range(res, sizeof(res));
547 }
548
expand_range(const Range & r1,Range * r2) const549 void Dimension::expand_range(const Range& r1, Range* r2) const {
550 assert(expand_range_func_ != nullptr);
551 expand_range_func_(r1, r2);
552 }
553
expand_range_var(const Range & r1,Range * r2) const554 void Dimension::expand_range_var(const Range& r1, Range* r2) const {
555 assert(type_ == Datatype::STRING_ASCII);
556
557 auto r1_start = r1.start_str();
558 auto r1_end = r1.end_str();
559
560 auto r2_start = r2->start_str();
561 auto r2_end = r2->end_str();
562
563 auto min = (r1_start < r2_start) ? r1_start : r2_start;
564 auto max = (r1_end < r2_end) ? r2_end : r1_end;
565
566 r2->set_str_range(min, max);
567 }
568
569 template <class T>
expand_to_tile(const Dimension * dim,Range * range)570 void Dimension::expand_to_tile(const Dimension* dim, Range* range) {
571 assert(dim != nullptr);
572 assert(!range->empty());
573
574 // Applicable only to regular tiles and integral domains
575 if (!dim->tile_extent() || !std::is_integral<T>::value)
576 return;
577
578 auto tile_extent = *(const T*)dim->tile_extent().data();
579 auto dim_dom = (const T*)dim->domain().data();
580 auto r = (const T*)range->data();
581 auto tile_idx1 = tile_idx(r[0], dim_dom[0], tile_extent);
582 auto tile_idx2 = tile_idx(r[1], dim_dom[0], tile_extent);
583
584 T res[2];
585 res[0] = tile_coord_low(tile_idx1, dim_dom[0], tile_extent);
586 res[1] = tile_coord_high(tile_idx2, dim_dom[0], tile_extent);
587
588 range->set_range(res, sizeof(res));
589 }
590
expand_to_tile(Range * range) const591 void Dimension::expand_to_tile(Range* range) const {
592 assert(expand_to_tile_func_ != nullptr);
593 expand_to_tile_func_(this, range);
594 }
595
596 template <class T>
oob(const Dimension * dim,const void * coord,std::string * err_msg)597 bool Dimension::oob(
598 const Dimension* dim, const void* coord, std::string* err_msg) {
599 auto domain = (const T*)dim->domain().data();
600 auto coord_t = (const T*)coord;
601 if (*coord_t < domain[0] || *coord_t > domain[1]) {
602 std::stringstream ss;
603 ss << "Coordinate " << *coord_t << " is out of domain bounds [" << domain[0]
604 << ", " << domain[1] << "] on dimension '" << dim->name() << "'";
605 *err_msg = ss.str();
606 return true;
607 }
608
609 return false;
610 }
611
oob(const void * coord) const612 Status Dimension::oob(const void* coord) const {
613 // Not applicable to string dimensions
614 if (datatype_is_string(type_))
615 return Status::Ok();
616
617 assert(oob_func_ != nullptr);
618 std::string err_msg;
619 auto ret = oob_func_(this, coord, &err_msg);
620 if (ret)
621 return Status::DimensionError(err_msg);
622 return Status::Ok();
623 }
624
625 template <>
covered(const Range & r1,const Range & r2)626 bool Dimension::covered<char>(const Range& r1, const Range& r2) {
627 auto r1_start = r1.start_str();
628 auto r1_end = r1.end_str();
629 auto r2_start = r2.start_str();
630 auto r2_end = r2.end_str();
631
632 auto r1_after_r2 =
633 !r1_start.empty() && !r2_start.empty() && r1_start >= r2_start;
634 auto r2_after_r1 = !r1_end.empty() && !r2_end.empty() && r1_end <= r2_end;
635
636 return r1_after_r2 && r2_after_r1;
637 }
638
639 template <class T>
covered(const Range & r1,const Range & r2)640 bool Dimension::covered(const Range& r1, const Range& r2) {
641 assert(!r1.empty());
642 assert(!r2.empty());
643
644 auto d1 = (const T*)r1.data();
645 auto d2 = (const T*)r2.data();
646 assert(d1[0] <= d1[1]);
647 assert(d2[0] <= d2[1]);
648
649 return d1[0] >= d2[0] && d1[1] <= d2[1];
650 }
651
covered(const Range & r1,const Range & r2) const652 bool Dimension::covered(const Range& r1, const Range& r2) const {
653 assert(covered_func_ != nullptr);
654 return covered_func_(r1, r2);
655 }
656
657 template <>
overlap(const Range & r1,const Range & r2)658 bool Dimension::overlap<char>(const Range& r1, const Range& r2) {
659 auto r1_start = r1.start_str();
660 auto r1_end = r1.end_str();
661 auto r2_start = r2.start_str();
662 auto r2_end = r2.end_str();
663
664 auto r1_after_r2 = !r1_start.empty() && !r2_end.empty() && r1_start > r2_end;
665 auto r2_after_r1 = !r2_start.empty() && !r1_end.empty() && r2_start > r1_end;
666
667 return !r1_after_r2 && !r2_after_r1;
668 }
669
670 template <class T>
overlap(const Range & r1,const Range & r2)671 bool Dimension::overlap(const Range& r1, const Range& r2) {
672 assert(!r1.empty());
673 assert(!r2.empty());
674
675 auto d1 = (const T*)r1.data();
676 auto d2 = (const T*)r2.data();
677 return !(d1[0] > d2[1] || d1[1] < d2[0]);
678 }
679
overlap(const Range & r1,const Range & r2) const680 bool Dimension::overlap(const Range& r1, const Range& r2) const {
681 assert(overlap_func_ != nullptr);
682 return overlap_func_(r1, r2);
683 }
684
685 template <>
overlap_ratio(const Range & r1,const Range & r2)686 double Dimension::overlap_ratio<char>(const Range& r1, const Range& r2) {
687 // An empty range spans the whole domain
688 if (r1.empty() || r2.empty())
689 return 1.0;
690
691 if (!overlap<char>(r1, r2))
692 return 0.0;
693
694 auto r1_start = r1.start_str();
695 auto r1_end = r1.end_str();
696 auto r2_start = r2.start_str();
697 auto r2_end = r2.end_str();
698 assert(!r2_start.empty());
699 assert(!r2_end.empty());
700
701 // Calculate the range of r2
702 uint64_t r2_range, pref_size = 0;
703 if (r2.unary()) {
704 r2_range = 1;
705 } else {
706 pref_size = utils::parse::common_prefix_size(r2_start, r2_end);
707 auto r2_start_c = (r2_start.size() == pref_size) ? 0 : r2_start[pref_size];
708 assert(r2_end.size() > pref_size);
709 r2_range = r2_end[pref_size] - r2_start_c + 1;
710 }
711
712 // Calculate the overlap and its range
713 uint64_t o_range;
714 auto o_start =
715 (!r1_start.empty() && r1_start > r2_start) ? r1_start : r2_start;
716 auto o_end = (!r1_end.empty() && r1_end < r2_end) ? r1_end : r2_end;
717 if (o_start == o_end) {
718 o_range = 1;
719 } else {
720 assert(o_end.size() > pref_size);
721 auto o_start_c = (o_start.size() == pref_size) ? 0 : o_start[pref_size];
722 o_range = o_end[pref_size] - o_start_c + 1;
723 }
724
725 // If the overlap is not equal to r2, then the ratio cannot be
726 // 1.0 - reduce it by epsilon
727 auto ratio = (double)o_range / r2_range;
728 if (ratio == 1.0 && (o_start != r2_start || o_end != r2_end))
729 ratio = std::nextafter(ratio, std::numeric_limits<double>::min());
730
731 return ratio;
732 }
733
734 template <class T>
overlap_ratio(const Range & r1,const Range & r2)735 double Dimension::overlap_ratio(const Range& r1, const Range& r2) {
736 // Verify that we have two intervals
737 assert(!r1.empty());
738 assert(!r2.empty());
739 auto d1 = (const T*)r1.data();
740 auto d2 = (const T*)r2.data();
741 const auto r1_low = d1[0];
742 const auto r1_high = d1[1];
743 auto r2_low = d2[0];
744 auto r2_high = d2[1];
745 assert(r1_low <= r1_high);
746 assert(r2_low <= r2_high);
747
748 // Special case: No overlap, intervals are disjoint
749 if (r1_low > r2_high || r1_high < r2_low)
750 return 0.0;
751 // Special case: All overlap, interval r2 is a subset of interval r1
752 if (r1_low <= r2_low && r2_high <= r1_high)
753 return 1.0;
754 /*
755 * At this point we know that r2_low < r2_high, because we would have returned
756 * by now otherwise. Note that for floating point types, however, we cannot
757 * conclude that r2_high - r2_low > 0 because of the possibility of underflow.
758 */
759 auto intersection_low = std::max(r1_low, r2_low);
760 auto intersection_high = std::min(r1_high, r2_high);
761 /*
762 * The intersection is a proper subset of interval r1, either the upper bounds
763 * are distinct, or lower bounds are distinct, or both. This means that any
764 * result has to be strictly greater than zero and strictly less than 1.
765 */
766 /*
767 * Guard against overflow. If the outer interval has a bound with an absolute
768 * value that's "too large", meaning that it might lead to an overflow, we
769 * apply a shrinking transformation that preserves the ratio. We only need to
770 * check the outer interval because the intersection is strictly smaller. For
771 * unsigned types we only need to check the upper bound, since the lower bound
772 * is zero. For signed types we need to check both.
773 */
774 const T safe_upper = std::nextafter(std::numeric_limits<T>::max() / 2, 0);
775 bool unsafe = safe_upper < r2_high;
776 if (std::numeric_limits<T>::is_signed) {
777 const T safe_lower =
778 std::nextafter(std::numeric_limits<T>::lowest() / 2, 0);
779 unsafe = unsafe || r2_low < safe_lower;
780 }
781 if (unsafe) {
782 r2_low /= 2;
783 r2_high /= 2;
784 intersection_low /= 2;
785 intersection_high /= 2;
786 }
787
788 // Compute ratio
789 auto numerator = intersection_high - intersection_low;
790 auto denominator = r2_high - r2_low;
791 if (std::numeric_limits<T>::is_integer) {
792 // integer types count elements; they don't measure length
793 numerator += 1;
794 denominator += 1;
795 } else {
796 if (denominator == 0) {
797 /*
798 * If the variable `denominator` is zero, it's the result of rounding,
799 * since checking the "disjoint" and "subset" cases above has ensured that
800 * the endpoints of the denominator interval are distinct. Thus we have no
801 * easy-to-access information about the true quotient value, but
802 * mathematically it must be between 0 and 1, so we need either to return
803 * some value between 0 and 1 or to throw an exception stating that we
804 * don't support this case.
805 *
806 * The variable `denominator` is larger than the variable `numerator`, so
807 * the numerator is also be zero. We could extract some information from
808 * the floating-point representation itself, but that's a lot of work that
809 * doesn't seem justified at present. Throwing an exception would be
810 * better on principle, but the code in its current state now would not
811 * deal with that gracefully. As a compromise, therefore, we return a
812 * valid but non-computed value. It's a defect, but one that will rarely
813 * if ever arise in practice.
814 */
815 return 0.5;
816 }
817 // The rounded-to-zero numerator is handled in the general case below.
818 }
819 auto ratio = (double)numerator / denominator;
820 // Round away from the endpoints if needed.
821 if (ratio == 0.0) {
822 ratio = std::nextafter(0, 1);
823 } else if (ratio == 1.0) {
824 ratio = std::nextafter(1, 0);
825 }
826 assert(0.0 < ratio && ratio < 1.0);
827 return ratio;
828 }
829
overlap_ratio(const Range & r1,const Range & r2) const830 double Dimension::overlap_ratio(const Range& r1, const Range& r2) const {
831 assert(overlap_ratio_func_ != nullptr);
832 return overlap_ratio_func_(r1, r2);
833 }
834
835 template <>
split_range(const Range & r,const ByteVecValue & v,Range * r1,Range * r2)836 void Dimension::split_range<char>(
837 const Range& r, const ByteVecValue& v, Range* r1, Range* r2) {
838 assert(v);
839 assert(r1 != nullptr);
840 assert(r2 != nullptr);
841
842 // First range
843 auto min_string = std::string("\x0", 1);
844 auto new_r1_start = !r.start_str().empty() ? r.start_str() : min_string;
845 auto new_r1_end = v.rvalue_as<std::string>();
846 auto new_r1_end_size = (int)new_r1_end.size();
847 int pos;
848 for (pos = 0; pos < new_r1_end_size; ++pos) {
849 if ((int)(signed char)new_r1_end[pos] < 0) {
850 new_r1_end[pos] = 127;
851 new_r1_end.resize(pos + 1);
852 break;
853 }
854 }
855 assert(pos < new_r1_end_size); // One negative char must be present
856 r1->set_str_range(new_r1_start, new_r1_end);
857
858 // Second range
859 auto new_r2_start = v.rvalue_as<std::string>();
860 // The following will make "a b -1 -4 0" -> "a c"
861 for (pos = 0; pos < new_r1_end_size; ++pos) {
862 if ((int)(signed char)new_r2_start[pos] < 0)
863 break;
864 }
865 do {
866 assert(pos != 0);
867 new_r2_start[pos] = 0;
868 new_r2_start[--pos]++;
869 } while (pos >= 0 && (int)(signed char)new_r2_start[pos] < 0);
870 new_r2_start.resize(pos + 1);
871
872 auto max_string = std::string("\x7F", 1);
873 auto new_r2_end = !r.end_str().empty() ? r.end_str() : max_string;
874
875 assert(new_r2_start > new_r1_end);
876 assert(new_r2_start <= new_r2_end);
877 r2->set_str_range(new_r2_start, new_r2_end);
878
879 // Set the depth of the split ranges to +1 the depth of
880 // the range they were split from.
881 r1->set_partition_depth(r.partition_depth() + 1);
882 r2->set_partition_depth(r.partition_depth() + 1);
883 }
884
885 template <class T>
split_range(const Range & r,const ByteVecValue & v,Range * r1,Range * r2)886 void Dimension::split_range(
887 const Range& r, const ByteVecValue& v, Range* r1, Range* r2) {
888 assert(!r.empty());
889 assert(v);
890 assert(r1 != nullptr);
891 assert(r2 != nullptr);
892
893 auto max = std::numeric_limits<T>::max();
894 bool int_domain = std::is_integral<T>::value;
895 auto r_t = (const T*)r.data();
896 auto v_t = *(const T*)(v.data());
897 assert(v_t >= r_t[0]);
898 assert(v_t < r_t[1]);
899
900 T ret[2];
901 ret[0] = r_t[0];
902 ret[1] = v_t;
903 r1->set_range(ret, sizeof(ret));
904 ret[0] = int_domain ? (v_t + 1) : static_cast<T>(std::nextafter(v_t, max));
905 ret[1] = r_t[1];
906 r2->set_range(ret, sizeof(ret));
907
908 // Set the depth of the split ranges to +1 the depth of
909 // the range they were split from.
910 r1->set_partition_depth(r.partition_depth() + 1);
911 r2->set_partition_depth(r.partition_depth() + 1);
912 }
913
split_range(const Range & r,const ByteVecValue & v,Range * r1,Range * r2) const914 void Dimension::split_range(
915 const Range& r, const ByteVecValue& v, Range* r1, Range* r2) const {
916 assert(split_range_func_ != nullptr);
917 split_range_func_(r, v, r1, r2);
918 }
919
920 template <>
splitting_value(const Range & r,ByteVecValue * v,bool * unsplittable)921 void Dimension::splitting_value<char>(
922 const Range& r, ByteVecValue* v, bool* unsplittable) {
923 assert(!r.empty());
924 assert(v != nullptr);
925 assert(unsplittable != nullptr);
926
927 // Check unsplittable
928 if (!r.empty() && r.unary()) {
929 *unsplittable = true;
930 return;
931 }
932
933 *unsplittable = false;
934
935 // Find position to split
936 auto start = r.start_str();
937 auto end = r.end_str();
938 auto pref_size = utils::parse::common_prefix_size(start, end);
939
940 // String ranges are infinitely splittable. We define a fixed
941 // limit on how deep we will split a user-given range. If we
942 // reach this limit, we will treat the range as unsplittable.
943 if (r.partition_depth() >= constants::max_string_dim_split_depth) {
944 *unsplittable = true;
945 return;
946 }
947
948 // Check unsplittable
949 if (!end.empty() && end[pref_size] == 0) {
950 *unsplittable = true;
951 return;
952 }
953
954 // 127 is the maximum ascii number
955 uint8_t end_pref = end.empty() ? 127 : (uint8_t)end[pref_size];
956 auto start_c = (start.size() == pref_size) ? 0 : start[pref_size];
957 auto split_v = (end_pref - start_c) / 2;
958 auto split_str =
959 start.substr(0, pref_size) + (char)(start_c + split_v) + "\x80";
960 assert(split_str >= start);
961
962 v->resize(split_str.size());
963 std::memcpy(v->data(), split_str.data(), split_str.size());
964 }
965
966 template <class T>
splitting_value(const Range & r,ByteVecValue * v,bool * unsplittable)967 void Dimension::splitting_value(
968 const Range& r, ByteVecValue* v, bool* unsplittable) {
969 assert(!r.empty());
970 assert(v != nullptr);
971 assert(unsplittable != nullptr);
972
973 auto r_t = (const T*)r.data();
974
975 // Floating-point template specializations for this routine exist below.
976 // All remaining template types are handled in this implementation,
977 // where all template types are integers. We will calculate the split value
978 // with the following expression: `r_t[0] + (r_t[1] - r_t[0]) / 2`. To
979 // prevent overflow in the `(r_t[1] - r_t[0]) / 2` sub-expression, we will
980 // perform this entire sub-expression with a 65-bit bitset.
981 std::bitset<65> r_t0(r_t[0]);
982 std::bitset<65> r_t1(r_t[1]);
983
984 // If `T` is signed, respect two's complement on the high bit.
985 if (std::is_signed<T>::value) {
986 r_t0[64] = r_t0[63];
987 r_t1[64] = r_t1[63];
988 }
989
990 // Subtract `r_t0` from `r_t1`.
991 while (r_t0 != 0) {
992 const std::bitset<65> carry = (~r_t1) & r_t0;
993 r_t1 = r_t1 ^ r_t0;
994 r_t0 = carry << 1;
995 }
996
997 // Divide by 2.
998 r_t1 = r_t1 >> 1;
999
1000 // Truncate the overflow bit. This will only occur if `T` is
1001 // a signed integer and the result of `(r_t[1] - r_t[0]) / 2`
1002 // is negative. This preserves signed representation when
1003 // converting back to 64-bits in the following invocation
1004 // of `std::bitset<65>::to_ulong`.
1005 r_t1 = r_t1 & std::bitset<65>(UINT64_MAX);
1006
1007 // Cast the intermediate result back to type `T` to calculate
1008 // the split value.
1009 const T sp = r_t[0] + static_cast<T>(r_t1.to_ullong());
1010
1011 v->assign_as<T>(sp);
1012 *unsplittable = !std::memcmp(&sp, &r_t[1], sizeof(T));
1013 }
1014
1015 template <>
splitting_value(const Range & r,ByteVecValue * v,bool * unsplittable)1016 void Dimension::splitting_value<float>(
1017 const Range& r, ByteVecValue* v, bool* unsplittable) {
1018 assert(!r.empty());
1019 assert(v != nullptr);
1020 assert(unsplittable != nullptr);
1021
1022 auto r_t = (const float*)r.data();
1023
1024 // Cast `r_t` elements to `double` to prevent overflow before
1025 // dividing by 2.
1026 const float sp = r_t[0] + ((double)r_t[1] - (double)r_t[0]) / 2;
1027
1028 v->assign_as<float>(sp);
1029 *unsplittable = !std::memcmp(&sp, &r_t[1], sizeof(float));
1030 }
1031
1032 template <>
splitting_value(const Range & r,ByteVecValue * v,bool * unsplittable)1033 void Dimension::splitting_value<double>(
1034 const Range& r, ByteVecValue* v, bool* unsplittable) {
1035 assert(!r.empty());
1036 assert(v != nullptr);
1037 assert(unsplittable != nullptr);
1038
1039 auto r_t = (const double*)r.data();
1040
1041 // Cast `r_t` elements to `long double` to prevent overflow
1042 // before dividing by 2.
1043 const double sp = r_t[0] + ((long double)r_t[1] - (long double)r_t[0]) / 2;
1044
1045 v->assign_as<double>(sp);
1046 *unsplittable = !std::memcmp(&sp, &r_t[1], sizeof(double));
1047 }
1048
splitting_value(const Range & r,ByteVecValue * v,bool * unsplittable) const1049 void Dimension::splitting_value(
1050 const Range& r, ByteVecValue* v, bool* unsplittable) const {
1051 assert(splitting_value_func_ != nullptr);
1052 splitting_value_func_(r, v, unsplittable);
1053 }
1054
1055 template <>
tile_num(const Dimension * dim,const Range & range)1056 uint64_t Dimension::tile_num<char>(const Dimension* dim, const Range& range) {
1057 (void)dim;
1058 (void)range;
1059
1060 return 1;
1061 }
1062
1063 template <class T>
tile_num(const Dimension * dim,const Range & range)1064 uint64_t Dimension::tile_num(const Dimension* dim, const Range& range) {
1065 assert(dim != nullptr);
1066 assert(!range.empty());
1067
1068 // Trivial cases
1069 if (!dim->tile_extent())
1070 return 1;
1071
1072 auto tile_extent = *(const T*)dim->tile_extent().data();
1073 auto dim_dom = (const T*)dim->domain().data();
1074 auto r = (const T*)range.data();
1075
1076 uint64_t start = tile_idx(r[0], dim_dom[0], tile_extent);
1077 uint64_t end = tile_idx(r[1], dim_dom[0], tile_extent);
1078 return end - start + 1;
1079 }
1080
tile_num(const Range & range) const1081 uint64_t Dimension::tile_num(const Range& range) const {
1082 assert(tile_num_func_ != nullptr);
1083 return tile_num_func_(this, range);
1084 }
1085
map_to_uint64(const QueryBuffer * buff,uint64_t c,uint64_t coords_num,int bits,uint64_t max_bucket_val) const1086 uint64_t Dimension::map_to_uint64(
1087 const QueryBuffer* buff,
1088 uint64_t c,
1089 uint64_t coords_num,
1090 int bits,
1091 uint64_t max_bucket_val) const {
1092 assert(map_to_uint64_func_ != nullptr);
1093 return map_to_uint64_func_(this, buff, c, coords_num, bits, max_bucket_val);
1094 }
1095
1096 template <class T>
map_to_uint64(const Dimension * dim,const QueryBuffer * buff,uint64_t c,uint64_t coords_num,int bits,uint64_t max_bucket_val)1097 uint64_t Dimension::map_to_uint64(
1098 const Dimension* dim,
1099 const QueryBuffer* buff,
1100 uint64_t c,
1101 uint64_t coords_num,
1102 int bits,
1103 uint64_t max_bucket_val) {
1104 assert(dim != nullptr);
1105 assert(buff != nullptr);
1106 assert(!dim->domain().empty());
1107 (void)coords_num; // Not used here
1108 (void)bits; // Not used here
1109
1110 double dom_start_T = *(const T*)dim->domain().start();
1111 double dom_end_T = *(const T*)dim->domain().end();
1112 auto dom_range_T = dom_end_T - dom_start_T;
1113 auto norm_coord_T = ((const T*)buff->buffer_)[c] - dom_start_T;
1114 return (norm_coord_T / dom_range_T) * max_bucket_val;
1115 }
1116
1117 template <>
map_to_uint64(const Dimension * dim,const QueryBuffer * buff,uint64_t c,uint64_t coords_num,int bits,uint64_t max_bucket_val)1118 uint64_t Dimension::map_to_uint64<char>(
1119 const Dimension* dim,
1120 const QueryBuffer* buff,
1121 uint64_t c,
1122 uint64_t coords_num,
1123 int bits,
1124 uint64_t max_bucket_val) {
1125 assert(dim != nullptr);
1126 assert(buff != nullptr);
1127 assert(buff->buffer_ != nullptr);
1128 assert(buff->buffer_var_ != nullptr);
1129 assert(buff->buffer_var_size_ != nullptr);
1130 (void)max_bucket_val; // Not needed here
1131 (void)dim;
1132
1133 auto offsets = (const uint64_t*)buff->buffer_;
1134 auto v_str = &((const char*)(buff->buffer_var_))[offsets[c]];
1135 auto v_str_size =
1136 ((c == coords_num - 1) ? *(buff->buffer_var_size_) : offsets[c + 1]) -
1137 offsets[c];
1138
1139 // The following will place up to the first 8 characters of the string
1140 // in the uint64 value to be returned. For instance, "cat" will be
1141 // "cat\0\0\0\0\0" inside the 8-byte uint64 value `ret`.
1142 uint64_t ret = 0;
1143 for (uint64_t i = 0; i < 8; ++i) {
1144 ret <<= 8; // Shift by one byte
1145 if (i < v_str_size)
1146 ret |= (uint64_t)v_str[i]; // Add next character (if exists)
1147 }
1148
1149 // Shift to fits in given number of bits
1150 return ret >> (64 - bits);
1151 }
1152
map_to_uint64(const void * coord,uint64_t coord_size,int bits,uint64_t max_bucket_val) const1153 uint64_t Dimension::map_to_uint64(
1154 const void* coord,
1155 uint64_t coord_size,
1156 int bits,
1157 uint64_t max_bucket_val) const {
1158 assert(map_to_uint64_2_func_ != nullptr);
1159 return map_to_uint64_2_func_(this, coord, coord_size, bits, max_bucket_val);
1160 }
1161
1162 template <class T>
map_to_uint64_2(const Dimension * dim,const void * coord,uint64_t coord_size,int bits,uint64_t max_bucket_val)1163 uint64_t Dimension::map_to_uint64_2(
1164 const Dimension* dim,
1165 const void* coord,
1166 uint64_t coord_size,
1167 int bits,
1168 uint64_t max_bucket_val) {
1169 assert(dim != nullptr);
1170 assert(coord != nullptr);
1171 assert(!dim->domain().empty());
1172 (void)coord_size; // Not needed here
1173 (void)bits; // Not needed here
1174
1175 double dom_start_T = *(const T*)dim->domain().start();
1176 double dom_end_T = *(const T*)dim->domain().end();
1177 auto dom_range_T = dom_end_T - dom_start_T;
1178 auto norm_coord_T = *(const T*)coord - dom_start_T;
1179 return (norm_coord_T / dom_range_T) * max_bucket_val;
1180 }
1181
1182 template <>
map_to_uint64_2(const Dimension * dim,const void * coord,uint64_t coord_size,int bits,uint64_t max_bucket_val)1183 uint64_t Dimension::map_to_uint64_2<char>(
1184 const Dimension* dim,
1185 const void* coord,
1186 uint64_t coord_size,
1187 int bits,
1188 uint64_t max_bucket_val) {
1189 assert(dim != nullptr);
1190 assert(coord != nullptr);
1191 (void)max_bucket_val;
1192 (void)dim;
1193
1194 auto v_str = (const char*)coord;
1195 auto v_str_size = coord_size;
1196
1197 // The following will place up to the first 8 characters of the string
1198 // in the uint64 value to be returned. For instance, "cat" will be
1199 // "cat\0\0\0\0\0" inside the 8-byte uint64 value `ret`.
1200 uint64_t ret = 0;
1201 for (uint64_t i = 0; i < 8; ++i) {
1202 ret <<= 8; // Shift by one byte
1203 if (i < v_str_size)
1204 ret |= (uint64_t)v_str[i]; // Add next character (if exists)
1205 }
1206
1207 // Shift to fit in given number of bits
1208 return ret >> (64 - bits);
1209 }
1210
map_to_uint64(const ResultCoords & coord,uint32_t dim_idx,int bits,uint64_t max_bucket_val) const1211 uint64_t Dimension::map_to_uint64(
1212 const ResultCoords& coord,
1213 uint32_t dim_idx,
1214 int bits,
1215 uint64_t max_bucket_val) const {
1216 assert(map_to_uint64_3_func_ != nullptr);
1217 return map_to_uint64_3_func_(this, coord, dim_idx, bits, max_bucket_val);
1218 }
1219
1220 template <class T>
map_to_uint64_3(const Dimension * dim,const ResultCoords & coord,uint32_t dim_idx,int bits,uint64_t max_bucket_val)1221 uint64_t Dimension::map_to_uint64_3(
1222 const Dimension* dim,
1223 const ResultCoords& coord,
1224 uint32_t dim_idx,
1225 int bits,
1226 uint64_t max_bucket_val) {
1227 assert(dim != nullptr);
1228 assert(!dim->domain().empty());
1229 (void)bits; // Not needed here
1230
1231 double dom_start_T = *(const T*)dim->domain().start();
1232 double dom_end_T = *(const T*)dim->domain().end();
1233 auto dom_range_T = dom_end_T - dom_start_T;
1234 auto norm_coord_T = *((const T*)coord.coord(dim_idx)) - dom_start_T;
1235 return (norm_coord_T / dom_range_T) * max_bucket_val;
1236 }
1237
1238 template <>
map_to_uint64_3(const Dimension * dim,const ResultCoords & coord,uint32_t dim_idx,int bits,uint64_t max_bucket_val)1239 uint64_t Dimension::map_to_uint64_3<char>(
1240 const Dimension* dim,
1241 const ResultCoords& coord,
1242 uint32_t dim_idx,
1243 int bits,
1244 uint64_t max_bucket_val) {
1245 assert(dim != nullptr);
1246 (void)max_bucket_val; // Not needed here
1247 (void)dim;
1248
1249 auto v_str = coord.coord_string(dim_idx);
1250 auto v_str_size = v_str.size();
1251
1252 // The following will place up to the first 8 characters of the string
1253 // in the uint64 value to be returned. For instance, "cat" will be
1254 // "cat\0\0\0\0\0" inside the 8-byte uint64 value `ret`.
1255 uint64_t ret = 0;
1256 for (uint64_t i = 0; i < 8; ++i) {
1257 ret <<= 8; // Shift by one byte
1258 if (i < v_str_size)
1259 ret |= (uint64_t)v_str[i]; // Add next character (if exists)
1260 }
1261
1262 // Shift to fit in given number of bits
1263 return ret >> (64 - bits);
1264 }
1265
map_from_uint64(uint64_t value,int bits,uint64_t max_bucket_val) const1266 ByteVecValue Dimension::map_from_uint64(
1267 uint64_t value, int bits, uint64_t max_bucket_val) const {
1268 assert(map_from_uint64_func_ != nullptr);
1269 return map_from_uint64_func_(this, value, bits, max_bucket_val);
1270 }
1271
1272 template <class T>
map_from_uint64(const Dimension * dim,uint64_t value,int bits,uint64_t max_bucket_val)1273 ByteVecValue Dimension::map_from_uint64(
1274 const Dimension* dim, uint64_t value, int bits, uint64_t max_bucket_val) {
1275 assert(dim != nullptr);
1276 assert(!dim->domain().empty());
1277 (void)bits; // Not needed here
1278
1279 ByteVecValue ret(sizeof(T));
1280
1281 // Add domain start
1282 auto value_T = static_cast<T>(value);
1283 value_T += *(const T*)dim->domain().start();
1284
1285 auto dom_start_T = *(const T*)dim->domain().start();
1286 auto dom_end_T = *(const T*)dim->domain().end();
1287 double dom_range_T = dom_end_T - dom_start_T;
1288
1289 // Essentially take the largest value in the bucket
1290 if (std::is_integral<T>::value) { // Integers
1291 T norm_coord_T =
1292 std::ceil(((value + 1) / (double)max_bucket_val) * dom_range_T - 1);
1293 T coord_T = norm_coord_T + dom_start_T;
1294 std::memcpy(ret.data(), &coord_T, sizeof(T));
1295 } else { // Floating point types
1296 T norm_coord_T = ((value + 1) / (double)max_bucket_val) * dom_range_T;
1297 norm_coord_T =
1298 std::nextafter(norm_coord_T, std::numeric_limits<T>::lowest());
1299 T coord_T = norm_coord_T + dom_start_T;
1300 std::memcpy(ret.data(), &coord_T, sizeof(T));
1301 }
1302
1303 return ret;
1304 }
1305
1306 template <>
map_from_uint64(const Dimension * dim,uint64_t value,int bits,uint64_t max_bucket_val)1307 ByteVecValue Dimension::map_from_uint64<char>(
1308 const Dimension* dim, uint64_t value, int bits, uint64_t max_bucket_val) {
1309 assert(dim != nullptr);
1310 (void)dim;
1311 (void)max_bucket_val; // Not needed here
1312
1313 std::vector<uint8_t> ret(sizeof(uint64_t)); // 8 bytes
1314
1315 uint64_t ret_uint64 = (value << (64 - bits));
1316 int ret_c;
1317 for (size_t i = 0; i < 8; ++i) { // Reverse ret_uint64
1318 ret_c = (int)((const char*)&ret_uint64)[7 - i];
1319 if (ret_c < 0) {
1320 ret[i] = 128;
1321 ret.resize(i + 1);
1322 break;
1323 } else {
1324 ret[i] = ret_c;
1325 }
1326 }
1327 if (ret.back() != 128)
1328 ret.push_back(128);
1329
1330 return ByteVecValue(std::move(ret));
1331 }
1332
smaller_than(const ByteVecValue & value,const Range & range) const1333 bool Dimension::smaller_than(
1334 const ByteVecValue& value, const Range& range) const {
1335 assert(smaller_than_func_ != nullptr);
1336 return smaller_than_func_(this, value, range);
1337 }
1338
1339 template <class T>
smaller_than(const Dimension * dim,const ByteVecValue & value,const Range & range)1340 bool Dimension::smaller_than(
1341 const Dimension* dim, const ByteVecValue& value, const Range& range) {
1342 assert(dim != nullptr);
1343 (void)dim;
1344 assert(value);
1345
1346 auto value_T = *(const T*)(value.data());
1347 auto range_start_T = *(const T*)range.start();
1348 return value_T < range_start_T;
1349 }
1350
1351 template <>
smaller_than(const Dimension * dim,const ByteVecValue & value,const Range & range)1352 bool Dimension::smaller_than<char>(
1353 const Dimension* dim, const ByteVecValue& value, const Range& range) {
1354 assert(dim != nullptr);
1355 assert(value);
1356 (void)dim;
1357
1358 auto value_str = value.rvalue_as<std::string>();
1359 auto range_start_str = range.start_str();
1360 auto range_end_str = range.end_str();
1361
1362 // If the range start is empty, then it is essentially -inf
1363 if (range_start_str.empty())
1364 return false;
1365
1366 return value_str < range_start_str;
1367 }
1368
1369 // ===== FORMAT =====
1370 // dimension_name_size (uint32_t)
1371 // dimension_name (string)
1372 // type (uint8_t)
1373 // cell_val_num (uint32_t)
1374 // filter_pipeline (see FilterPipeline::serialize)
1375 // domain_size (uint64_t)
1376 // domain (void* - domain_size)
1377 // null_tile_extent (uint8_t)
1378 // tile_extent (void* - type_size)
serialize(Buffer * buff,uint32_t version)1379 Status Dimension::serialize(Buffer* buff, uint32_t version) {
1380 // Sanity check
1381 auto is_str = datatype_is_string(type_);
1382 assert(is_str || !domain_.empty());
1383
1384 // Write dimension name
1385 auto dimension_name_size = (uint32_t)name_.size();
1386 RETURN_NOT_OK(buff->write(&dimension_name_size, sizeof(uint32_t)));
1387 RETURN_NOT_OK(buff->write(name_.c_str(), dimension_name_size));
1388
1389 // Applicable only to version >= 5
1390 if (version >= 5) {
1391 // Write type
1392 auto type = (uint8_t)type_;
1393 RETURN_NOT_OK(buff->write(&type, sizeof(uint8_t)));
1394
1395 // Write cell_val_num_
1396 RETURN_NOT_OK(buff->write(&cell_val_num_, sizeof(uint32_t)));
1397
1398 // Write filter pipeline
1399 RETURN_NOT_OK(filters_.serialize(buff));
1400 }
1401
1402 // Write domain and tile extent
1403 uint64_t domain_size = (is_str) ? 0 : 2 * coord_size();
1404 RETURN_NOT_OK(buff->write(&domain_size, sizeof(uint64_t)));
1405 RETURN_NOT_OK(buff->write(domain_.data(), domain_size));
1406
1407 auto null_tile_extent = (uint8_t)(tile_extent_ ? 0 : 1);
1408 RETURN_NOT_OK(buff->write(&null_tile_extent, sizeof(uint8_t)));
1409 if (tile_extent_)
1410 RETURN_NOT_OK(buff->write(tile_extent_.data(), tile_extent_.size()));
1411
1412 return Status::Ok();
1413 }
1414
set_domain(const void * domain)1415 Status Dimension::set_domain(const void* domain) {
1416 if (type_ == Datatype::STRING_ASCII) {
1417 if (domain == nullptr)
1418 return Status::Ok();
1419 return LOG_STATUS(Status::DimensionError(
1420 std::string("Setting the domain to a dimension with type '") +
1421 datatype_str(type_) + "' is not supported"));
1422 }
1423
1424 if (domain == nullptr)
1425 return Status::Ok();
1426 return set_domain(Range(domain, 2 * coord_size()));
1427 }
1428
set_domain(const Range & domain)1429 Status Dimension::set_domain(const Range& domain) {
1430 if (domain.empty())
1431 return Status::Ok();
1432
1433 domain_ = domain;
1434 RETURN_NOT_OK_ELSE(check_domain(), domain_.clear());
1435
1436 return Status::Ok();
1437 }
1438
set_domain_unsafe(const void * domain)1439 Status Dimension::set_domain_unsafe(const void* domain) {
1440 domain_ = Range(domain, 2 * coord_size());
1441
1442 return Status::Ok();
1443 }
1444
set_filter_pipeline(const FilterPipeline * pipeline)1445 Status Dimension::set_filter_pipeline(const FilterPipeline* pipeline) {
1446 if (pipeline == nullptr)
1447 return LOG_STATUS(Status::DimensionError(
1448 "Cannot set filter pipeline to dimension; Pipeline cannot be null"));
1449
1450 for (unsigned i = 0; i < pipeline->size(); ++i) {
1451 if (datatype_is_real(type_) &&
1452 pipeline->get_filter(i)->type() == FilterType::FILTER_DOUBLE_DELTA)
1453 return LOG_STATUS(
1454 Status::DimensionError("Cannot set DOUBLE DELTA filter to a "
1455 "dimension with a real datatype"));
1456 }
1457
1458 filters_ = *pipeline;
1459
1460 return Status::Ok();
1461 }
1462
set_tile_extent(const void * tile_extent)1463 Status Dimension::set_tile_extent(const void* tile_extent) {
1464 if (type_ == Datatype::STRING_ASCII) {
1465 if (tile_extent == nullptr)
1466 return Status::Ok();
1467 return LOG_STATUS(Status::DimensionError(
1468 std::string("Setting the tile extent to a dimension with type '") +
1469 datatype_str(type_) + "' is not supported"));
1470 }
1471
1472 ByteVecValue te;
1473 if (tile_extent != nullptr) {
1474 auto size = coord_size();
1475 te.resize(size);
1476 std::memcpy(te.data(), tile_extent, size);
1477 }
1478
1479 return set_tile_extent(te);
1480 }
1481
set_tile_extent(const ByteVecValue & tile_extent)1482 Status Dimension::set_tile_extent(const ByteVecValue& tile_extent) {
1483 if (type_ == Datatype::STRING_ASCII) {
1484 if (!tile_extent)
1485 return Status::Ok();
1486 return LOG_STATUS(Status::DimensionError(
1487 std::string("Setting the tile extent to a dimension with type '") +
1488 datatype_str(type_) + "' is not supported"));
1489 }
1490 if (domain_.empty())
1491 return LOG_STATUS(Status::DimensionError(
1492 "Cannot set tile extent; Domain must be set first"));
1493
1494 tile_extent_ = tile_extent;
1495
1496 return check_tile_extent();
1497 }
1498
set_null_tile_extent_to_range()1499 Status Dimension::set_null_tile_extent_to_range() {
1500 switch (type_) {
1501 case Datatype::INT8:
1502 return set_null_tile_extent_to_range<int8_t>();
1503 case Datatype::UINT8:
1504 return set_null_tile_extent_to_range<uint8_t>();
1505 case Datatype::INT16:
1506 return set_null_tile_extent_to_range<int16_t>();
1507 case Datatype::UINT16:
1508 return set_null_tile_extent_to_range<uint16_t>();
1509 case Datatype::INT32:
1510 return set_null_tile_extent_to_range<int32_t>();
1511 case Datatype::UINT32:
1512 return set_null_tile_extent_to_range<uint32_t>();
1513 case Datatype::INT64:
1514 return set_null_tile_extent_to_range<int64_t>();
1515 case Datatype::UINT64:
1516 return set_null_tile_extent_to_range<uint64_t>();
1517 case Datatype::FLOAT32:
1518 return set_null_tile_extent_to_range<float>();
1519 case Datatype::FLOAT64:
1520 return set_null_tile_extent_to_range<double>();
1521 case Datatype::DATETIME_YEAR:
1522 case Datatype::DATETIME_MONTH:
1523 case Datatype::DATETIME_WEEK:
1524 case Datatype::DATETIME_DAY:
1525 case Datatype::DATETIME_HR:
1526 case Datatype::DATETIME_MIN:
1527 case Datatype::DATETIME_SEC:
1528 case Datatype::DATETIME_MS:
1529 case Datatype::DATETIME_US:
1530 case Datatype::DATETIME_NS:
1531 case Datatype::DATETIME_PS:
1532 case Datatype::DATETIME_FS:
1533 case Datatype::DATETIME_AS:
1534 case Datatype::TIME_HR:
1535 case Datatype::TIME_MIN:
1536 case Datatype::TIME_SEC:
1537 case Datatype::TIME_MS:
1538 case Datatype::TIME_US:
1539 case Datatype::TIME_NS:
1540 case Datatype::TIME_PS:
1541 case Datatype::TIME_FS:
1542 case Datatype::TIME_AS:
1543 return set_null_tile_extent_to_range<int64_t>();
1544 case Datatype::STRING_ASCII:
1545 return Status::Ok(); // Do nothing for strings
1546 default:
1547 return LOG_STATUS(
1548 Status::DimensionError("Cannot set null tile extent to domain range; "
1549 "Invalid dimension domain type"));
1550 }
1551
1552 assert(false);
1553 return LOG_STATUS(
1554 Status::DimensionError("Cannot set null tile extent to domain range; "
1555 "Unsupported dimension type"));
1556 }
1557
1558 template <class T>
set_null_tile_extent_to_range()1559 Status Dimension::set_null_tile_extent_to_range() {
1560 // Applicable only to null extents
1561 if (tile_extent_)
1562 return Status::Ok();
1563
1564 // Check empty domain
1565 if (domain_.empty())
1566 return LOG_STATUS(Status::DimensionError(
1567 "Cannot set tile extent to domain range; Domain not set"));
1568
1569 // Calculate new tile extent equal to domain range
1570 auto domain = (const T*)domain_.data();
1571
1572 // For integral domain, we need to add 1, check for overflow before doing
1573 // anything
1574 if (std::is_integral<T>::value) {
1575 if (domain[0] == std::numeric_limits<T>::min() &&
1576 domain[1] == std::numeric_limits<T>::max()) {
1577 return LOG_STATUS(Status::DimensionError(
1578 "Cannot set null tile extent to domain range; "
1579 "Domain range exceeds domain type max numeric limit"));
1580 }
1581 }
1582
1583 T tile_extent = domain[1] - domain[0];
1584
1585 // We need to add 1 for integral domains
1586 if (std::is_integral<T>::value) {
1587 ++tile_extent;
1588 // After this, tile_extent = domain[1] - domain[0] + 1, which is the correct
1589 // domain range
1590 }
1591
1592 tile_extent_.assign_as<T>(tile_extent);
1593 return Status::Ok();
1594 }
1595
tile_extent() const1596 const ByteVecValue& Dimension::tile_extent() const {
1597 return tile_extent_;
1598 }
1599
type() const1600 Datatype Dimension::type() const {
1601 return type_;
1602 }
1603
var_size() const1604 bool Dimension::var_size() const {
1605 return cell_val_num_ == constants::var_num;
1606 }
1607
1608 /* ********************************* */
1609 /* PRIVATE METHODS */
1610 /* ********************************* */
1611
check_domain() const1612 Status Dimension::check_domain() const {
1613 switch (type_) {
1614 case Datatype::INT32:
1615 return check_domain<int>();
1616 case Datatype::INT64:
1617 return check_domain<int64_t>();
1618 case Datatype::INT8:
1619 return check_domain<int8_t>();
1620 case Datatype::UINT8:
1621 return check_domain<uint8_t>();
1622 case Datatype::INT16:
1623 return check_domain<int16_t>();
1624 case Datatype::UINT16:
1625 return check_domain<uint16_t>();
1626 case Datatype::UINT32:
1627 return check_domain<uint32_t>();
1628 case Datatype::UINT64:
1629 return check_domain<uint64_t>();
1630 case Datatype::FLOAT32:
1631 return check_domain<float>();
1632 case Datatype::FLOAT64:
1633 return check_domain<double>();
1634 case Datatype::DATETIME_YEAR:
1635 case Datatype::DATETIME_MONTH:
1636 case Datatype::DATETIME_WEEK:
1637 case Datatype::DATETIME_DAY:
1638 case Datatype::DATETIME_HR:
1639 case Datatype::DATETIME_MIN:
1640 case Datatype::DATETIME_SEC:
1641 case Datatype::DATETIME_MS:
1642 case Datatype::DATETIME_US:
1643 case Datatype::DATETIME_NS:
1644 case Datatype::DATETIME_PS:
1645 case Datatype::DATETIME_FS:
1646 case Datatype::DATETIME_AS:
1647 case Datatype::TIME_HR:
1648 case Datatype::TIME_MIN:
1649 case Datatype::TIME_SEC:
1650 case Datatype::TIME_MS:
1651 case Datatype::TIME_US:
1652 case Datatype::TIME_NS:
1653 case Datatype::TIME_PS:
1654 case Datatype::TIME_FS:
1655 case Datatype::TIME_AS:
1656 return check_domain<int64_t>();
1657 default:
1658 return LOG_STATUS(Status::DimensionError(
1659 "Domain check failed; Invalid dimension domain type"));
1660 }
1661 }
1662
check_tile_extent() const1663 Status Dimension::check_tile_extent() const {
1664 switch (type_) {
1665 case Datatype::INT32:
1666 return check_tile_extent<int>();
1667 case Datatype::INT64:
1668 return check_tile_extent<int64_t>();
1669 case Datatype::INT8:
1670 return check_tile_extent<int8_t>();
1671 case Datatype::UINT8:
1672 return check_tile_extent<uint8_t>();
1673 case Datatype::INT16:
1674 return check_tile_extent<int16_t>();
1675 case Datatype::UINT16:
1676 return check_tile_extent<uint16_t>();
1677 case Datatype::UINT32:
1678 return check_tile_extent<uint32_t>();
1679 case Datatype::UINT64:
1680 return check_tile_extent<uint64_t>();
1681 case Datatype::FLOAT32:
1682 return check_tile_extent<float>();
1683 case Datatype::FLOAT64:
1684 return check_tile_extent<double>();
1685 case Datatype::DATETIME_YEAR:
1686 case Datatype::DATETIME_MONTH:
1687 case Datatype::DATETIME_WEEK:
1688 case Datatype::DATETIME_DAY:
1689 case Datatype::DATETIME_HR:
1690 case Datatype::DATETIME_MIN:
1691 case Datatype::DATETIME_SEC:
1692 case Datatype::DATETIME_MS:
1693 case Datatype::DATETIME_US:
1694 case Datatype::DATETIME_NS:
1695 case Datatype::DATETIME_PS:
1696 case Datatype::DATETIME_FS:
1697 case Datatype::DATETIME_AS:
1698 case Datatype::TIME_HR:
1699 case Datatype::TIME_MIN:
1700 case Datatype::TIME_SEC:
1701 case Datatype::TIME_MS:
1702 case Datatype::TIME_US:
1703 case Datatype::TIME_NS:
1704 case Datatype::TIME_PS:
1705 case Datatype::TIME_FS:
1706 case Datatype::TIME_AS:
1707 return check_tile_extent<int64_t>();
1708 default:
1709 return LOG_STATUS(Status::DimensionError(
1710 "Tile extent check failed; Invalid dimension domain type"));
1711 }
1712 }
1713
1714 template <class T>
check_tile_extent() const1715 Status Dimension::check_tile_extent() const {
1716 if (domain_.empty())
1717 return LOG_STATUS(
1718 Status::DimensionError("Tile extent check failed; Domain not set"));
1719
1720 if (!tile_extent_)
1721 return Status::Ok();
1722
1723 auto tile_extent = (const T*)tile_extent_.data();
1724 auto domain = (const T*)domain_.data();
1725 bool is_int = std::is_integral<T>::value;
1726
1727 // Check if tile extent exceeds domain
1728 if (!is_int) {
1729 // Check if tile extent is negative or 0
1730 if (*tile_extent <= 0)
1731 return LOG_STATUS(Status::DimensionError(
1732 "Tile extent check failed; Tile extent must be greater than 0"));
1733
1734 if (*tile_extent > (domain[1] - domain[0] + 1))
1735 return LOG_STATUS(
1736 Status::DimensionError("Tile extent check failed; Tile extent "
1737 "exceeds dimension domain range"));
1738 } else {
1739 // Check if tile extent is 0
1740 if (*tile_extent == 0)
1741 return LOG_STATUS(Status::DimensionError(
1742 "Tile extent check failed; Tile extent must not be 0"));
1743
1744 // Check if tile extent exceeds domain
1745 uint64_t range = (uint64_t)domain[1] - (uint64_t)domain[0] + 1;
1746 if (uint64_t(*tile_extent) > range)
1747 return LOG_STATUS(
1748 Status::DimensionError("Tile extent check failed; Tile extent "
1749 "exceeds dimension domain range"));
1750
1751 // In the worst case one tile extent will be added to the upper domain
1752 // for the dense case, so check if the expanded domain will exceed type
1753 // T's max limit.
1754 if (range % uint64_t(*tile_extent))
1755 RETURN_NOT_OK(check_tile_extent_upper_floor(domain, *tile_extent));
1756 }
1757
1758 return Status::Ok();
1759 }
1760
1761 template <typename T>
check_tile_extent_upper_floor(const T * const domain,const T tile_extent) const1762 Status Dimension::check_tile_extent_upper_floor(
1763 const T* const domain, const T tile_extent) const {
1764 // The type of the upper floor must match the sign of the extent
1765 // type.
1766 return std::is_signed<T>::value ?
1767 check_tile_extent_upper_floor_internal<T, int64_t>(
1768 domain, tile_extent) :
1769 check_tile_extent_upper_floor_internal<T, uint64_t>(
1770 domain, tile_extent);
1771 }
1772
1773 template <typename T_EXTENT, typename T_FLOOR>
check_tile_extent_upper_floor_internal(const T_EXTENT * const domain,const T_EXTENT tile_extent) const1774 Status Dimension::check_tile_extent_upper_floor_internal(
1775 const T_EXTENT* const domain, const T_EXTENT tile_extent) const {
1776 const uint64_t range = domain[1] - domain[0] + 1;
1777 const T_FLOOR upper_floor =
1778 ((range - 1) / (tile_extent)) * (tile_extent) + domain[0];
1779 const T_FLOOR upper_floor_max =
1780 std::numeric_limits<T_FLOOR>::max() - (tile_extent - 1);
1781 const T_FLOOR extent_max =
1782 static_cast<T_FLOOR>(std::numeric_limits<T_EXTENT>::max());
1783 const bool exceeds =
1784 upper_floor > upper_floor_max || upper_floor > extent_max;
1785 if (exceeds) {
1786 return LOG_STATUS(Status::DimensionError(
1787 "Tile extent check failed; domain max expanded to multiple of tile "
1788 "extent exceeds max value representable by domain type. Reduce "
1789 "domain max by 1 tile extent to allow for expansion."));
1790 }
1791
1792 return Status::Ok();
1793 }
1794
domain_str() const1795 std::string Dimension::domain_str() const {
1796 std::stringstream ss;
1797
1798 if (domain_.empty())
1799 return constants::null_str;
1800
1801 const int* domain_int32;
1802 const int64_t* domain_int64;
1803 const float* domain_float32;
1804 const double* domain_float64;
1805 const int8_t* domain_int8;
1806 const uint8_t* domain_uint8;
1807 const int16_t* domain_int16;
1808 const uint16_t* domain_uint16;
1809 const uint32_t* domain_uint32;
1810 const uint64_t* domain_uint64;
1811
1812 switch (type_) {
1813 case Datatype::INT32:
1814 domain_int32 = (const int32_t*)domain_.data();
1815 ss << "[" << domain_int32[0] << "," << domain_int32[1] << "]";
1816 return ss.str();
1817 case Datatype::INT64:
1818 domain_int64 = (const int64_t*)domain_.data();
1819 ss << "[" << domain_int64[0] << "," << domain_int64[1] << "]";
1820 return ss.str();
1821 case Datatype::FLOAT32:
1822 domain_float32 = (const float*)domain_.data();
1823 ss << "[" << domain_float32[0] << "," << domain_float32[1] << "]";
1824 return ss.str();
1825 case Datatype::FLOAT64:
1826 domain_float64 = (const double*)domain_.data();
1827 ss << "[" << domain_float64[0] << "," << domain_float64[1] << "]";
1828 return ss.str();
1829 case Datatype::INT8:
1830 domain_int8 = (const int8_t*)domain_.data();
1831 ss << "[" << int(domain_int8[0]) << "," << int(domain_int8[1]) << "]";
1832 return ss.str();
1833 case Datatype::UINT8:
1834 domain_uint8 = (const uint8_t*)domain_.data();
1835 ss << "[" << int(domain_uint8[0]) << "," << int(domain_uint8[1]) << "]";
1836 return ss.str();
1837 case Datatype::INT16:
1838 domain_int16 = (const int16_t*)domain_.data();
1839 ss << "[" << domain_int16[0] << "," << domain_int16[1] << "]";
1840 return ss.str();
1841 case Datatype::UINT16:
1842 domain_uint16 = (const uint16_t*)domain_.data();
1843 ss << "[" << domain_uint16[0] << "," << domain_uint16[1] << "]";
1844 return ss.str();
1845 case Datatype::UINT32:
1846 domain_uint32 = (const uint32_t*)domain_.data();
1847 ss << "[" << domain_uint32[0] << "," << domain_uint32[1] << "]";
1848 return ss.str();
1849 case Datatype::UINT64:
1850 domain_uint64 = (const uint64_t*)domain_.data();
1851 ss << "[" << domain_uint64[0] << "," << domain_uint64[1] << "]";
1852 return ss.str();
1853 case Datatype::DATETIME_YEAR:
1854 case Datatype::DATETIME_MONTH:
1855 case Datatype::DATETIME_WEEK:
1856 case Datatype::DATETIME_DAY:
1857 case Datatype::DATETIME_HR:
1858 case Datatype::DATETIME_MIN:
1859 case Datatype::DATETIME_SEC:
1860 case Datatype::DATETIME_MS:
1861 case Datatype::DATETIME_US:
1862 case Datatype::DATETIME_NS:
1863 case Datatype::DATETIME_PS:
1864 case Datatype::DATETIME_FS:
1865 case Datatype::DATETIME_AS:
1866 case Datatype::TIME_HR:
1867 case Datatype::TIME_MIN:
1868 case Datatype::TIME_SEC:
1869 case Datatype::TIME_MS:
1870 case Datatype::TIME_US:
1871 case Datatype::TIME_NS:
1872 case Datatype::TIME_PS:
1873 case Datatype::TIME_FS:
1874 case Datatype::TIME_AS:
1875 domain_int64 = (const int64_t*)domain_.data();
1876 ss << "[" << domain_int64[0] << "," << domain_int64[1] << "]";
1877 return ss.str();
1878
1879 case Datatype::CHAR:
1880 case Datatype::STRING_ASCII:
1881 case Datatype::STRING_UTF8:
1882 case Datatype::STRING_UTF16:
1883 case Datatype::STRING_UTF32:
1884 case Datatype::STRING_UCS2:
1885 case Datatype::STRING_UCS4:
1886 case Datatype::ANY:
1887 // Not supported domain type
1888 assert(false);
1889 return "";
1890 }
1891
1892 assert(false);
1893 return "";
1894 }
1895
tile_extent_str() const1896 std::string Dimension::tile_extent_str() const {
1897 std::stringstream ss;
1898
1899 if (!tile_extent_)
1900 return constants::null_str;
1901
1902 const float* tile_extent_float32;
1903 const double* tile_extent_float64;
1904 const uint8_t* tile_extent_uint8;
1905 const uint16_t* tile_extent_uint16;
1906 const uint32_t* tile_extent_uint32;
1907 const uint64_t* tile_extent_uint64;
1908
1909 switch (type_) {
1910 case Datatype::INT32:
1911 tile_extent_uint32 = (const uint32_t*)tile_extent_.data();
1912 ss << *tile_extent_uint32;
1913 return ss.str();
1914 case Datatype::INT64:
1915 tile_extent_uint64 = (const uint64_t*)tile_extent_.data();
1916 ss << *tile_extent_uint64;
1917 return ss.str();
1918 case Datatype::FLOAT32:
1919 tile_extent_float32 = (const float*)tile_extent_.data();
1920 ss << *tile_extent_float32;
1921 return ss.str();
1922 case Datatype::FLOAT64:
1923 tile_extent_float64 = (const double*)tile_extent_.data();
1924 ss << *tile_extent_float64;
1925 return ss.str();
1926 case Datatype::INT8:
1927 tile_extent_uint8 = (const uint8_t*)tile_extent_.data();
1928 ss << int(*tile_extent_uint8);
1929 return ss.str();
1930 case Datatype::UINT8:
1931 tile_extent_uint8 = (const uint8_t*)tile_extent_.data();
1932 ss << int(*tile_extent_uint8);
1933 return ss.str();
1934 case Datatype::INT16:
1935 tile_extent_uint16 = (const uint16_t*)tile_extent_.data();
1936 ss << *tile_extent_uint16;
1937 return ss.str();
1938 case Datatype::UINT16:
1939 tile_extent_uint16 = (const uint16_t*)tile_extent_.data();
1940 ss << *tile_extent_uint16;
1941 return ss.str();
1942 case Datatype::UINT32:
1943 tile_extent_uint32 = (const uint32_t*)tile_extent_.data();
1944 ss << *tile_extent_uint32;
1945 return ss.str();
1946 case Datatype::UINT64:
1947 tile_extent_uint64 = (const uint64_t*)tile_extent_.data();
1948 ss << *tile_extent_uint64;
1949 return ss.str();
1950 case Datatype::DATETIME_YEAR:
1951 case Datatype::DATETIME_MONTH:
1952 case Datatype::DATETIME_WEEK:
1953 case Datatype::DATETIME_DAY:
1954 case Datatype::DATETIME_HR:
1955 case Datatype::DATETIME_MIN:
1956 case Datatype::DATETIME_SEC:
1957 case Datatype::DATETIME_MS:
1958 case Datatype::DATETIME_US:
1959 case Datatype::DATETIME_NS:
1960 case Datatype::DATETIME_PS:
1961 case Datatype::DATETIME_FS:
1962 case Datatype::DATETIME_AS:
1963 case Datatype::TIME_HR:
1964 case Datatype::TIME_MIN:
1965 case Datatype::TIME_SEC:
1966 case Datatype::TIME_MS:
1967 case Datatype::TIME_US:
1968 case Datatype::TIME_NS:
1969 case Datatype::TIME_PS:
1970 case Datatype::TIME_FS:
1971 case Datatype::TIME_AS:
1972 tile_extent_uint64 = (const uint64_t*)tile_extent_.data();
1973 ss << *tile_extent_uint64;
1974 return ss.str();
1975
1976 case Datatype::CHAR:
1977 case Datatype::STRING_ASCII:
1978 case Datatype::STRING_UTF8:
1979 case Datatype::STRING_UTF16:
1980 case Datatype::STRING_UTF32:
1981 case Datatype::STRING_UCS2:
1982 case Datatype::STRING_UCS4:
1983 case Datatype::ANY:
1984 // Not supported domain type
1985 assert(false);
1986 return "";
1987 }
1988
1989 assert(false);
1990 return "";
1991 }
1992
set_crop_range_func()1993 void Dimension::set_crop_range_func() {
1994 switch (type_) {
1995 case Datatype::INT32:
1996 crop_range_func_ = crop_range<int32_t>;
1997 break;
1998 case Datatype::INT64:
1999 crop_range_func_ = crop_range<int64_t>;
2000 break;
2001 case Datatype::INT8:
2002 crop_range_func_ = crop_range<int8_t>;
2003 break;
2004 case Datatype::UINT8:
2005 crop_range_func_ = crop_range<uint8_t>;
2006 break;
2007 case Datatype::INT16:
2008 crop_range_func_ = crop_range<int16_t>;
2009 break;
2010 case Datatype::UINT16:
2011 crop_range_func_ = crop_range<uint16_t>;
2012 break;
2013 case Datatype::UINT32:
2014 crop_range_func_ = crop_range<uint32_t>;
2015 break;
2016 case Datatype::UINT64:
2017 crop_range_func_ = crop_range<uint64_t>;
2018 break;
2019 case Datatype::FLOAT32:
2020 crop_range_func_ = crop_range<float>;
2021 break;
2022 case Datatype::FLOAT64:
2023 crop_range_func_ = crop_range<double>;
2024 break;
2025 case Datatype::DATETIME_YEAR:
2026 case Datatype::DATETIME_MONTH:
2027 case Datatype::DATETIME_WEEK:
2028 case Datatype::DATETIME_DAY:
2029 case Datatype::DATETIME_HR:
2030 case Datatype::DATETIME_MIN:
2031 case Datatype::DATETIME_SEC:
2032 case Datatype::DATETIME_MS:
2033 case Datatype::DATETIME_US:
2034 case Datatype::DATETIME_NS:
2035 case Datatype::DATETIME_PS:
2036 case Datatype::DATETIME_FS:
2037 case Datatype::DATETIME_AS:
2038 case Datatype::TIME_HR:
2039 case Datatype::TIME_MIN:
2040 case Datatype::TIME_SEC:
2041 case Datatype::TIME_MS:
2042 case Datatype::TIME_US:
2043 case Datatype::TIME_NS:
2044 case Datatype::TIME_PS:
2045 case Datatype::TIME_FS:
2046 case Datatype::TIME_AS:
2047 crop_range_func_ = crop_range<int64_t>;
2048 break;
2049 default:
2050 crop_range_func_ = nullptr;
2051 break;
2052 }
2053 }
2054
set_domain_range_func()2055 void Dimension::set_domain_range_func() {
2056 switch (type_) {
2057 case Datatype::INT32:
2058 domain_range_func_ = domain_range<int32_t>;
2059 break;
2060 case Datatype::INT64:
2061 domain_range_func_ = domain_range<int64_t>;
2062 break;
2063 case Datatype::INT8:
2064 domain_range_func_ = domain_range<int8_t>;
2065 break;
2066 case Datatype::UINT8:
2067 domain_range_func_ = domain_range<uint8_t>;
2068 break;
2069 case Datatype::INT16:
2070 domain_range_func_ = domain_range<int16_t>;
2071 break;
2072 case Datatype::UINT16:
2073 domain_range_func_ = domain_range<uint16_t>;
2074 break;
2075 case Datatype::UINT32:
2076 domain_range_func_ = domain_range<uint32_t>;
2077 break;
2078 case Datatype::UINT64:
2079 domain_range_func_ = domain_range<uint64_t>;
2080 break;
2081 case Datatype::FLOAT32:
2082 domain_range_func_ = domain_range<float>;
2083 break;
2084 case Datatype::FLOAT64:
2085 domain_range_func_ = domain_range<double>;
2086 break;
2087 case Datatype::DATETIME_YEAR:
2088 case Datatype::DATETIME_MONTH:
2089 case Datatype::DATETIME_WEEK:
2090 case Datatype::DATETIME_DAY:
2091 case Datatype::DATETIME_HR:
2092 case Datatype::DATETIME_MIN:
2093 case Datatype::DATETIME_SEC:
2094 case Datatype::DATETIME_MS:
2095 case Datatype::DATETIME_US:
2096 case Datatype::DATETIME_NS:
2097 case Datatype::DATETIME_PS:
2098 case Datatype::DATETIME_FS:
2099 case Datatype::DATETIME_AS:
2100 case Datatype::TIME_HR:
2101 case Datatype::TIME_MIN:
2102 case Datatype::TIME_SEC:
2103 case Datatype::TIME_MS:
2104 case Datatype::TIME_US:
2105 case Datatype::TIME_NS:
2106 case Datatype::TIME_PS:
2107 case Datatype::TIME_FS:
2108 case Datatype::TIME_AS:
2109 domain_range_func_ = domain_range<int64_t>;
2110 break;
2111 default:
2112 domain_range_func_ = nullptr;
2113 break;
2114 }
2115 }
2116
set_ceil_to_tile_func()2117 void Dimension::set_ceil_to_tile_func() {
2118 switch (type_) {
2119 case Datatype::INT32:
2120 ceil_to_tile_func_ = ceil_to_tile<int32_t>;
2121 break;
2122 case Datatype::INT64:
2123 ceil_to_tile_func_ = ceil_to_tile<int64_t>;
2124 break;
2125 case Datatype::INT8:
2126 ceil_to_tile_func_ = ceil_to_tile<int8_t>;
2127 break;
2128 case Datatype::UINT8:
2129 ceil_to_tile_func_ = ceil_to_tile<uint8_t>;
2130 break;
2131 case Datatype::INT16:
2132 ceil_to_tile_func_ = ceil_to_tile<int16_t>;
2133 break;
2134 case Datatype::UINT16:
2135 ceil_to_tile_func_ = ceil_to_tile<uint16_t>;
2136 break;
2137 case Datatype::UINT32:
2138 ceil_to_tile_func_ = ceil_to_tile<uint32_t>;
2139 break;
2140 case Datatype::UINT64:
2141 ceil_to_tile_func_ = ceil_to_tile<uint64_t>;
2142 break;
2143 case Datatype::FLOAT32:
2144 ceil_to_tile_func_ = ceil_to_tile<float>;
2145 break;
2146 case Datatype::FLOAT64:
2147 ceil_to_tile_func_ = ceil_to_tile<double>;
2148 break;
2149 case Datatype::DATETIME_YEAR:
2150 case Datatype::DATETIME_MONTH:
2151 case Datatype::DATETIME_WEEK:
2152 case Datatype::DATETIME_DAY:
2153 case Datatype::DATETIME_HR:
2154 case Datatype::DATETIME_MIN:
2155 case Datatype::DATETIME_SEC:
2156 case Datatype::DATETIME_MS:
2157 case Datatype::DATETIME_US:
2158 case Datatype::DATETIME_NS:
2159 case Datatype::DATETIME_PS:
2160 case Datatype::DATETIME_FS:
2161 case Datatype::DATETIME_AS:
2162 case Datatype::TIME_HR:
2163 case Datatype::TIME_MIN:
2164 case Datatype::TIME_SEC:
2165 case Datatype::TIME_MS:
2166 case Datatype::TIME_US:
2167 case Datatype::TIME_NS:
2168 case Datatype::TIME_PS:
2169 case Datatype::TIME_FS:
2170 case Datatype::TIME_AS:
2171 ceil_to_tile_func_ = ceil_to_tile<int64_t>;
2172 break;
2173 default:
2174 ceil_to_tile_func_ = nullptr;
2175 break;
2176 }
2177 }
2178
set_check_range_func()2179 void Dimension::set_check_range_func() {
2180 switch (type_) {
2181 case Datatype::INT32:
2182 check_range_func_ = check_range<int32_t>;
2183 break;
2184 case Datatype::INT64:
2185 check_range_func_ = check_range<int64_t>;
2186 break;
2187 case Datatype::INT8:
2188 check_range_func_ = check_range<int8_t>;
2189 break;
2190 case Datatype::UINT8:
2191 check_range_func_ = check_range<uint8_t>;
2192 break;
2193 case Datatype::INT16:
2194 check_range_func_ = check_range<int16_t>;
2195 break;
2196 case Datatype::UINT16:
2197 check_range_func_ = check_range<uint16_t>;
2198 break;
2199 case Datatype::UINT32:
2200 check_range_func_ = check_range<uint32_t>;
2201 break;
2202 case Datatype::UINT64:
2203 check_range_func_ = check_range<uint64_t>;
2204 break;
2205 case Datatype::FLOAT32:
2206 check_range_func_ = check_range<float>;
2207 break;
2208 case Datatype::FLOAT64:
2209 check_range_func_ = check_range<double>;
2210 break;
2211 case Datatype::DATETIME_YEAR:
2212 case Datatype::DATETIME_MONTH:
2213 case Datatype::DATETIME_WEEK:
2214 case Datatype::DATETIME_DAY:
2215 case Datatype::DATETIME_HR:
2216 case Datatype::DATETIME_MIN:
2217 case Datatype::DATETIME_SEC:
2218 case Datatype::DATETIME_MS:
2219 case Datatype::DATETIME_US:
2220 case Datatype::DATETIME_NS:
2221 case Datatype::DATETIME_PS:
2222 case Datatype::DATETIME_FS:
2223 case Datatype::DATETIME_AS:
2224 case Datatype::TIME_HR:
2225 case Datatype::TIME_MIN:
2226 case Datatype::TIME_SEC:
2227 case Datatype::TIME_MS:
2228 case Datatype::TIME_US:
2229 case Datatype::TIME_NS:
2230 case Datatype::TIME_PS:
2231 case Datatype::TIME_FS:
2232 case Datatype::TIME_AS:
2233 check_range_func_ = check_range<int64_t>;
2234 break;
2235 default:
2236 check_range_func_ = nullptr;
2237 break;
2238 }
2239 }
2240
set_adjust_range_oob_func()2241 void Dimension::set_adjust_range_oob_func() {
2242 switch (type_) {
2243 case Datatype::INT32:
2244 adjust_range_oob_func_ = adjust_range_oob<int32_t>;
2245 break;
2246 case Datatype::INT64:
2247 adjust_range_oob_func_ = adjust_range_oob<int64_t>;
2248 break;
2249 case Datatype::INT8:
2250 adjust_range_oob_func_ = adjust_range_oob<int8_t>;
2251 break;
2252 case Datatype::UINT8:
2253 adjust_range_oob_func_ = adjust_range_oob<uint8_t>;
2254 break;
2255 case Datatype::INT16:
2256 adjust_range_oob_func_ = adjust_range_oob<int16_t>;
2257 break;
2258 case Datatype::UINT16:
2259 adjust_range_oob_func_ = adjust_range_oob<uint16_t>;
2260 break;
2261 case Datatype::UINT32:
2262 adjust_range_oob_func_ = adjust_range_oob<uint32_t>;
2263 break;
2264 case Datatype::UINT64:
2265 adjust_range_oob_func_ = adjust_range_oob<uint64_t>;
2266 break;
2267 case Datatype::FLOAT32:
2268 adjust_range_oob_func_ = adjust_range_oob<float>;
2269 break;
2270 case Datatype::FLOAT64:
2271 adjust_range_oob_func_ = adjust_range_oob<double>;
2272 break;
2273 case Datatype::DATETIME_YEAR:
2274 case Datatype::DATETIME_MONTH:
2275 case Datatype::DATETIME_WEEK:
2276 case Datatype::DATETIME_DAY:
2277 case Datatype::DATETIME_HR:
2278 case Datatype::DATETIME_MIN:
2279 case Datatype::DATETIME_SEC:
2280 case Datatype::DATETIME_MS:
2281 case Datatype::DATETIME_US:
2282 case Datatype::DATETIME_NS:
2283 case Datatype::DATETIME_PS:
2284 case Datatype::DATETIME_FS:
2285 case Datatype::DATETIME_AS:
2286 case Datatype::TIME_HR:
2287 case Datatype::TIME_MIN:
2288 case Datatype::TIME_SEC:
2289 case Datatype::TIME_MS:
2290 case Datatype::TIME_US:
2291 case Datatype::TIME_NS:
2292 case Datatype::TIME_PS:
2293 case Datatype::TIME_FS:
2294 case Datatype::TIME_AS:
2295 adjust_range_oob_func_ = adjust_range_oob<int64_t>;
2296 break;
2297 default:
2298 adjust_range_oob_func_ = nullptr;
2299 break;
2300 }
2301 }
2302
set_coincides_with_tiles_func()2303 void Dimension::set_coincides_with_tiles_func() {
2304 switch (type_) {
2305 case Datatype::INT32:
2306 coincides_with_tiles_func_ = coincides_with_tiles<int32_t>;
2307 break;
2308 case Datatype::INT64:
2309 coincides_with_tiles_func_ = coincides_with_tiles<int64_t>;
2310 break;
2311 case Datatype::INT8:
2312 coincides_with_tiles_func_ = coincides_with_tiles<int8_t>;
2313 break;
2314 case Datatype::UINT8:
2315 coincides_with_tiles_func_ = coincides_with_tiles<uint8_t>;
2316 break;
2317 case Datatype::INT16:
2318 coincides_with_tiles_func_ = coincides_with_tiles<int16_t>;
2319 break;
2320 case Datatype::UINT16:
2321 coincides_with_tiles_func_ = coincides_with_tiles<uint16_t>;
2322 break;
2323 case Datatype::UINT32:
2324 coincides_with_tiles_func_ = coincides_with_tiles<uint32_t>;
2325 break;
2326 case Datatype::UINT64:
2327 coincides_with_tiles_func_ = coincides_with_tiles<uint64_t>;
2328 break;
2329 case Datatype::FLOAT32:
2330 coincides_with_tiles_func_ = coincides_with_tiles<float>;
2331 break;
2332 case Datatype::FLOAT64:
2333 coincides_with_tiles_func_ = coincides_with_tiles<double>;
2334 break;
2335 case Datatype::DATETIME_YEAR:
2336 case Datatype::DATETIME_MONTH:
2337 case Datatype::DATETIME_WEEK:
2338 case Datatype::DATETIME_DAY:
2339 case Datatype::DATETIME_HR:
2340 case Datatype::DATETIME_MIN:
2341 case Datatype::DATETIME_SEC:
2342 case Datatype::DATETIME_MS:
2343 case Datatype::DATETIME_US:
2344 case Datatype::DATETIME_NS:
2345 case Datatype::DATETIME_PS:
2346 case Datatype::DATETIME_FS:
2347 case Datatype::DATETIME_AS:
2348 case Datatype::TIME_HR:
2349 case Datatype::TIME_MIN:
2350 case Datatype::TIME_SEC:
2351 case Datatype::TIME_MS:
2352 case Datatype::TIME_US:
2353 case Datatype::TIME_NS:
2354 case Datatype::TIME_PS:
2355 case Datatype::TIME_FS:
2356 case Datatype::TIME_AS:
2357 coincides_with_tiles_func_ = coincides_with_tiles<int64_t>;
2358 break;
2359 default:
2360 coincides_with_tiles_func_ = nullptr;
2361 break;
2362 }
2363 }
2364
set_compute_mbr_func()2365 void Dimension::set_compute_mbr_func() {
2366 if (!var_size()) { // Fixed-sized
2367 compute_mbr_var_func_ = nullptr;
2368 switch (type_) {
2369 case Datatype::INT32:
2370 compute_mbr_func_ = compute_mbr<int32_t>;
2371 break;
2372 case Datatype::INT64:
2373 compute_mbr_func_ = compute_mbr<int64_t>;
2374 break;
2375 case Datatype::INT8:
2376 compute_mbr_func_ = compute_mbr<int8_t>;
2377 break;
2378 case Datatype::UINT8:
2379 compute_mbr_func_ = compute_mbr<uint8_t>;
2380 break;
2381 case Datatype::INT16:
2382 compute_mbr_func_ = compute_mbr<int16_t>;
2383 break;
2384 case Datatype::UINT16:
2385 compute_mbr_func_ = compute_mbr<uint16_t>;
2386 break;
2387 case Datatype::UINT32:
2388 compute_mbr_func_ = compute_mbr<uint32_t>;
2389 break;
2390 case Datatype::UINT64:
2391 compute_mbr_func_ = compute_mbr<uint64_t>;
2392 break;
2393 case Datatype::FLOAT32:
2394 compute_mbr_func_ = compute_mbr<float>;
2395 break;
2396 case Datatype::FLOAT64:
2397 compute_mbr_func_ = compute_mbr<double>;
2398 break;
2399 case Datatype::DATETIME_YEAR:
2400 case Datatype::DATETIME_MONTH:
2401 case Datatype::DATETIME_WEEK:
2402 case Datatype::DATETIME_DAY:
2403 case Datatype::DATETIME_HR:
2404 case Datatype::DATETIME_MIN:
2405 case Datatype::DATETIME_SEC:
2406 case Datatype::DATETIME_MS:
2407 case Datatype::DATETIME_US:
2408 case Datatype::DATETIME_NS:
2409 case Datatype::DATETIME_PS:
2410 case Datatype::DATETIME_FS:
2411 case Datatype::DATETIME_AS:
2412 case Datatype::TIME_HR:
2413 case Datatype::TIME_MIN:
2414 case Datatype::TIME_SEC:
2415 case Datatype::TIME_MS:
2416 case Datatype::TIME_US:
2417 case Datatype::TIME_NS:
2418 case Datatype::TIME_PS:
2419 case Datatype::TIME_FS:
2420 case Datatype::TIME_AS:
2421 compute_mbr_func_ = compute_mbr<int64_t>;
2422 break;
2423 default:
2424 compute_mbr_func_ = nullptr;
2425 break;
2426 }
2427 } else { // Var-sized
2428 assert(type_ == Datatype::STRING_ASCII);
2429 compute_mbr_func_ = nullptr;
2430 compute_mbr_var_func_ = compute_mbr_var<char>;
2431 }
2432 }
2433
set_expand_range_func()2434 void Dimension::set_expand_range_func() {
2435 switch (type_) {
2436 case Datatype::INT32:
2437 expand_range_func_ = expand_range<int32_t>;
2438 break;
2439 case Datatype::INT64:
2440 expand_range_func_ = expand_range<int64_t>;
2441 break;
2442 case Datatype::INT8:
2443 expand_range_func_ = expand_range<int8_t>;
2444 break;
2445 case Datatype::UINT8:
2446 expand_range_func_ = expand_range<uint8_t>;
2447 break;
2448 case Datatype::INT16:
2449 expand_range_func_ = expand_range<int16_t>;
2450 break;
2451 case Datatype::UINT16:
2452 expand_range_func_ = expand_range<uint16_t>;
2453 break;
2454 case Datatype::UINT32:
2455 expand_range_func_ = expand_range<uint32_t>;
2456 break;
2457 case Datatype::UINT64:
2458 expand_range_func_ = expand_range<uint64_t>;
2459 break;
2460 case Datatype::FLOAT32:
2461 expand_range_func_ = expand_range<float>;
2462 break;
2463 case Datatype::FLOAT64:
2464 expand_range_func_ = expand_range<double>;
2465 break;
2466 case Datatype::DATETIME_YEAR:
2467 case Datatype::DATETIME_MONTH:
2468 case Datatype::DATETIME_WEEK:
2469 case Datatype::DATETIME_DAY:
2470 case Datatype::DATETIME_HR:
2471 case Datatype::DATETIME_MIN:
2472 case Datatype::DATETIME_SEC:
2473 case Datatype::DATETIME_MS:
2474 case Datatype::DATETIME_US:
2475 case Datatype::DATETIME_NS:
2476 case Datatype::DATETIME_PS:
2477 case Datatype::DATETIME_FS:
2478 case Datatype::DATETIME_AS:
2479 case Datatype::TIME_HR:
2480 case Datatype::TIME_MIN:
2481 case Datatype::TIME_SEC:
2482 case Datatype::TIME_MS:
2483 case Datatype::TIME_US:
2484 case Datatype::TIME_NS:
2485 case Datatype::TIME_PS:
2486 case Datatype::TIME_FS:
2487 case Datatype::TIME_AS:
2488 expand_range_func_ = expand_range<int64_t>;
2489 break;
2490 default:
2491 expand_range_func_ = nullptr;
2492 break;
2493 }
2494 }
2495
set_expand_range_v_func()2496 void Dimension::set_expand_range_v_func() {
2497 switch (type_) {
2498 case Datatype::INT32:
2499 expand_range_v_func_ = expand_range_v<int32_t>;
2500 break;
2501 case Datatype::INT64:
2502 expand_range_v_func_ = expand_range_v<int64_t>;
2503 break;
2504 case Datatype::INT8:
2505 expand_range_v_func_ = expand_range_v<int8_t>;
2506 break;
2507 case Datatype::UINT8:
2508 expand_range_v_func_ = expand_range_v<uint8_t>;
2509 break;
2510 case Datatype::INT16:
2511 expand_range_v_func_ = expand_range_v<int16_t>;
2512 break;
2513 case Datatype::UINT16:
2514 expand_range_v_func_ = expand_range_v<uint16_t>;
2515 break;
2516 case Datatype::UINT32:
2517 expand_range_v_func_ = expand_range_v<uint32_t>;
2518 break;
2519 case Datatype::UINT64:
2520 expand_range_v_func_ = expand_range_v<uint64_t>;
2521 break;
2522 case Datatype::FLOAT32:
2523 expand_range_v_func_ = expand_range_v<float>;
2524 break;
2525 case Datatype::FLOAT64:
2526 expand_range_v_func_ = expand_range_v<double>;
2527 break;
2528 case Datatype::DATETIME_YEAR:
2529 case Datatype::DATETIME_MONTH:
2530 case Datatype::DATETIME_WEEK:
2531 case Datatype::DATETIME_DAY:
2532 case Datatype::DATETIME_HR:
2533 case Datatype::DATETIME_MIN:
2534 case Datatype::DATETIME_SEC:
2535 case Datatype::DATETIME_MS:
2536 case Datatype::DATETIME_US:
2537 case Datatype::DATETIME_NS:
2538 case Datatype::DATETIME_PS:
2539 case Datatype::DATETIME_FS:
2540 case Datatype::DATETIME_AS:
2541 case Datatype::TIME_HR:
2542 case Datatype::TIME_MIN:
2543 case Datatype::TIME_SEC:
2544 case Datatype::TIME_MS:
2545 case Datatype::TIME_US:
2546 case Datatype::TIME_NS:
2547 case Datatype::TIME_PS:
2548 case Datatype::TIME_FS:
2549 case Datatype::TIME_AS:
2550 expand_range_v_func_ = expand_range_v<int64_t>;
2551 break;
2552 default:
2553 expand_range_v_func_ = nullptr;
2554 break;
2555 }
2556 }
2557
set_expand_to_tile_func()2558 void Dimension::set_expand_to_tile_func() {
2559 switch (type_) {
2560 case Datatype::INT32:
2561 expand_to_tile_func_ = expand_to_tile<int32_t>;
2562 break;
2563 case Datatype::INT64:
2564 expand_to_tile_func_ = expand_to_tile<int64_t>;
2565 break;
2566 case Datatype::INT8:
2567 expand_to_tile_func_ = expand_to_tile<int8_t>;
2568 break;
2569 case Datatype::UINT8:
2570 expand_to_tile_func_ = expand_to_tile<uint8_t>;
2571 break;
2572 case Datatype::INT16:
2573 expand_to_tile_func_ = expand_to_tile<int16_t>;
2574 break;
2575 case Datatype::UINT16:
2576 expand_to_tile_func_ = expand_to_tile<uint16_t>;
2577 break;
2578 case Datatype::UINT32:
2579 expand_to_tile_func_ = expand_to_tile<uint32_t>;
2580 break;
2581 case Datatype::UINT64:
2582 expand_to_tile_func_ = expand_to_tile<uint64_t>;
2583 break;
2584 case Datatype::FLOAT32:
2585 expand_to_tile_func_ = expand_to_tile<float>;
2586 break;
2587 case Datatype::FLOAT64:
2588 expand_to_tile_func_ = expand_to_tile<double>;
2589 break;
2590 case Datatype::DATETIME_YEAR:
2591 case Datatype::DATETIME_MONTH:
2592 case Datatype::DATETIME_WEEK:
2593 case Datatype::DATETIME_DAY:
2594 case Datatype::DATETIME_HR:
2595 case Datatype::DATETIME_MIN:
2596 case Datatype::DATETIME_SEC:
2597 case Datatype::DATETIME_MS:
2598 case Datatype::DATETIME_US:
2599 case Datatype::DATETIME_NS:
2600 case Datatype::DATETIME_PS:
2601 case Datatype::DATETIME_FS:
2602 case Datatype::DATETIME_AS:
2603 case Datatype::TIME_HR:
2604 case Datatype::TIME_MIN:
2605 case Datatype::TIME_SEC:
2606 case Datatype::TIME_MS:
2607 case Datatype::TIME_US:
2608 case Datatype::TIME_NS:
2609 case Datatype::TIME_PS:
2610 case Datatype::TIME_FS:
2611 case Datatype::TIME_AS:
2612 expand_to_tile_func_ = expand_to_tile<int64_t>;
2613 break;
2614 default:
2615 expand_to_tile_func_ = nullptr;
2616 break;
2617 }
2618 }
2619
set_oob_func()2620 void Dimension::set_oob_func() {
2621 switch (type_) {
2622 case Datatype::INT32:
2623 oob_func_ = oob<int32_t>;
2624 break;
2625 case Datatype::INT64:
2626 oob_func_ = oob<int64_t>;
2627 break;
2628 case Datatype::INT8:
2629 oob_func_ = oob<int8_t>;
2630 break;
2631 case Datatype::UINT8:
2632 oob_func_ = oob<uint8_t>;
2633 break;
2634 case Datatype::INT16:
2635 oob_func_ = oob<int16_t>;
2636 break;
2637 case Datatype::UINT16:
2638 oob_func_ = oob<uint16_t>;
2639 break;
2640 case Datatype::UINT32:
2641 oob_func_ = oob<uint32_t>;
2642 break;
2643 case Datatype::UINT64:
2644 oob_func_ = oob<uint64_t>;
2645 break;
2646 case Datatype::FLOAT32:
2647 oob_func_ = oob<float>;
2648 break;
2649 case Datatype::FLOAT64:
2650 oob_func_ = oob<double>;
2651 break;
2652 case Datatype::DATETIME_YEAR:
2653 case Datatype::DATETIME_MONTH:
2654 case Datatype::DATETIME_WEEK:
2655 case Datatype::DATETIME_DAY:
2656 case Datatype::DATETIME_HR:
2657 case Datatype::DATETIME_MIN:
2658 case Datatype::DATETIME_SEC:
2659 case Datatype::DATETIME_MS:
2660 case Datatype::DATETIME_US:
2661 case Datatype::DATETIME_NS:
2662 case Datatype::DATETIME_PS:
2663 case Datatype::DATETIME_FS:
2664 case Datatype::DATETIME_AS:
2665 case Datatype::TIME_HR:
2666 case Datatype::TIME_MIN:
2667 case Datatype::TIME_SEC:
2668 case Datatype::TIME_MS:
2669 case Datatype::TIME_US:
2670 case Datatype::TIME_NS:
2671 case Datatype::TIME_PS:
2672 case Datatype::TIME_FS:
2673 case Datatype::TIME_AS:
2674 oob_func_ = oob<int64_t>;
2675 break;
2676 default:
2677 oob_func_ = nullptr;
2678 break;
2679 }
2680 }
2681
set_covered_func()2682 void Dimension::set_covered_func() {
2683 switch (type_) {
2684 case Datatype::INT32:
2685 covered_func_ = covered<int32_t>;
2686 break;
2687 case Datatype::INT64:
2688 covered_func_ = covered<int64_t>;
2689 break;
2690 case Datatype::INT8:
2691 covered_func_ = covered<int8_t>;
2692 break;
2693 case Datatype::UINT8:
2694 covered_func_ = covered<uint8_t>;
2695 break;
2696 case Datatype::INT16:
2697 covered_func_ = covered<int16_t>;
2698 break;
2699 case Datatype::UINT16:
2700 covered_func_ = covered<uint16_t>;
2701 break;
2702 case Datatype::UINT32:
2703 covered_func_ = covered<uint32_t>;
2704 break;
2705 case Datatype::UINT64:
2706 covered_func_ = covered<uint64_t>;
2707 break;
2708 case Datatype::FLOAT32:
2709 covered_func_ = covered<float>;
2710 break;
2711 case Datatype::FLOAT64:
2712 covered_func_ = covered<double>;
2713 break;
2714 case Datatype::DATETIME_YEAR:
2715 case Datatype::DATETIME_MONTH:
2716 case Datatype::DATETIME_WEEK:
2717 case Datatype::DATETIME_DAY:
2718 case Datatype::DATETIME_HR:
2719 case Datatype::DATETIME_MIN:
2720 case Datatype::DATETIME_SEC:
2721 case Datatype::DATETIME_MS:
2722 case Datatype::DATETIME_US:
2723 case Datatype::DATETIME_NS:
2724 case Datatype::DATETIME_PS:
2725 case Datatype::DATETIME_FS:
2726 case Datatype::DATETIME_AS:
2727 case Datatype::TIME_HR:
2728 case Datatype::TIME_MIN:
2729 case Datatype::TIME_SEC:
2730 case Datatype::TIME_MS:
2731 case Datatype::TIME_US:
2732 case Datatype::TIME_NS:
2733 case Datatype::TIME_PS:
2734 case Datatype::TIME_FS:
2735 case Datatype::TIME_AS:
2736 covered_func_ = covered<int64_t>;
2737 break;
2738 case Datatype::STRING_ASCII:
2739 assert(var_size());
2740 covered_func_ = covered<char>;
2741 break;
2742 default:
2743 covered_func_ = nullptr;
2744 break;
2745 }
2746 }
2747
set_overlap_func()2748 void Dimension::set_overlap_func() {
2749 switch (type_) {
2750 case Datatype::INT32:
2751 overlap_func_ = overlap<int32_t>;
2752 break;
2753 case Datatype::INT64:
2754 overlap_func_ = overlap<int64_t>;
2755 break;
2756 case Datatype::INT8:
2757 overlap_func_ = overlap<int8_t>;
2758 break;
2759 case Datatype::UINT8:
2760 overlap_func_ = overlap<uint8_t>;
2761 break;
2762 case Datatype::INT16:
2763 overlap_func_ = overlap<int16_t>;
2764 break;
2765 case Datatype::UINT16:
2766 overlap_func_ = overlap<uint16_t>;
2767 break;
2768 case Datatype::UINT32:
2769 overlap_func_ = overlap<uint32_t>;
2770 break;
2771 case Datatype::UINT64:
2772 overlap_func_ = overlap<uint64_t>;
2773 break;
2774 case Datatype::FLOAT32:
2775 overlap_func_ = overlap<float>;
2776 break;
2777 case Datatype::FLOAT64:
2778 overlap_func_ = overlap<double>;
2779 break;
2780 case Datatype::DATETIME_YEAR:
2781 case Datatype::DATETIME_MONTH:
2782 case Datatype::DATETIME_WEEK:
2783 case Datatype::DATETIME_DAY:
2784 case Datatype::DATETIME_HR:
2785 case Datatype::DATETIME_MIN:
2786 case Datatype::DATETIME_SEC:
2787 case Datatype::DATETIME_MS:
2788 case Datatype::DATETIME_US:
2789 case Datatype::DATETIME_NS:
2790 case Datatype::DATETIME_PS:
2791 case Datatype::DATETIME_FS:
2792 case Datatype::DATETIME_AS:
2793 case Datatype::TIME_HR:
2794 case Datatype::TIME_MIN:
2795 case Datatype::TIME_SEC:
2796 case Datatype::TIME_MS:
2797 case Datatype::TIME_US:
2798 case Datatype::TIME_NS:
2799 case Datatype::TIME_PS:
2800 case Datatype::TIME_FS:
2801 case Datatype::TIME_AS:
2802 overlap_func_ = overlap<int64_t>;
2803 break;
2804 case Datatype::STRING_ASCII:
2805 assert(var_size());
2806 overlap_func_ = overlap<char>;
2807 break;
2808 default:
2809 overlap_func_ = nullptr;
2810 break;
2811 }
2812 }
2813
set_overlap_ratio_func()2814 void Dimension::set_overlap_ratio_func() {
2815 switch (type_) {
2816 case Datatype::INT32:
2817 overlap_ratio_func_ = overlap_ratio<int32_t>;
2818 break;
2819 case Datatype::INT64:
2820 overlap_ratio_func_ = overlap_ratio<int64_t>;
2821 break;
2822 case Datatype::INT8:
2823 overlap_ratio_func_ = overlap_ratio<int8_t>;
2824 break;
2825 case Datatype::UINT8:
2826 overlap_ratio_func_ = overlap_ratio<uint8_t>;
2827 break;
2828 case Datatype::INT16:
2829 overlap_ratio_func_ = overlap_ratio<int16_t>;
2830 break;
2831 case Datatype::UINT16:
2832 overlap_ratio_func_ = overlap_ratio<uint16_t>;
2833 break;
2834 case Datatype::UINT32:
2835 overlap_ratio_func_ = overlap_ratio<uint32_t>;
2836 break;
2837 case Datatype::UINT64:
2838 overlap_ratio_func_ = overlap_ratio<uint64_t>;
2839 break;
2840 case Datatype::FLOAT32:
2841 overlap_ratio_func_ = overlap_ratio<float>;
2842 break;
2843 case Datatype::FLOAT64:
2844 overlap_ratio_func_ = overlap_ratio<double>;
2845 break;
2846 case Datatype::DATETIME_YEAR:
2847 case Datatype::DATETIME_MONTH:
2848 case Datatype::DATETIME_WEEK:
2849 case Datatype::DATETIME_DAY:
2850 case Datatype::DATETIME_HR:
2851 case Datatype::DATETIME_MIN:
2852 case Datatype::DATETIME_SEC:
2853 case Datatype::DATETIME_MS:
2854 case Datatype::DATETIME_US:
2855 case Datatype::DATETIME_NS:
2856 case Datatype::DATETIME_PS:
2857 case Datatype::DATETIME_FS:
2858 case Datatype::DATETIME_AS:
2859 case Datatype::TIME_HR:
2860 case Datatype::TIME_MIN:
2861 case Datatype::TIME_SEC:
2862 case Datatype::TIME_MS:
2863 case Datatype::TIME_US:
2864 case Datatype::TIME_NS:
2865 case Datatype::TIME_PS:
2866 case Datatype::TIME_FS:
2867 case Datatype::TIME_AS:
2868 overlap_ratio_func_ = overlap_ratio<int64_t>;
2869 break;
2870 case Datatype::STRING_ASCII:
2871 assert(var_size());
2872 overlap_ratio_func_ = overlap_ratio<char>;
2873 break;
2874 default:
2875 overlap_ratio_func_ = nullptr;
2876 break;
2877 }
2878 }
2879
set_split_range_func()2880 void Dimension::set_split_range_func() {
2881 switch (type_) {
2882 case Datatype::INT32:
2883 split_range_func_ = split_range<int32_t>;
2884 break;
2885 case Datatype::INT64:
2886 split_range_func_ = split_range<int64_t>;
2887 break;
2888 case Datatype::INT8:
2889 split_range_func_ = split_range<int8_t>;
2890 break;
2891 case Datatype::UINT8:
2892 split_range_func_ = split_range<uint8_t>;
2893 break;
2894 case Datatype::INT16:
2895 split_range_func_ = split_range<int16_t>;
2896 break;
2897 case Datatype::UINT16:
2898 split_range_func_ = split_range<uint16_t>;
2899 break;
2900 case Datatype::UINT32:
2901 split_range_func_ = split_range<uint32_t>;
2902 break;
2903 case Datatype::UINT64:
2904 split_range_func_ = split_range<uint64_t>;
2905 break;
2906 case Datatype::FLOAT32:
2907 split_range_func_ = split_range<float>;
2908 break;
2909 case Datatype::FLOAT64:
2910 split_range_func_ = split_range<double>;
2911 break;
2912 case Datatype::DATETIME_YEAR:
2913 case Datatype::DATETIME_MONTH:
2914 case Datatype::DATETIME_WEEK:
2915 case Datatype::DATETIME_DAY:
2916 case Datatype::DATETIME_HR:
2917 case Datatype::DATETIME_MIN:
2918 case Datatype::DATETIME_SEC:
2919 case Datatype::DATETIME_MS:
2920 case Datatype::DATETIME_US:
2921 case Datatype::DATETIME_NS:
2922 case Datatype::DATETIME_PS:
2923 case Datatype::DATETIME_FS:
2924 case Datatype::DATETIME_AS:
2925 case Datatype::TIME_HR:
2926 case Datatype::TIME_MIN:
2927 case Datatype::TIME_SEC:
2928 case Datatype::TIME_MS:
2929 case Datatype::TIME_US:
2930 case Datatype::TIME_NS:
2931 case Datatype::TIME_PS:
2932 case Datatype::TIME_FS:
2933 case Datatype::TIME_AS:
2934 split_range_func_ = split_range<int64_t>;
2935 break;
2936 case Datatype::STRING_ASCII:
2937 split_range_func_ = split_range<char>;
2938 break;
2939 default:
2940 split_range_func_ = nullptr;
2941 break;
2942 }
2943 }
2944
set_splitting_value_func()2945 void Dimension::set_splitting_value_func() {
2946 switch (type_) {
2947 case Datatype::INT32:
2948 splitting_value_func_ = splitting_value<int32_t>;
2949 break;
2950 case Datatype::INT64:
2951 splitting_value_func_ = splitting_value<int64_t>;
2952 break;
2953 case Datatype::INT8:
2954 splitting_value_func_ = splitting_value<int8_t>;
2955 break;
2956 case Datatype::UINT8:
2957 splitting_value_func_ = splitting_value<uint8_t>;
2958 break;
2959 case Datatype::INT16:
2960 splitting_value_func_ = splitting_value<int16_t>;
2961 break;
2962 case Datatype::UINT16:
2963 splitting_value_func_ = splitting_value<uint16_t>;
2964 break;
2965 case Datatype::UINT32:
2966 splitting_value_func_ = splitting_value<uint32_t>;
2967 break;
2968 case Datatype::UINT64:
2969 splitting_value_func_ = splitting_value<uint64_t>;
2970 break;
2971 case Datatype::FLOAT32:
2972 splitting_value_func_ = splitting_value<float>;
2973 break;
2974 case Datatype::FLOAT64:
2975 splitting_value_func_ = splitting_value<double>;
2976 break;
2977 case Datatype::DATETIME_YEAR:
2978 case Datatype::DATETIME_MONTH:
2979 case Datatype::DATETIME_WEEK:
2980 case Datatype::DATETIME_DAY:
2981 case Datatype::DATETIME_HR:
2982 case Datatype::DATETIME_MIN:
2983 case Datatype::DATETIME_SEC:
2984 case Datatype::DATETIME_MS:
2985 case Datatype::DATETIME_US:
2986 case Datatype::DATETIME_NS:
2987 case Datatype::DATETIME_PS:
2988 case Datatype::DATETIME_FS:
2989 case Datatype::DATETIME_AS:
2990 case Datatype::TIME_HR:
2991 case Datatype::TIME_MIN:
2992 case Datatype::TIME_SEC:
2993 case Datatype::TIME_MS:
2994 case Datatype::TIME_US:
2995 case Datatype::TIME_NS:
2996 case Datatype::TIME_PS:
2997 case Datatype::TIME_FS:
2998 case Datatype::TIME_AS:
2999 splitting_value_func_ = splitting_value<int64_t>;
3000 break;
3001 case Datatype::STRING_ASCII:
3002 assert(var_size());
3003 splitting_value_func_ = splitting_value<char>;
3004 break;
3005 default:
3006 splitting_value_func_ = nullptr;
3007 break;
3008 }
3009 }
3010
set_tile_num_func()3011 void Dimension::set_tile_num_func() {
3012 switch (type_) {
3013 case Datatype::INT32:
3014 tile_num_func_ = tile_num<int32_t>;
3015 break;
3016 case Datatype::INT64:
3017 tile_num_func_ = tile_num<int64_t>;
3018 break;
3019 case Datatype::INT8:
3020 tile_num_func_ = tile_num<int8_t>;
3021 break;
3022 case Datatype::UINT8:
3023 tile_num_func_ = tile_num<uint8_t>;
3024 break;
3025 case Datatype::INT16:
3026 tile_num_func_ = tile_num<int16_t>;
3027 break;
3028 case Datatype::UINT16:
3029 tile_num_func_ = tile_num<uint16_t>;
3030 break;
3031 case Datatype::UINT32:
3032 tile_num_func_ = tile_num<uint32_t>;
3033 break;
3034 case Datatype::UINT64:
3035 tile_num_func_ = tile_num<uint64_t>;
3036 break;
3037 case Datatype::FLOAT32:
3038 tile_num_func_ = tile_num<float>;
3039 break;
3040 case Datatype::FLOAT64:
3041 tile_num_func_ = tile_num<double>;
3042 break;
3043 case Datatype::DATETIME_YEAR:
3044 case Datatype::DATETIME_MONTH:
3045 case Datatype::DATETIME_WEEK:
3046 case Datatype::DATETIME_DAY:
3047 case Datatype::DATETIME_HR:
3048 case Datatype::DATETIME_MIN:
3049 case Datatype::DATETIME_SEC:
3050 case Datatype::DATETIME_MS:
3051 case Datatype::DATETIME_US:
3052 case Datatype::DATETIME_NS:
3053 case Datatype::DATETIME_PS:
3054 case Datatype::DATETIME_FS:
3055 case Datatype::DATETIME_AS:
3056 case Datatype::TIME_HR:
3057 case Datatype::TIME_MIN:
3058 case Datatype::TIME_SEC:
3059 case Datatype::TIME_MS:
3060 case Datatype::TIME_US:
3061 case Datatype::TIME_NS:
3062 case Datatype::TIME_PS:
3063 case Datatype::TIME_FS:
3064 case Datatype::TIME_AS:
3065 tile_num_func_ = tile_num<int64_t>;
3066 break;
3067 case Datatype::STRING_ASCII:
3068 tile_num_func_ = tile_num<char>;
3069 break;
3070 default:
3071 tile_num_func_ = nullptr;
3072 break;
3073 }
3074 }
3075
set_map_to_uint64_func()3076 void Dimension::set_map_to_uint64_func() {
3077 switch (type_) {
3078 case Datatype::INT32:
3079 map_to_uint64_func_ = map_to_uint64<int32_t>;
3080 break;
3081 case Datatype::INT64:
3082 map_to_uint64_func_ = map_to_uint64<int64_t>;
3083 break;
3084 case Datatype::INT8:
3085 map_to_uint64_func_ = map_to_uint64<int8_t>;
3086 break;
3087 case Datatype::UINT8:
3088 map_to_uint64_func_ = map_to_uint64<uint8_t>;
3089 break;
3090 case Datatype::INT16:
3091 map_to_uint64_func_ = map_to_uint64<int16_t>;
3092 break;
3093 case Datatype::UINT16:
3094 map_to_uint64_func_ = map_to_uint64<uint16_t>;
3095 break;
3096 case Datatype::UINT32:
3097 map_to_uint64_func_ = map_to_uint64<uint32_t>;
3098 break;
3099 case Datatype::UINT64:
3100 map_to_uint64_func_ = map_to_uint64<uint64_t>;
3101 break;
3102 case Datatype::FLOAT32:
3103 map_to_uint64_func_ = map_to_uint64<float>;
3104 break;
3105 case Datatype::FLOAT64:
3106 map_to_uint64_func_ = map_to_uint64<double>;
3107 break;
3108 case Datatype::DATETIME_YEAR:
3109 case Datatype::DATETIME_MONTH:
3110 case Datatype::DATETIME_WEEK:
3111 case Datatype::DATETIME_DAY:
3112 case Datatype::DATETIME_HR:
3113 case Datatype::DATETIME_MIN:
3114 case Datatype::DATETIME_SEC:
3115 case Datatype::DATETIME_MS:
3116 case Datatype::DATETIME_US:
3117 case Datatype::DATETIME_NS:
3118 case Datatype::DATETIME_PS:
3119 case Datatype::DATETIME_FS:
3120 case Datatype::DATETIME_AS:
3121 case Datatype::TIME_HR:
3122 case Datatype::TIME_MIN:
3123 case Datatype::TIME_SEC:
3124 case Datatype::TIME_MS:
3125 case Datatype::TIME_US:
3126 case Datatype::TIME_NS:
3127 case Datatype::TIME_PS:
3128 case Datatype::TIME_FS:
3129 case Datatype::TIME_AS:
3130 map_to_uint64_func_ = map_to_uint64<int64_t>;
3131 break;
3132 case Datatype::STRING_ASCII:
3133 map_to_uint64_func_ = map_to_uint64<char>;
3134 break;
3135 default:
3136 map_to_uint64_func_ = nullptr;
3137 break;
3138 }
3139 }
3140
set_map_to_uint64_2_func()3141 void Dimension::set_map_to_uint64_2_func() {
3142 switch (type_) {
3143 case Datatype::INT32:
3144 map_to_uint64_2_func_ = map_to_uint64_2<int32_t>;
3145 break;
3146 case Datatype::INT64:
3147 map_to_uint64_2_func_ = map_to_uint64_2<int64_t>;
3148 break;
3149 case Datatype::INT8:
3150 map_to_uint64_2_func_ = map_to_uint64_2<int8_t>;
3151 break;
3152 case Datatype::UINT8:
3153 map_to_uint64_2_func_ = map_to_uint64_2<uint8_t>;
3154 break;
3155 case Datatype::INT16:
3156 map_to_uint64_2_func_ = map_to_uint64_2<int16_t>;
3157 break;
3158 case Datatype::UINT16:
3159 map_to_uint64_2_func_ = map_to_uint64_2<uint16_t>;
3160 break;
3161 case Datatype::UINT32:
3162 map_to_uint64_2_func_ = map_to_uint64_2<uint32_t>;
3163 break;
3164 case Datatype::UINT64:
3165 map_to_uint64_2_func_ = map_to_uint64_2<uint64_t>;
3166 break;
3167 case Datatype::FLOAT32:
3168 map_to_uint64_2_func_ = map_to_uint64_2<float>;
3169 break;
3170 case Datatype::FLOAT64:
3171 map_to_uint64_2_func_ = map_to_uint64_2<double>;
3172 break;
3173 case Datatype::DATETIME_YEAR:
3174 case Datatype::DATETIME_MONTH:
3175 case Datatype::DATETIME_WEEK:
3176 case Datatype::DATETIME_DAY:
3177 case Datatype::DATETIME_HR:
3178 case Datatype::DATETIME_MIN:
3179 case Datatype::DATETIME_SEC:
3180 case Datatype::DATETIME_MS:
3181 case Datatype::DATETIME_US:
3182 case Datatype::DATETIME_NS:
3183 case Datatype::DATETIME_PS:
3184 case Datatype::DATETIME_FS:
3185 case Datatype::DATETIME_AS:
3186 case Datatype::TIME_HR:
3187 case Datatype::TIME_MIN:
3188 case Datatype::TIME_SEC:
3189 case Datatype::TIME_MS:
3190 case Datatype::TIME_US:
3191 case Datatype::TIME_NS:
3192 case Datatype::TIME_PS:
3193 case Datatype::TIME_FS:
3194 case Datatype::TIME_AS:
3195 map_to_uint64_2_func_ = map_to_uint64_2<int64_t>;
3196 break;
3197 case Datatype::STRING_ASCII:
3198 map_to_uint64_2_func_ = map_to_uint64_2<char>;
3199 break;
3200 default:
3201 map_to_uint64_2_func_ = nullptr;
3202 break;
3203 }
3204 }
3205
set_map_to_uint64_3_func()3206 void Dimension::set_map_to_uint64_3_func() {
3207 switch (type_) {
3208 case Datatype::INT32:
3209 map_to_uint64_3_func_ = map_to_uint64_3<int32_t>;
3210 break;
3211 case Datatype::INT64:
3212 map_to_uint64_3_func_ = map_to_uint64_3<int64_t>;
3213 break;
3214 case Datatype::INT8:
3215 map_to_uint64_3_func_ = map_to_uint64_3<int8_t>;
3216 break;
3217 case Datatype::UINT8:
3218 map_to_uint64_3_func_ = map_to_uint64_3<uint8_t>;
3219 break;
3220 case Datatype::INT16:
3221 map_to_uint64_3_func_ = map_to_uint64_3<int16_t>;
3222 break;
3223 case Datatype::UINT16:
3224 map_to_uint64_3_func_ = map_to_uint64_3<uint16_t>;
3225 break;
3226 case Datatype::UINT32:
3227 map_to_uint64_3_func_ = map_to_uint64_3<uint32_t>;
3228 break;
3229 case Datatype::UINT64:
3230 map_to_uint64_3_func_ = map_to_uint64_3<uint64_t>;
3231 break;
3232 case Datatype::FLOAT32:
3233 map_to_uint64_3_func_ = map_to_uint64_3<float>;
3234 break;
3235 case Datatype::FLOAT64:
3236 map_to_uint64_3_func_ = map_to_uint64_3<double>;
3237 break;
3238 case Datatype::DATETIME_YEAR:
3239 case Datatype::DATETIME_MONTH:
3240 case Datatype::DATETIME_WEEK:
3241 case Datatype::DATETIME_DAY:
3242 case Datatype::DATETIME_HR:
3243 case Datatype::DATETIME_MIN:
3244 case Datatype::DATETIME_SEC:
3245 case Datatype::DATETIME_MS:
3246 case Datatype::DATETIME_US:
3247 case Datatype::DATETIME_NS:
3248 case Datatype::DATETIME_PS:
3249 case Datatype::DATETIME_FS:
3250 case Datatype::DATETIME_AS:
3251 case Datatype::TIME_HR:
3252 case Datatype::TIME_MIN:
3253 case Datatype::TIME_SEC:
3254 case Datatype::TIME_MS:
3255 case Datatype::TIME_US:
3256 case Datatype::TIME_NS:
3257 case Datatype::TIME_PS:
3258 case Datatype::TIME_FS:
3259 case Datatype::TIME_AS:
3260 map_to_uint64_3_func_ = map_to_uint64_3<int64_t>;
3261 break;
3262 case Datatype::STRING_ASCII:
3263 map_to_uint64_3_func_ = map_to_uint64_3<char>;
3264 break;
3265 default:
3266 map_to_uint64_3_func_ = nullptr;
3267 break;
3268 }
3269 }
3270
set_map_from_uint64_func()3271 void Dimension::set_map_from_uint64_func() {
3272 switch (type_) {
3273 case Datatype::INT32:
3274 map_from_uint64_func_ = map_from_uint64<int32_t>;
3275 break;
3276 case Datatype::INT64:
3277 map_from_uint64_func_ = map_from_uint64<int64_t>;
3278 break;
3279 case Datatype::INT8:
3280 map_from_uint64_func_ = map_from_uint64<int8_t>;
3281 break;
3282 case Datatype::UINT8:
3283 map_from_uint64_func_ = map_from_uint64<uint8_t>;
3284 break;
3285 case Datatype::INT16:
3286 map_from_uint64_func_ = map_from_uint64<int16_t>;
3287 break;
3288 case Datatype::UINT16:
3289 map_from_uint64_func_ = map_from_uint64<uint16_t>;
3290 break;
3291 case Datatype::UINT32:
3292 map_from_uint64_func_ = map_from_uint64<uint32_t>;
3293 break;
3294 case Datatype::UINT64:
3295 map_from_uint64_func_ = map_from_uint64<uint64_t>;
3296 break;
3297 case Datatype::FLOAT32:
3298 map_from_uint64_func_ = map_from_uint64<float>;
3299 break;
3300 case Datatype::FLOAT64:
3301 map_from_uint64_func_ = map_from_uint64<double>;
3302 break;
3303 case Datatype::DATETIME_YEAR:
3304 case Datatype::DATETIME_MONTH:
3305 case Datatype::DATETIME_WEEK:
3306 case Datatype::DATETIME_DAY:
3307 case Datatype::DATETIME_HR:
3308 case Datatype::DATETIME_MIN:
3309 case Datatype::DATETIME_SEC:
3310 case Datatype::DATETIME_MS:
3311 case Datatype::DATETIME_US:
3312 case Datatype::DATETIME_NS:
3313 case Datatype::DATETIME_PS:
3314 case Datatype::DATETIME_FS:
3315 case Datatype::DATETIME_AS:
3316 case Datatype::TIME_HR:
3317 case Datatype::TIME_MIN:
3318 case Datatype::TIME_SEC:
3319 case Datatype::TIME_MS:
3320 case Datatype::TIME_US:
3321 case Datatype::TIME_NS:
3322 case Datatype::TIME_PS:
3323 case Datatype::TIME_FS:
3324 case Datatype::TIME_AS:
3325 map_from_uint64_func_ = map_from_uint64<int64_t>;
3326 break;
3327 case Datatype::STRING_ASCII:
3328 map_from_uint64_func_ = map_from_uint64<char>;
3329 break;
3330 default:
3331 map_from_uint64_func_ = nullptr;
3332 break;
3333 }
3334 }
3335
set_smaller_than_func()3336 void Dimension::set_smaller_than_func() {
3337 switch (type_) {
3338 case Datatype::INT32:
3339 smaller_than_func_ = smaller_than<int32_t>;
3340 break;
3341 case Datatype::INT64:
3342 smaller_than_func_ = smaller_than<int64_t>;
3343 break;
3344 case Datatype::INT8:
3345 smaller_than_func_ = smaller_than<int8_t>;
3346 break;
3347 case Datatype::UINT8:
3348 smaller_than_func_ = smaller_than<uint8_t>;
3349 break;
3350 case Datatype::INT16:
3351 smaller_than_func_ = smaller_than<int16_t>;
3352 break;
3353 case Datatype::UINT16:
3354 smaller_than_func_ = smaller_than<uint16_t>;
3355 break;
3356 case Datatype::UINT32:
3357 smaller_than_func_ = smaller_than<uint32_t>;
3358 break;
3359 case Datatype::UINT64:
3360 smaller_than_func_ = smaller_than<uint64_t>;
3361 break;
3362 case Datatype::FLOAT32:
3363 smaller_than_func_ = smaller_than<float>;
3364 break;
3365 case Datatype::FLOAT64:
3366 smaller_than_func_ = smaller_than<double>;
3367 break;
3368 case Datatype::DATETIME_YEAR:
3369 case Datatype::DATETIME_MONTH:
3370 case Datatype::DATETIME_WEEK:
3371 case Datatype::DATETIME_DAY:
3372 case Datatype::DATETIME_HR:
3373 case Datatype::DATETIME_MIN:
3374 case Datatype::DATETIME_SEC:
3375 case Datatype::DATETIME_MS:
3376 case Datatype::DATETIME_US:
3377 case Datatype::DATETIME_NS:
3378 case Datatype::DATETIME_PS:
3379 case Datatype::DATETIME_FS:
3380 case Datatype::DATETIME_AS:
3381 case Datatype::TIME_HR:
3382 case Datatype::TIME_MIN:
3383 case Datatype::TIME_SEC:
3384 case Datatype::TIME_MS:
3385 case Datatype::TIME_US:
3386 case Datatype::TIME_NS:
3387 case Datatype::TIME_PS:
3388 case Datatype::TIME_FS:
3389 case Datatype::TIME_AS:
3390 smaller_than_func_ = smaller_than<int64_t>;
3391 break;
3392 case Datatype::STRING_ASCII:
3393 smaller_than_func_ = smaller_than<char>;
3394 break;
3395 default:
3396 smaller_than_func_ = nullptr;
3397 break;
3398 }
3399 }
3400
3401 } // namespace sm
3402 } // namespace tiledb
3403