@@ -240,6 +240,174 @@ void CurrentDomain::check_schema_sanity(
240
240
}
241
241
}
242
242
243
+ /*
244
+ * This is a templatized auxiliary for expand_to_tiles,
245
+ * dispatched on the (necessarily integral) type of a given domain slot.
246
+ */
247
+ template <typename T>
248
+ void expand_to_tiles_aux (
249
+ CurrentDomain::dimension_size_type dimidx,
250
+ const Dimension* dimptr,
251
+ std::shared_ptr<NDRectangle> cur_dom_ndrect,
252
+ NDRange& query_ndrange) {
253
+ // No extents for string dims, etc.
254
+ if constexpr (!std::is_integral_v<T>) {
255
+ return ;
256
+ }
257
+
258
+ // Find the initial lo/hi for the query range on this dimension.
259
+ auto query_slot = query_ndrange[dimidx];
260
+ auto query_slot_range = (const T*)query_slot.data ();
261
+
262
+ // Find the lo/hi for the current domain on this dimension.
263
+ auto cur_dom_slot_range = (const T*)cur_dom_ndrect->get_range (dimidx).data ();
264
+
265
+ // Find the lo/hi for the core domain (max domain) on this dimension.
266
+ auto dim_dom = (const T*)dimptr->domain ().data ();
267
+
268
+ // Find the tile extent.
269
+ auto tile_extent = *(const T*)dimptr->tile_extent ().data ();
270
+
271
+ // Compute tile indices: e.g. if the extent is 512 and the query lo is
272
+ // 1027, that's tile 2.
273
+ T domain_low = dim_dom[0 ];
274
+ auto tile_idx0 =
275
+ Dimension::tile_idx (query_slot_range[0 ], domain_low, tile_extent);
276
+ auto tile_idx1 =
277
+ Dimension::tile_idx (query_slot_range[1 ], domain_low, tile_extent);
278
+
279
+ // Round up to a multiple of the tile coords. E.g. if the query range
280
+ // starts out as (3,4) but the tile extent is 512, that will become (0,511).
281
+ T result[2 ];
282
+ result[0 ] = Dimension::tile_coord_low (tile_idx0, domain_low, tile_extent);
283
+ result[1 ] = Dimension::tile_coord_high (tile_idx1, domain_low, tile_extent);
284
+
285
+ /*
286
+ * Since there is a current domain, though (we assume our caller checks this),
287
+ * rounding up to a multiple of the tile extent will lead to an out-of-bounds
288
+ * read. Make the query range lo no smaller than current domain lo on this
289
+ * dimension, and make the query range hi no larger than current domain hi on
290
+ * this dimension.
291
+ */
292
+ result[0 ] = std::max (result[0 ], cur_dom_slot_range[0 ]);
293
+ result[1 ] = std::min (result[1 ], cur_dom_slot_range[1 ]);
294
+
295
+ // Update the query range
296
+ query_slot.set_range (result, sizeof (result));
297
+ }
298
+
299
+ /* The job here is, for a given domain slot:
300
+ * Given query ranges (nominally, for dense consolidation)
301
+ * Given the core current domain (which may be empty)
302
+ * Given the core (max) domain
303
+ * Given initial query bounds
304
+ * If the current domain is empty:
305
+ * o round the query to tile boundaries
306
+ * Else:
307
+ * o round the query to tile boundaries, but not outside the current domain
308
+ *
309
+ * Example on one dim slot:
310
+ * - Say non-empty domain is (3,4)
311
+ * - Say tile extent is 512
312
+ * - Say domain is (0,99999)
313
+ * - If current domain is empty: send (3,4) to (0,511)
314
+ * - If current domain is (2, 63): send (3,4) to (2,63)
315
+ */
316
+ void CurrentDomain::expand_to_tiles (
317
+ const Domain& domain, NDRange& query_ndrange) const {
318
+ if (query_ndrange.empty ()) {
319
+ throw std::invalid_argument (" Query range is empty" );
320
+ }
321
+
322
+ if (this ->empty ()) {
323
+ domain.expand_to_tiles_when_no_current_domain (query_ndrange);
324
+ return ;
325
+ }
326
+
327
+ if (this ->type () != CurrentDomainType::NDRECTANGLE) {
328
+ return ;
329
+ }
330
+
331
+ auto cur_dom_ndrect = this ->ndrectangle ();
332
+
333
+ if (query_ndrange.size () != domain.dim_num ()) {
334
+ throw std::invalid_argument (
335
+ " Query range size does not match domain dimension size" );
336
+ }
337
+
338
+ for (CurrentDomain::dimension_size_type dimidx = 0 ; dimidx < domain.dim_num ();
339
+ dimidx++) {
340
+ const auto dimptr = domain.dimension_ptr (dimidx);
341
+
342
+ if (dimptr->var_size ()) {
343
+ continue ;
344
+ }
345
+
346
+ if (!dimptr->tile_extent ()) {
347
+ continue ;
348
+ }
349
+
350
+ switch (dimptr->type ()) {
351
+ case Datatype::INT64:
352
+ case Datatype::DATETIME_YEAR:
353
+ case Datatype::DATETIME_MONTH:
354
+ case Datatype::DATETIME_WEEK:
355
+ case Datatype::DATETIME_DAY:
356
+ case Datatype::DATETIME_HR:
357
+ case Datatype::DATETIME_MIN:
358
+ case Datatype::DATETIME_SEC:
359
+ case Datatype::DATETIME_MS:
360
+ case Datatype::DATETIME_US:
361
+ case Datatype::DATETIME_NS:
362
+ case Datatype::DATETIME_PS:
363
+ case Datatype::DATETIME_FS:
364
+ case Datatype::DATETIME_AS:
365
+ case Datatype::TIME_HR:
366
+ case Datatype::TIME_MIN:
367
+ case Datatype::TIME_SEC:
368
+ case Datatype::TIME_MS:
369
+ case Datatype::TIME_US:
370
+ case Datatype::TIME_NS:
371
+ case Datatype::TIME_PS:
372
+ case Datatype::TIME_FS:
373
+ case Datatype::TIME_AS:
374
+ expand_to_tiles_aux<int64_t >(
375
+ dimidx, dimptr, cur_dom_ndrect, query_ndrange);
376
+ break ;
377
+ case Datatype::UINT64:
378
+ expand_to_tiles_aux<uint64_t >(
379
+ dimidx, dimptr, cur_dom_ndrect, query_ndrange);
380
+ break ;
381
+ case Datatype::INT32:
382
+ expand_to_tiles_aux<int32_t >(
383
+ dimidx, dimptr, cur_dom_ndrect, query_ndrange);
384
+ break ;
385
+ case Datatype::UINT32:
386
+ expand_to_tiles_aux<uint32_t >(
387
+ dimidx, dimptr, cur_dom_ndrect, query_ndrange);
388
+ break ;
389
+ case Datatype::INT16:
390
+ expand_to_tiles_aux<int16_t >(
391
+ dimidx, dimptr, cur_dom_ndrect, query_ndrange);
392
+ break ;
393
+ case Datatype::UINT16:
394
+ expand_to_tiles_aux<uint16_t >(
395
+ dimidx, dimptr, cur_dom_ndrect, query_ndrange);
396
+ break ;
397
+ case Datatype::INT8:
398
+ expand_to_tiles_aux<int8_t >(
399
+ dimidx, dimptr, cur_dom_ndrect, query_ndrange);
400
+ break ;
401
+ case Datatype::UINT8:
402
+ expand_to_tiles_aux<uint8_t >(
403
+ dimidx, dimptr, cur_dom_ndrect, query_ndrange);
404
+ break ;
405
+ default :
406
+ break ;
407
+ }
408
+ }
409
+ }
410
+
243
411
} // namespace tiledb::sm
244
412
245
413
std::ostream& operator <<(
0 commit comments