1#pragma once
2
3#include <AggregateFunctions/AggregateFunctionFactory.h>
4#include <Columns/ColumnAggregateFunction.h>
5#include <Columns/ColumnArray.h>
6#include <Columns/ColumnConst.h>
7#include <Columns/ColumnVector.h>
8#include <Columns/ColumnsNumber.h>
9#include <DataTypes/DataTypeAggregateFunction.h>
10#include <DataTypes/DataTypeArray.h>
11#include <DataTypes/DataTypesNumber.h>
12#include <Functions/FunctionHelpers.h>
13#include <Functions/IFunctionImpl.h>
14#include <Common/typeid_cast.h>
15#include <Common/assert_cast.h>
16
17// TODO include this last because of a broken roaring header. See the comment
18// inside.
19#include <AggregateFunctions/AggregateFunctionGroupBitmapData.h>
20
21namespace DB
22{
23namespace ErrorCodes
24{
25 extern const int LOGICAL_ERROR;
26 extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
27}
28
29/** Bitmap functions.
30 * Build a bitmap from integer array:
31 * bitmapBuild: integer[] -> bitmap
32 *
33 * Convert bitmap to integer array:
34 * bitmapToArray: bitmap -> integer[]
35 *
36 * Retrun the smallest value in the set:
37 * bitmapMin: bitmap -> integer
38 *
39 * Retrun the greatest value in the set:
40 * bitmapMax: bitmap -> integer
41 *
42 * Return subset in specified range (not include the range_end):
43 * bitmapSubsetInRange: bitmap,integer,integer -> bitmap
44 *
45 * Return subset of the smallest `limit` values in set which is no smaller than `range_start`.
46 * bitmapSubsetLimit: bitmap,integer,integer -> bitmap
47 *
48 * Transform an array of values in a bitmap to another array of values, the result is a new bitmap.
49 * bitmapTransform: bitmap,integer[],integer[] -> bitmap
50 *
51 * Two bitmap and calculation:
52 * bitmapAnd: bitmap,bitmap -> bitmap
53 *
54 * Two bitmap or calculation:
55 * bitmapOr: bitmap,bitmap -> bitmap
56 *
57 * Two bitmap xor calculation:
58 * bitmapXor: bitmap,bitmap -> bitmap
59 *
60 * Two bitmap andnot calculation:
61 * bitmapAndnot: bitmap,bitmap -> bitmap
62 *
63 * Retrun bitmap cardinality:
64 * bitmapCardinality: bitmap -> integer
65 *
66 * Two bitmap and calculation, return cardinality:
67 * bitmapAndCardinality: bitmap,bitmap -> integer
68 *
69 * Two bitmap or calculation, return cardinality:
70 * bitmapOrCardinality: bitmap,bitmap -> integer
71 *
72 * Two bitmap xor calculation, return cardinality:
73 * bitmapXorCardinality: bitmap,bitmap -> integer
74 *
75 * Two bitmap andnot calculation, return cardinality:
76 * bitmapAndnotCardinality: bitmap,bitmap -> integer
77 *
78 * Determine if a bitmap contains the given integer:
79 * bitmapContains: bitmap,integer -> bool
80 *
81 * Judge if a bitmap is superset of the another one:
82 * bitmapHasAll: bitmap,bitmap -> bool
83 *
84 * Judge if the intersection of two bitmap is nonempty:
85 * bitmapHasAny: bitmap,bitmap -> bool
86 */
87
88template <typename Name>
89class FunctionBitmapBuildImpl : public IFunction
90{
91public:
92 static constexpr auto name = Name::name;
93
94 static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapBuildImpl>(); }
95
96 String getName() const override { return name; }
97
98 bool isVariadic() const override { return false; }
99
100 size_t getNumberOfArguments() const override { return 1; }
101
102 DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
103 {
104 if (arguments[0]->onlyNull())
105 return arguments[0];
106
107 auto array_type = typeid_cast<const DataTypeArray *>(arguments[0].get());
108 if (!array_type)
109 throw Exception(
110 "First argument for function " + getName() + " must be an array but it has type " + arguments[0]->getName() + ".",
111 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
112
113 auto nested_type = array_type->getNestedType();
114 DataTypes argument_types = {nested_type};
115 Array params_row;
116 AggregateFunctionPtr bitmap_function
117 = AggregateFunctionFactory::instance().get(AggregateFunctionGroupBitmapData<UInt32>::name(), argument_types, params_row);
118
119 return std::make_shared<DataTypeAggregateFunction>(bitmap_function, argument_types, params_row);
120 }
121
122 bool useDefaultImplementationForConstants() const override { return true; }
123
124 void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /* input_rows_count */) override
125 {
126 const IDataType * from_type = block.getByPosition(arguments[0]).type.get();
127 auto array_type = typeid_cast<const DataTypeArray *>(from_type);
128 auto nested_type = array_type->getNestedType();
129
130 DataTypes argument_types = {nested_type};
131
132 WhichDataType which(nested_type);
133 if (which.isUInt8())
134 executeBitmapData<UInt8>(block, argument_types, arguments, result);
135 else if (which.isUInt16())
136 executeBitmapData<UInt16>(block, argument_types, arguments, result);
137 else if (which.isUInt32())
138 executeBitmapData<UInt32>(block, argument_types, arguments, result);
139 else if (which.isUInt64())
140 executeBitmapData<UInt64>(block, argument_types, arguments, result);
141 else
142 throw Exception(
143 "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
144 }
145
146private:
147 template <typename T>
148 void executeBitmapData(Block & block, DataTypes & argument_types, const ColumnNumbers & arguments, size_t result)
149 {
150 // input data
151 const ColumnArray * array = typeid_cast<const ColumnArray *>(block.getByPosition(arguments[0]).column.get());
152 ColumnPtr mapped = array->getDataPtr();
153 const ColumnArray::Offsets & offsets = array->getOffsets();
154 const ColumnVector<T> * column = checkAndGetColumn<ColumnVector<T>>(&*mapped);
155 const typename ColumnVector<T>::Container & input_data = column->getData();
156
157 // output data
158 Array params_row;
159 AggregateFunctionPtr bitmap_function
160 = AggregateFunctionFactory::instance().get(AggregateFunctionGroupBitmapData<UInt32>::name(), argument_types, params_row);
161 auto col_to = ColumnAggregateFunction::create(bitmap_function);
162 col_to->reserve(offsets.size());
163
164 size_t pos = 0;
165 for (size_t i = 0; i < offsets.size(); ++i)
166 {
167 col_to->insertDefault();
168 AggregateFunctionGroupBitmapData<T> & bitmap_data
169 = *reinterpret_cast<AggregateFunctionGroupBitmapData<T> *>(col_to->getData()[i]);
170 for (; pos < offsets[i]; ++pos)
171 {
172 bitmap_data.rbs.add(input_data[pos]);
173 }
174 }
175 block.getByPosition(result).column = std::move(col_to);
176 }
177};
178
179template <typename Name>
180class FunctionBitmapToArrayImpl : public IFunction
181{
182public:
183 static constexpr auto name = Name::name;
184
185 static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapToArrayImpl>(); }
186
187 String getName() const override { return name; }
188
189 bool isVariadic() const override { return false; }
190
191 size_t getNumberOfArguments() const override { return 1; }
192
193 DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
194 {
195 const DataTypeAggregateFunction * bitmap_type = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
196 if (!(bitmap_type && bitmap_type->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
197 throw Exception(
198 "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + ".",
199 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
200
201 const DataTypePtr data_type = bitmap_type->getArgumentsDataTypes()[0];
202
203 return std::make_shared<DataTypeArray>(data_type);
204 }
205
206 bool useDefaultImplementationForConstants() const override { return true; }
207
208 void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
209 {
210 // input data
211 const auto & return_type = block.getByPosition(result).type;
212 auto res_ptr = return_type->createColumn();
213 ColumnArray & res = assert_cast<ColumnArray &>(*res_ptr);
214
215 IColumn & res_data = res.getData();
216 ColumnArray::Offsets & res_offsets = res.getOffsets();
217
218 const IDataType * from_type = block.getByPosition(arguments[0]).type.get();
219 const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
220 WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
221 if (which.isUInt8())
222 executeIntType<UInt8>(block, arguments, input_rows_count, res_data, res_offsets);
223 else if (which.isUInt16())
224 executeIntType<UInt16>(block, arguments, input_rows_count, res_data, res_offsets);
225 else if (which.isUInt32())
226 executeIntType<UInt32>(block, arguments, input_rows_count, res_data, res_offsets);
227 else if (which.isUInt64())
228 executeIntType<UInt64>(block, arguments, input_rows_count, res_data, res_offsets);
229 else
230 throw Exception(
231 "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
232
233 block.getByPosition(result).column = std::move(res_ptr);
234 }
235
236private:
237 using ToType = UInt64;
238
239 template <typename T>
240 void executeIntType(
241 Block & block, const ColumnNumbers & arguments, size_t input_rows_count, IColumn & res_data_col, ColumnArray::Offsets & res_offsets)
242 const
243 {
244 const ColumnAggregateFunction * column
245 = typeid_cast<const ColumnAggregateFunction *>(block.getByPosition(arguments[0]).column.get());
246
247 PaddedPODArray<T> & res_data = typeid_cast<ColumnVector<T> &>(res_data_col).getData();
248 ColumnArray::Offset res_offset = 0;
249
250 for (size_t i = 0; i < input_rows_count; ++i)
251 {
252 const AggregateFunctionGroupBitmapData<T> & bitmap_data_1
253 = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(column->getData()[i]);
254 UInt64 count = bitmap_data_1.rbs.rb_to_array(res_data);
255 res_offset += count;
256 res_offsets.emplace_back(res_offset);
257 }
258 }
259};
260
261template <typename Impl>
262class FunctionBitmapSubset : public IFunction
263{
264public:
265 static constexpr auto name = Impl::name;
266
267 static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapSubset<Impl>>(); }
268
269 String getName() const override { return name; }
270
271 bool isVariadic() const override { return false; }
272
273 size_t getNumberOfArguments() const override { return 3; }
274
275 DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
276 {
277 const DataTypeAggregateFunction * bitmap_type = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
278 if (!(bitmap_type && bitmap_type->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
279 throw Exception(
280 "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + ".",
281 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
282
283 auto arg_type1 = typeid_cast<const DataTypeNumber<UInt32> *>(arguments[1].get());
284 if (!(arg_type1))
285 throw Exception(
286 "Second argument for function " + getName() + " must be UInt32 but it has type " + arguments[1]->getName() + ".",
287 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
288
289 auto arg_type2 = typeid_cast<const DataTypeNumber<UInt32> *>(arguments[1].get());
290 if (!(arg_type2))
291 throw Exception(
292 "Third argument for function " + getName() + " must be UInt32 but it has type " + arguments[2]->getName() + ".",
293 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
294
295 return arguments[0];
296 }
297
298 bool useDefaultImplementationForConstants() const override { return true; }
299
300 void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
301 {
302 const IDataType * from_type = block.getByPosition(arguments[0]).type.get();
303 const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
304 WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
305 if (which.isUInt8())
306 executeIntType<UInt8>(block, arguments, result, input_rows_count);
307 else if (which.isUInt16())
308 executeIntType<UInt16>(block, arguments, result, input_rows_count);
309 else if (which.isUInt32())
310 executeIntType<UInt32>(block, arguments, result, input_rows_count);
311 else if (which.isUInt64())
312 executeIntType<UInt64>(block, arguments, result, input_rows_count);
313 else
314 throw Exception(
315 "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
316 }
317
318private:
319 using ToType = UInt64;
320
321 template <typename T>
322 void executeIntType(
323 Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count)
324 const
325 {
326 const IColumn * columns[3];
327 bool is_column_const[3];
328 const ColumnAggregateFunction * col_agg_func;
329 const PaddedPODArray<AggregateDataPtr> * container0;
330 const PaddedPODArray<UInt32> * container1, * container2;
331
332 for (size_t i = 0; i < 3; ++i)
333 {
334 columns[i] = block.getByPosition(arguments[i]).column.get();
335 is_column_const[i] = isColumnConst(*columns[i]);
336 }
337 if (is_column_const[0])
338 col_agg_func = typeid_cast<const ColumnAggregateFunction*>(typeid_cast<const ColumnConst*>(columns[0])->getDataColumnPtr().get());
339 else
340 col_agg_func = typeid_cast<const ColumnAggregateFunction*>(columns[0]);
341
342 container0 = &col_agg_func->getData();
343 if (is_column_const[1])
344 container1 = &typeid_cast<const ColumnUInt32*>(typeid_cast<const ColumnConst*>(columns[1])->getDataColumnPtr().get())->getData();
345 else
346 container1 = &typeid_cast<const ColumnUInt32*>(columns[1])->getData();
347 if (is_column_const[2])
348 container2 = &typeid_cast<const ColumnUInt32*>(typeid_cast<const ColumnConst*>(columns[2])->getDataColumnPtr().get())->getData();
349 else
350 container2 = &typeid_cast<const ColumnUInt32*>(columns[2])->getData();
351
352 auto col_to = ColumnAggregateFunction::create(col_agg_func->getAggregateFunction());
353 col_to->reserve(input_rows_count);
354
355 for (size_t i = 0; i < input_rows_count; ++i)
356 {
357 const AggregateDataPtr data_ptr_0 = is_column_const[0] ? (*container0)[0] : (*container0)[i];
358 const AggregateFunctionGroupBitmapData<T> & bitmap_data_0
359 = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T>*>(data_ptr_0);
360 const UInt32 range_start = is_column_const[1] ? (*container1)[0] : (*container1)[i];
361 const UInt32 range_end = is_column_const[2] ? (*container2)[0] : (*container2)[i];
362
363 col_to->insertDefault();
364 AggregateFunctionGroupBitmapData<T> & bitmap_data_2
365 = *reinterpret_cast<AggregateFunctionGroupBitmapData<T> *>(col_to->getData()[i]);
366 Impl::apply(bitmap_data_0, range_start, range_end, bitmap_data_2);
367 }
368 block.getByPosition(result).column = std::move(col_to);
369 }
370};
371
372struct BitmapSubsetInRangeImpl
373{
374public:
375 static constexpr auto name = "bitmapSubsetInRange";
376 template <typename T>
377 static void apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_0, UInt32 range_start, UInt32 range_end, AggregateFunctionGroupBitmapData<T> & bitmap_data_2)
378 {
379 bitmap_data_0.rbs.rb_range(range_start, range_end, bitmap_data_2.rbs);
380 }
381};
382
383struct BitmapSubsetLimitImpl
384{
385public:
386 static constexpr auto name = "bitmapSubsetLimit";
387 template <typename T>
388 static void apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_0, UInt32 range_start, UInt32 range_end, AggregateFunctionGroupBitmapData<T> & bitmap_data_2)
389 {
390 bitmap_data_0.rbs.rb_limit(range_start, range_end, bitmap_data_2.rbs);
391 }
392};
393
394using FunctionBitmapSubsetInRange = FunctionBitmapSubset<BitmapSubsetInRangeImpl>;
395using FunctionBitmapSubsetLimit = FunctionBitmapSubset<BitmapSubsetLimitImpl>;
396
397
398class FunctionBitmapTransform : public IFunction
399{
400public:
401 static constexpr auto name = "bitmapTransform";
402
403 static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapTransform>(); }
404
405 String getName() const override { return name; }
406
407 bool isVariadic() const override { return false; }
408
409 size_t getNumberOfArguments() const override { return 3; }
410
411 DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
412 {
413 const DataTypeAggregateFunction * bitmap_type = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
414 if (!(bitmap_type && bitmap_type->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
415 throw Exception(
416 "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + ".",
417 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
418 for (size_t i = 0; i < 2; ++i)
419 {
420 auto array_type = typeid_cast<const DataTypeArray *>(arguments[i + 1].get());
421 String msg(i == 0 ? "Second" : "Third");
422 msg += " argument for function " + getName() + " must be an UInt32 array but it has type " + arguments[i + 1]->getName() + ".";
423 if (!array_type)
424 throw Exception(msg, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
425
426 auto nested_type = array_type->getNestedType();
427 WhichDataType which(nested_type);
428 if (!which.isUInt32())
429 throw Exception(msg, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
430 }
431 return arguments[0];
432 }
433
434 bool useDefaultImplementationForConstants() const override { return true; }
435
436 void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
437 {
438 const IDataType * from_type = block.getByPosition(arguments[0]).type.get();
439 const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
440 WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
441 if (which.isUInt8())
442 executeIntType<UInt8>(block, arguments, result, input_rows_count);
443 else if (which.isUInt16())
444 executeIntType<UInt16>(block, arguments, result, input_rows_count);
445 else if (which.isUInt32())
446 executeIntType<UInt32>(block, arguments, result, input_rows_count);
447 else if (which.isUInt64())
448 executeIntType<UInt64>(block, arguments, result, input_rows_count);
449 else
450 throw Exception(
451 "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
452 }
453
454private:
455 using ToType = UInt64;
456
457 template <typename T>
458 void executeIntType(
459 Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const
460 {
461 const IColumn * columns[3];
462 bool is_column_const[3];
463 const ColumnAggregateFunction * col_agg_func;
464 const PaddedPODArray<AggregateDataPtr> * container0;
465 const ColumnArray * array;
466
467 for (size_t i = 0; i < 3; ++i)
468 {
469 columns[i] = block.getByPosition(arguments[i]).column.get();
470 is_column_const[i] = isColumnConst(*columns[i]);
471 }
472 if (is_column_const[0])
473 {
474 col_agg_func = typeid_cast<const ColumnAggregateFunction*>(typeid_cast<const ColumnConst*>(columns[0])->getDataColumnPtr().get());
475 }
476 else
477 {
478 col_agg_func = typeid_cast<const ColumnAggregateFunction*>(columns[0]);
479 }
480 container0 = &col_agg_func->getData();
481
482 if (is_column_const[1])
483 array = typeid_cast<const ColumnArray*>(typeid_cast<const ColumnConst*>(columns[1])->getDataColumnPtr().get());
484 else
485 {
486 array = typeid_cast<const ColumnArray *>(block.getByPosition(arguments[1]).column.get());
487 }
488 const ColumnArray::Offsets & from_offsets = array->getOffsets();
489 const ColumnVector<UInt32>::Container & from_container = typeid_cast<const ColumnVector<UInt32> *>(&array->getData())->getData();
490
491 if (is_column_const[2])
492 array = typeid_cast<const ColumnArray*>(typeid_cast<const ColumnConst*>(columns[2])->getDataColumnPtr().get());
493 else
494 array = typeid_cast<const ColumnArray *>(block.getByPosition(arguments[2]).column.get());
495
496 const ColumnArray::Offsets & to_offsets = array->getOffsets();
497 const ColumnVector<UInt32>::Container & to_container = typeid_cast<const ColumnVector<UInt32> *>(&array->getData())->getData();
498 auto col_to = ColumnAggregateFunction::create(col_agg_func->getAggregateFunction());
499 col_to->reserve(input_rows_count);
500
501 size_t from_start;
502 size_t from_end;
503 size_t to_start;
504 size_t to_end;
505 for (size_t i = 0; i < input_rows_count; ++i)
506 {
507 const AggregateDataPtr data_ptr_0 = is_column_const[0] ? (*container0)[0] : (*container0)[i];
508 const AggregateFunctionGroupBitmapData<T> & bitmap_data_0
509 = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(data_ptr_0);
510 if (is_column_const[1])
511 {
512 from_start = 0;
513 from_end = from_container.size();
514 }
515 else
516 {
517 from_start = i == 0 ? 0 : from_offsets[i - 1];
518 from_end = from_offsets[i];
519 }
520 if (is_column_const[2])
521 {
522 to_start = 0;
523 to_end = to_container.size();
524 }
525 else
526 {
527 to_start = i == 0 ? 0 : to_offsets[i - 1];
528 to_end = to_offsets[i];
529 }
530 if (from_end - from_start != to_end - to_start)
531 throw Exception("From array size and to array size mismatch", ErrorCodes::LOGICAL_ERROR);
532
533 col_to->insertDefault();
534 AggregateFunctionGroupBitmapData<T> & bitmap_data_2
535 = *reinterpret_cast<AggregateFunctionGroupBitmapData<T> *>(col_to->getData()[i]);
536 bitmap_data_2.rbs.merge(bitmap_data_0.rbs);
537 bitmap_data_2.rbs.rb_replace(&from_container[from_start], &to_container[to_start], from_end - from_start);
538 }
539 block.getByPosition(result).column = std::move(col_to);
540 }
541};
542
543template <typename Impl>
544class FunctionBitmapSelfCardinalityImpl : public IFunction
545{
546public:
547 static constexpr auto name = Impl::name;
548
549 static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapSelfCardinalityImpl<Impl>>(); }
550
551 String getName() const override { return name; }
552
553 bool isVariadic() const override { return false; }
554
555 size_t getNumberOfArguments() const override { return 1; }
556
557 DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
558 {
559 auto bitmap_type = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
560 if (!(bitmap_type && bitmap_type->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
561 throw Exception(
562 "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + ".",
563 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
564 return std::make_shared<DataTypeNumber<ToType>>();
565 }
566
567 bool useDefaultImplementationForConstants() const override { return true; }
568
569 void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
570 {
571 auto col_to = ColumnVector<ToType>::create(input_rows_count);
572 typename ColumnVector<ToType>::Container & vec_to = col_to->getData();
573 const IDataType * from_type = block.getByPosition(arguments[0]).type.get();
574
575 const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
576 WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
577 if (which.isUInt8())
578 executeIntType<UInt8>(block, arguments, input_rows_count, vec_to);
579 else if (which.isUInt16())
580 executeIntType<UInt16>(block, arguments, input_rows_count, vec_to);
581 else if (which.isUInt32())
582 executeIntType<UInt32>(block, arguments, input_rows_count, vec_to);
583 else if (which.isUInt64())
584 executeIntType<UInt64>(block, arguments, input_rows_count, vec_to);
585 else
586 throw Exception(
587 "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
588
589 block.getByPosition(result).column = std::move(col_to);
590 }
591
592private:
593 using ToType = UInt64;
594
595 template <typename T>
596 void executeIntType(
597 Block & block, const ColumnNumbers & arguments, size_t input_rows_count, typename ColumnVector<ToType>::Container & vec_to)
598 {
599 const ColumnAggregateFunction * column
600 = typeid_cast<const ColumnAggregateFunction *>(block.getByPosition(arguments[0]).column.get());
601 for (size_t i = 0; i < input_rows_count; ++i)
602 {
603 const AggregateFunctionGroupBitmapData<T> & bitmap_data
604 = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(column->getData()[i]);
605 vec_to[i] = Impl::apply(bitmap_data);
606 }
607 }
608};
609
610struct BitmapCardinalityImpl
611{
612public:
613 static constexpr auto name = "bitmapCardinality";
614 template <typename T>
615 static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data)
616 {
617 return bitmap_data.rbs.size();
618 }
619};
620
621struct BitmapMinImpl
622{
623public:
624 static constexpr auto name = "bitmapMin";
625 template <typename T>
626 static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data)
627 {
628 return bitmap_data.rbs.rb_min();
629 }
630};
631
632struct BitmapMaxImpl
633{
634public:
635 static constexpr auto name = "bitmapMax";
636 template <typename T>
637 static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data)
638 {
639 return bitmap_data.rbs.rb_max();
640 }
641};
642
643template <typename T>
644struct BitmapAndCardinalityImpl
645{
646 using ReturnType = UInt64;
647 static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2)
648 {
649 // roaring_bitmap_and_cardinality( rb1, rb2 );
650 return bitmap_data_1.rbs.rb_and_cardinality(bitmap_data_2.rbs);
651 }
652};
653
654
655template <typename T>
656struct BitmapOrCardinalityImpl
657{
658 using ReturnType = UInt64;
659 static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2)
660 {
661 // return roaring_bitmap_or_cardinality( rb1, rb2 );
662 return bitmap_data_1.rbs.rb_or_cardinality(bitmap_data_2.rbs);
663 }
664};
665
666template <typename T>
667struct BitmapXorCardinalityImpl
668{
669 using ReturnType = UInt64;
670 static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2)
671 {
672 // return roaring_bitmap_xor_cardinality( rb1, rb2 );
673 return bitmap_data_1.rbs.rb_xor_cardinality(bitmap_data_2.rbs);
674 }
675};
676
677template <typename T>
678struct BitmapAndnotCardinalityImpl
679{
680 using ReturnType = UInt64;
681 static UInt64 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2)
682 {
683 // roaring_bitmap_andnot_cardinality( rb1, rb2 );
684 return bitmap_data_1.rbs.rb_andnot_cardinality(bitmap_data_2.rbs);
685 }
686};
687
688template <typename T>
689struct BitmapHasAllImpl
690{
691 using ReturnType = UInt8;
692 static UInt8 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2)
693 {
694 return bitmap_data_1.rbs.rb_is_subset(bitmap_data_2.rbs);
695 }
696};
697
698template <typename T>
699struct BitmapHasAnyImpl
700{
701 using ReturnType = UInt8;
702 static UInt8 apply(const AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2)
703 {
704 return bitmap_data_1.rbs.rb_intersect(bitmap_data_2.rbs);
705 }
706};
707
708class FunctionBitmapContains : public IFunction
709{
710public:
711 static constexpr auto name = "bitmapContains";
712
713 static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapContains>(); }
714
715 String getName() const override { return name; }
716
717 bool isVariadic() const override { return false; }
718
719 size_t getNumberOfArguments() const override { return 2; }
720
721 DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
722 {
723 auto bitmap_type0 = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
724 if (!(bitmap_type0 && bitmap_type0->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
725 throw Exception(
726 "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + ".",
727 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
728 auto arg_type1 = typeid_cast<const DataTypeNumber<UInt32> *>(arguments[1].get());
729 if (!(arg_type1))
730 throw Exception(
731 "Second argument for function " + getName() + " must be UInt32 but it has type " + arguments[1]->getName() + ".",
732 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
733
734 return std::make_shared<DataTypeNumber<UInt8>>();
735 }
736
737 bool useDefaultImplementationForConstants() const override { return true; }
738
739 void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
740 {
741 auto col_to = ColumnVector<UInt8>::create(input_rows_count);
742 typename ColumnVector<UInt8>::Container & vec_to = col_to->getData();
743 const IDataType * from_type = block.getByPosition(arguments[0]).type.get();
744
745 const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
746 WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
747 if (which.isUInt8())
748 executeIntType<UInt8>(block, arguments, input_rows_count, vec_to);
749 else if (which.isUInt16())
750 executeIntType<UInt16>(block, arguments, input_rows_count, vec_to);
751 else if (which.isUInt32())
752 executeIntType<UInt32>(block, arguments, input_rows_count, vec_to);
753 else if (which.isUInt64())
754 executeIntType<UInt64>(block, arguments, input_rows_count, vec_to);
755 else
756 throw Exception(
757 "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
758
759 block.getByPosition(result).column = std::move(col_to);
760 }
761
762private:
763 template <typename T>
764 void executeIntType(
765 Block & block, const ColumnNumbers & arguments, size_t input_rows_count, typename ColumnVector<UInt8>::Container & vec_to)
766 {
767 const IColumn * columns[2];
768 bool is_column_const[2];
769 const PaddedPODArray<AggregateDataPtr> * container0;
770 const PaddedPODArray<UInt32> * container1;
771
772 for (size_t i = 0; i < 2; ++i)
773 {
774 columns[i] = block.getByPosition(arguments[i]).column.get();
775 is_column_const[i] = isColumnConst(*columns[i]);
776 }
777 if (is_column_const[0])
778 container0 = &typeid_cast<const ColumnAggregateFunction*>(typeid_cast<const ColumnConst*>(columns[0])->getDataColumnPtr().get())->getData();
779 else
780 container0 = &typeid_cast<const ColumnAggregateFunction*>(columns[0])->getData();
781 if (is_column_const[1])
782 container1 = &typeid_cast<const ColumnUInt32*>(typeid_cast<const ColumnConst*>(columns[1])->getDataColumnPtr().get())->getData();
783 else
784 container1 = &typeid_cast<const ColumnUInt32*>(columns[1])->getData();
785
786 for (size_t i = 0; i < input_rows_count; ++i)
787 {
788 const AggregateDataPtr data_ptr_0 = is_column_const[0] ? (*container0)[0] : (*container0)[i];
789 const UInt32 data1 = is_column_const[1] ? (*container1)[0] : (*container1)[i];
790 const AggregateFunctionGroupBitmapData<T> & bitmap_data_0
791 = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(data_ptr_0);
792 vec_to[i] = bitmap_data_0.rbs.rb_contains(data1);
793 }
794 }
795};
796
797template <template <typename> class Impl, typename Name, typename ToType>
798class FunctionBitmapCardinality : public IFunction
799{
800public:
801 static constexpr auto name = Name::name;
802
803 static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmapCardinality>(); }
804
805 String getName() const override { return name; }
806
807 bool isVariadic() const override { return false; }
808
809 size_t getNumberOfArguments() const override { return 2; }
810
811 DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
812 {
813 auto bitmap_type0 = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
814 if (!(bitmap_type0 && bitmap_type0->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
815 throw Exception(
816 "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + ".",
817 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
818
819 auto bitmap_type1 = typeid_cast<const DataTypeAggregateFunction *>(arguments[1].get());
820 if (!(bitmap_type1 && bitmap_type1->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
821 throw Exception(
822 "Second argument for function " + getName() + " must be a bitmap but it has type " + arguments[1]->getName() + ".",
823 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
824
825 if (bitmap_type0->getArgumentsDataTypes()[0]->getTypeId() != bitmap_type1->getArgumentsDataTypes()[0]->getTypeId())
826 throw Exception(
827 "The nested type in bitmaps must be the same, but one is " + bitmap_type0->getArgumentsDataTypes()[0]->getName()
828 + ", and the other is " + bitmap_type1->getArgumentsDataTypes()[0]->getName(),
829 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
830
831 return std::make_shared<DataTypeNumber<ToType>>();
832 }
833
834 bool useDefaultImplementationForConstants() const override { return true; }
835
836 void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
837 {
838 auto col_to = ColumnVector<ToType>::create(input_rows_count);
839 typename ColumnVector<ToType>::Container & vec_to = col_to->getData();
840 const IDataType * from_type = block.getByPosition(arguments[0]).type.get();
841
842 const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
843 WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
844 if (which.isUInt8())
845 executeIntType<UInt8>(block, arguments, input_rows_count, vec_to);
846 else if (which.isUInt16())
847 executeIntType<UInt16>(block, arguments, input_rows_count, vec_to);
848 else if (which.isUInt32())
849 executeIntType<UInt32>(block, arguments, input_rows_count, vec_to);
850 else if (which.isUInt64())
851 executeIntType<UInt64>(block, arguments, input_rows_count, vec_to);
852 else
853 throw Exception(
854 "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
855
856 block.getByPosition(result).column = std::move(col_to);
857 }
858
859private:
860 template <typename T>
861 void executeIntType(
862 Block & block, const ColumnNumbers & arguments, size_t input_rows_count, typename ColumnVector<ToType>::Container & vec_to)
863 {
864 const ColumnAggregateFunction * columns[2];
865 bool is_column_const[2];
866 for (size_t i = 0; i < 2; ++i)
867 {
868 if (auto argument_column_const = checkAndGetColumn<ColumnConst>(block.getByPosition(arguments[i]).column.get()))
869 {
870 columns[i] = typeid_cast<const ColumnAggregateFunction*>(argument_column_const->getDataColumnPtr().get());
871 is_column_const[i] = true;
872 }
873 else
874 {
875 columns[i] = typeid_cast<const ColumnAggregateFunction*>(block.getByPosition(arguments[i]).column.get());
876 is_column_const[i] = false;
877 }
878 }
879
880 const PaddedPODArray<AggregateDataPtr> & container0 = columns[0]->getData();
881 const PaddedPODArray<AggregateDataPtr> & container1 = columns[1]->getData();
882
883 for (size_t i = 0; i < input_rows_count; ++i)
884 {
885 const AggregateDataPtr data_ptr_0 = is_column_const[0] ? container0[0] : container0[i];
886 const AggregateDataPtr data_ptr_1 = is_column_const[1] ? container1[0] : container1[i];
887 const AggregateFunctionGroupBitmapData<T> & bitmap_data_1
888 = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(data_ptr_0);
889 const AggregateFunctionGroupBitmapData<T> & bitmap_data_2
890 = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(data_ptr_1);
891 vec_to[i] = Impl<T>::apply(bitmap_data_1, bitmap_data_2);
892 }
893 }
894};
895
896template <typename T>
897struct BitmapAndImpl
898{
899 static void apply(AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2)
900 {
901 bitmap_data_1.rbs.rb_and(bitmap_data_2.rbs);
902 }
903};
904
905template <typename T>
906struct BitmapOrImpl
907{
908 static void apply(AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2)
909 {
910 bitmap_data_1.rbs.rb_or(bitmap_data_2.rbs);
911 }
912};
913
914template <typename T>
915struct BitmapXorImpl
916{
917 static void apply(AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2)
918 {
919 bitmap_data_1.rbs.rb_xor(bitmap_data_2.rbs);
920 }
921};
922
923template <typename T>
924struct BitmapAndnotImpl
925{
926 static void apply(AggregateFunctionGroupBitmapData<T> & bitmap_data_1, const AggregateFunctionGroupBitmapData<T> & bitmap_data_2)
927 {
928 bitmap_data_1.rbs.rb_andnot(bitmap_data_2.rbs);
929 }
930};
931
932template <template <typename> class Impl, typename Name>
933class FunctionBitmap : public IFunction
934{
935public:
936 static constexpr auto name = Name::name;
937
938 static FunctionPtr create(const Context &) { return std::make_shared<FunctionBitmap>(); }
939
940 String getName() const override { return name; }
941
942 bool isVariadic() const override { return false; }
943
944 size_t getNumberOfArguments() const override { return 2; }
945
946 DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
947 {
948 auto bitmap_type0 = typeid_cast<const DataTypeAggregateFunction *>(arguments[0].get());
949 if (!(bitmap_type0 && bitmap_type0->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
950 throw Exception(
951 "First argument for function " + getName() + " must be a bitmap but it has type " + arguments[0]->getName() + ".",
952 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
953
954 auto bitmap_type1 = typeid_cast<const DataTypeAggregateFunction *>(arguments[1].get());
955 if (!(bitmap_type1 && bitmap_type1->getFunctionName() == AggregateFunctionGroupBitmapData<UInt32>::name()))
956 throw Exception(
957 "Second argument for function " + getName() + " must be a bitmap but it has type " + arguments[1]->getName() + ".",
958 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
959
960 if (bitmap_type0->getArgumentsDataTypes()[0]->getTypeId() != bitmap_type1->getArgumentsDataTypes()[0]->getTypeId())
961 throw Exception(
962 "The nested type in bitmaps must be the same, but one is " + bitmap_type0->getArgumentsDataTypes()[0]->getName()
963 + ", and the other is " + bitmap_type1->getArgumentsDataTypes()[0]->getName(),
964 ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
965
966 return arguments[0];
967 }
968
969 bool useDefaultImplementationForConstants() const override { return true; }
970
971 void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
972 {
973 const IDataType * from_type = block.getByPosition(arguments[0]).type.get();
974 const DataTypeAggregateFunction * aggr_type = typeid_cast<const DataTypeAggregateFunction *>(from_type);
975 WhichDataType which(aggr_type->getArgumentsDataTypes()[0]);
976 if (which.isUInt8())
977 executeBitmapData<UInt8>(block, arguments, result, input_rows_count);
978 else if (which.isUInt16())
979 executeBitmapData<UInt16>(block, arguments, result, input_rows_count);
980 else if (which.isUInt32())
981 executeBitmapData<UInt32>(block, arguments, result, input_rows_count);
982 else if (which.isUInt64())
983 executeBitmapData<UInt64>(block, arguments, result, input_rows_count);
984 else
985 throw Exception(
986 "Unexpected type " + from_type->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
987 }
988
989private:
990 template <typename T>
991 void executeBitmapData(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count)
992 {
993 const ColumnAggregateFunction * columns[2];
994 bool is_column_const[2];
995 for (size_t i = 0; i < 2; ++i)
996 {
997 if (auto argument_column_const = typeid_cast<const ColumnConst *>(block.getByPosition(arguments[i]).column.get()))
998 {
999 columns[i] = typeid_cast<const ColumnAggregateFunction *>(argument_column_const->getDataColumnPtr().get());
1000 is_column_const[i] = true;
1001 }
1002 else
1003 {
1004 columns[i] = typeid_cast<const ColumnAggregateFunction *>(block.getByPosition(arguments[i]).column.get());
1005 is_column_const[i] = false;
1006 }
1007 }
1008
1009 auto col_to = ColumnAggregateFunction::create(columns[0]->getAggregateFunction());
1010
1011 col_to->reserve(input_rows_count);
1012
1013 const PaddedPODArray<AggregateDataPtr> & container0 = columns[0]->getData();
1014 const PaddedPODArray<AggregateDataPtr> & container1 = columns[1]->getData();
1015
1016 for (size_t i = 0; i < input_rows_count; ++i)
1017 {
1018 const AggregateDataPtr data_ptr_0 = is_column_const[0] ? container0[0] : container0[i];
1019 const AggregateDataPtr data_ptr_1 = is_column_const[1] ? container1[0] : container1[i];
1020
1021 col_to->insertFrom(data_ptr_0);
1022 AggregateFunctionGroupBitmapData<T> & bitmap_data_1 = *reinterpret_cast<AggregateFunctionGroupBitmapData<T> *>(col_to->getData()[i]);
1023 const AggregateFunctionGroupBitmapData<T> & bitmap_data_2
1024 = *reinterpret_cast<const AggregateFunctionGroupBitmapData<T> *>(data_ptr_1);
1025 Impl<T>::apply(bitmap_data_1, bitmap_data_2);
1026 }
1027 block.getByPosition(result).column = std::move(col_to);
1028 }
1029};
1030
1031struct NameBitmapBuild
1032{
1033 static constexpr auto name = "bitmapBuild";
1034};
1035using FunctionBitmapBuild = FunctionBitmapBuildImpl<NameBitmapBuild>;
1036
1037struct NameBitmapToArray
1038{
1039 static constexpr auto name = "bitmapToArray";
1040};
1041using FunctionBitmapToArray = FunctionBitmapToArrayImpl<NameBitmapToArray>;
1042
1043struct NameBitmapCardinality
1044{
1045 static constexpr auto name = "bitmapCardinality";
1046};
1047struct NameBitmapAndCardinality
1048{
1049 static constexpr auto name = "bitmapAndCardinality";
1050};
1051struct NameBitmapOrCardinality
1052{
1053 static constexpr auto name = "bitmapOrCardinality";
1054};
1055struct NameBitmapXorCardinality
1056{
1057 static constexpr auto name = "bitmapXorCardinality";
1058};
1059struct NameBitmapAndnotCardinality
1060{
1061 static constexpr auto name = "bitmapAndnotCardinality";
1062};
1063struct NameBitmapHasAll
1064{
1065 static constexpr auto name = "bitmapHasAll";
1066};
1067struct NameBitmapHasAny
1068{
1069 static constexpr auto name = "bitmapHasAny";
1070};
1071
1072using FunctionBitmapSelfCardinality = FunctionBitmapSelfCardinalityImpl<BitmapCardinalityImpl>;
1073using FunctionBitmapMin = FunctionBitmapSelfCardinalityImpl<BitmapMinImpl>;
1074using FunctionBitmapMax = FunctionBitmapSelfCardinalityImpl<BitmapMaxImpl>;
1075using FunctionBitmapAndCardinality = FunctionBitmapCardinality<BitmapAndCardinalityImpl, NameBitmapAndCardinality, UInt64>;
1076using FunctionBitmapOrCardinality = FunctionBitmapCardinality<BitmapOrCardinalityImpl, NameBitmapOrCardinality, UInt64>;
1077using FunctionBitmapXorCardinality = FunctionBitmapCardinality<BitmapXorCardinalityImpl, NameBitmapXorCardinality, UInt64>;
1078using FunctionBitmapAndnotCardinality = FunctionBitmapCardinality<BitmapAndnotCardinalityImpl, NameBitmapAndnotCardinality, UInt64>;
1079using FunctionBitmapHasAll = FunctionBitmapCardinality<BitmapHasAllImpl, NameBitmapHasAll, UInt8>;
1080using FunctionBitmapHasAny = FunctionBitmapCardinality<BitmapHasAnyImpl, NameBitmapHasAny, UInt8>;
1081
1082struct NameBitmapAnd
1083{
1084 static constexpr auto name = "bitmapAnd";
1085};
1086struct NameBitmapOr
1087{
1088 static constexpr auto name = "bitmapOr";
1089};
1090struct NameBitmapXor
1091{
1092 static constexpr auto name = "bitmapXor";
1093};
1094struct NameBitmapAndnot
1095{
1096 static constexpr auto name = "bitmapAndnot";
1097};
1098using FunctionBitmapAnd = FunctionBitmap<BitmapAndImpl, NameBitmapAnd>;
1099using FunctionBitmapOr = FunctionBitmap<BitmapOrImpl, NameBitmapOr>;
1100using FunctionBitmapXor = FunctionBitmap<BitmapXorImpl, NameBitmapXor>;
1101using FunctionBitmapAndnot = FunctionBitmap<BitmapAndnotImpl, NameBitmapAndnot>;
1102
1103
1104}
1105