be/src/exprs/bitset_container.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #pragma once |
19 | | |
20 | | #include <array> |
21 | | #include <cstddef> |
22 | | #include <cstdint> |
23 | | #include <type_traits> |
24 | | #include <vector> |
25 | | |
26 | | #include "common/compiler_util.h" |
27 | | |
28 | | namespace doris { |
29 | | |
30 | | template <typename T> |
31 | | struct BitSetContainerTraits { |
32 | | static constexpr size_t RANGE = 0; |
33 | | }; |
34 | | |
35 | | template <> |
36 | | struct BitSetContainerTraits<int8_t> { |
37 | | static constexpr size_t RANGE = 256; |
38 | | }; |
39 | | |
40 | | template <> |
41 | | struct BitSetContainerTraits<int16_t> { |
42 | | static constexpr size_t RANGE = 65536; |
43 | | }; |
44 | | |
45 | | template <typename T> |
46 | | class BitSetContainer { |
47 | | public: |
48 | | using Self = BitSetContainer; |
49 | | using ElementType = T; |
50 | | |
51 | | static_assert(std::is_same_v<T, int8_t> || std::is_same_v<T, int16_t>, |
52 | | "BitSetContainer only supports int8_t or int16_t"); |
53 | | |
54 | | static constexpr size_t RANGE = BitSetContainerTraits<T>::RANGE; |
55 | | |
56 | | class Iterator { |
57 | | public: |
58 | | explicit Iterator(const std::array<bool, RANGE>* data, size_t index) |
59 | 12 | : _data(data), _index(index) { |
60 | 12 | _find_next(); |
61 | 12 | } _ZN5doris15BitSetContainerIaE8IteratorC2EPKSt5arrayIbLm256EEm Line | Count | Source | 59 | 6 | : _data(data), _index(index) { | 60 | 6 | _find_next(); | 61 | 6 | } |
_ZN5doris15BitSetContainerIsE8IteratorC2EPKSt5arrayIbLm65536EEm Line | Count | Source | 59 | 6 | : _data(data), _index(index) { | 60 | 6 | _find_next(); | 61 | 6 | } |
|
62 | | |
63 | 22 | Iterator& operator++() { |
64 | 22 | ++_index; |
65 | 22 | _find_next(); |
66 | 22 | return *this; |
67 | 22 | } _ZN5doris15BitSetContainerIaE8IteratorppEv Line | Count | Source | 63 | 11 | Iterator& operator++() { | 64 | 11 | ++_index; | 65 | 11 | _find_next(); | 66 | 11 | return *this; | 67 | 11 | } |
_ZN5doris15BitSetContainerIsE8IteratorppEv Line | Count | Source | 63 | 11 | Iterator& operator++() { | 64 | 11 | ++_index; | 65 | 11 | _find_next(); | 66 | 11 | return *this; | 67 | 11 | } |
|
68 | | |
69 | | Iterator operator++(int) { |
70 | | Iterator ret_val = *this; |
71 | | ++(*this); |
72 | | return ret_val; |
73 | | } |
74 | | |
75 | 28 | bool operator==(Iterator other) const { return _index == other._index; }_ZNK5doris15BitSetContainerIaE8IteratoreqES2_ Line | Count | Source | 75 | 14 | bool operator==(Iterator other) const { return _index == other._index; } |
_ZNK5doris15BitSetContainerIsE8IteratoreqES2_ Line | Count | Source | 75 | 14 | bool operator==(Iterator other) const { return _index == other._index; } |
|
76 | 0 | bool operator!=(Iterator other) const { return !(*this == other); }Unexecuted instantiation: _ZNK5doris15BitSetContainerIaE8IteratorneES2_ Unexecuted instantiation: _ZNK5doris15BitSetContainerIsE8IteratorneES2_ |
77 | | |
78 | 0 | T operator*() const { return static_cast<T>(_index); }Unexecuted instantiation: _ZNK5doris15BitSetContainerIaE8IteratordeEv Unexecuted instantiation: _ZNK5doris15BitSetContainerIsE8IteratordeEv |
79 | | |
80 | 10 | T* operator->() const { |
81 | 10 | _cached_value = static_cast<T>(_index); |
82 | 10 | return &_cached_value; |
83 | 10 | } _ZNK5doris15BitSetContainerIaE8IteratorptEv Line | Count | Source | 80 | 5 | T* operator->() const { | 81 | 5 | _cached_value = static_cast<T>(_index); | 82 | 5 | return &_cached_value; | 83 | 5 | } |
_ZNK5doris15BitSetContainerIsE8IteratorptEv Line | Count | Source | 80 | 5 | T* operator->() const { | 81 | 5 | _cached_value = static_cast<T>(_index); | 82 | 5 | return &_cached_value; | 83 | 5 | } |
|
84 | | |
85 | | using iterator_category = std::forward_iterator_tag; |
86 | | using difference_type = std::ptrdiff_t; |
87 | | using value_type = T; |
88 | | using pointer = const T*; |
89 | | using reference = const T&; |
90 | | |
91 | | private: |
92 | 34 | void _find_next() { |
93 | 197k | while (_index < RANGE && !(*_data)[_index]) { |
94 | 197k | ++_index; |
95 | 197k | } |
96 | 34 | } _ZN5doris15BitSetContainerIaE8Iterator10_find_nextEv Line | Count | Source | 92 | 17 | void _find_next() { | 93 | 774 | while (_index < RANGE && !(*_data)[_index]) { | 94 | 757 | ++_index; | 95 | 757 | } | 96 | 17 | } |
_ZN5doris15BitSetContainerIsE8Iterator10_find_nextEv Line | Count | Source | 92 | 17 | void _find_next() { | 93 | 196k | while (_index < RANGE && !(*_data)[_index]) { | 94 | 196k | ++_index; | 95 | 196k | } | 96 | 17 | } |
|
97 | | |
98 | | const std::array<bool, RANGE>* _data; |
99 | | size_t _index; |
100 | | mutable T _cached_value = T(); |
101 | | }; |
102 | | |
103 | 12 | BitSetContainer() { _data.fill(false); }_ZN5doris15BitSetContainerIaEC2Ev Line | Count | Source | 103 | 8 | BitSetContainer() { _data.fill(false); } |
_ZN5doris15BitSetContainerIsEC2Ev Line | Count | Source | 103 | 4 | BitSetContainer() { _data.fill(false); } |
|
104 | | |
105 | | ~BitSetContainer() = default; |
106 | | |
107 | 32 | ALWAYS_INLINE void insert(const T& value) { |
108 | 32 | auto idx = _to_index(value); |
109 | 32 | if (!_data[idx]) { |
110 | 30 | _data[idx] = true; |
111 | 30 | _size++; |
112 | 30 | } |
113 | 32 | } _ZN5doris15BitSetContainerIaE6insertERKa Line | Count | Source | 107 | 18 | ALWAYS_INLINE void insert(const T& value) { | 108 | 18 | auto idx = _to_index(value); | 109 | 18 | if (!_data[idx]) { | 110 | 17 | _data[idx] = true; | 111 | 17 | _size++; | 112 | 17 | } | 113 | 18 | } |
_ZN5doris15BitSetContainerIsE6insertERKs Line | Count | Source | 107 | 14 | ALWAYS_INLINE void insert(const T& value) { | 108 | 14 | auto idx = _to_index(value); | 109 | 14 | if (!_data[idx]) { | 110 | 13 | _data[idx] = true; | 111 | 13 | _size++; | 112 | 13 | } | 113 | 14 | } |
|
114 | | |
115 | 20.8k | ALWAYS_INLINE bool find(const T& value) const { return _data[_to_index(value)]; }_ZNK5doris15BitSetContainerIaE4findERKa Line | Count | Source | 115 | 20.8k | ALWAYS_INLINE bool find(const T& value) const { return _data[_to_index(value)]; } |
_ZNK5doris15BitSetContainerIsE4findERKs Line | Count | Source | 115 | 15 | ALWAYS_INLINE bool find(const T& value) const { return _data[_to_index(value)]; } |
|
116 | | |
117 | 0 | void clear() { |
118 | 0 | _data.fill(false); |
119 | 0 | _size = 0; |
120 | 0 | } Unexecuted instantiation: _ZN5doris15BitSetContainerIaE5clearEv Unexecuted instantiation: _ZN5doris15BitSetContainerIsE5clearEv |
121 | | |
122 | 8 | size_t size() const { return _size; }_ZNK5doris15BitSetContainerIaE4sizeEv Line | Count | Source | 122 | 4 | size_t size() const { return _size; } |
_ZNK5doris15BitSetContainerIsE4sizeEv Line | Count | Source | 122 | 4 | size_t size() const { return _size; } |
|
123 | | |
124 | 6 | Iterator begin() const { return Iterator(&_data, 0); }_ZNK5doris15BitSetContainerIaE5beginEv Line | Count | Source | 124 | 3 | Iterator begin() const { return Iterator(&_data, 0); } |
_ZNK5doris15BitSetContainerIsE5beginEv Line | Count | Source | 124 | 3 | Iterator begin() const { return Iterator(&_data, 0); } |
|
125 | 6 | Iterator end() const { return Iterator(&_data, RANGE); }_ZNK5doris15BitSetContainerIaE3endEv Line | Count | Source | 125 | 3 | Iterator end() const { return Iterator(&_data, RANGE); } |
_ZNK5doris15BitSetContainerIsE3endEv Line | Count | Source | 125 | 3 | Iterator end() const { return Iterator(&_data, RANGE); } |
|
126 | | |
127 | | template <typename ColumnData> |
128 | | void find_batch(const ColumnData& data, size_t rows, std::vector<bool>& results) const { |
129 | | results.resize(rows); |
130 | | for (size_t i = 0; i < rows; ++i) { |
131 | | results[i] = find(data[i]); |
132 | | } |
133 | | } |
134 | | |
135 | | template <typename ColumnData> |
136 | | void find_batch(const ColumnData& data, size_t rows, std::vector<uint8_t>& results) const { |
137 | | results.resize(rows); |
138 | | for (size_t i = 0; i < rows; ++i) { |
139 | | results[i] = find(data[i]) ? 1 : 0; |
140 | | } |
141 | | } |
142 | | |
143 | | private: |
144 | 20.9k | ALWAYS_INLINE constexpr size_t _to_index(T value) const { |
145 | 20.9k | if constexpr (std::is_same_v<T, int8_t>) { |
146 | 20.8k | return static_cast<uint8_t>(value); |
147 | 20.8k | } else { |
148 | 29 | return static_cast<uint16_t>(value); |
149 | 29 | } |
150 | 20.9k | } _ZNK5doris15BitSetContainerIaE9_to_indexEa Line | Count | Source | 144 | 20.8k | ALWAYS_INLINE constexpr size_t _to_index(T value) const { | 145 | 20.8k | if constexpr (std::is_same_v<T, int8_t>) { | 146 | 20.8k | return static_cast<uint8_t>(value); | 147 | | } else { | 148 | | return static_cast<uint16_t>(value); | 149 | | } | 150 | 20.8k | } |
_ZNK5doris15BitSetContainerIsE9_to_indexEs Line | Count | Source | 144 | 29 | ALWAYS_INLINE constexpr size_t _to_index(T value) const { | 145 | | if constexpr (std::is_same_v<T, int8_t>) { | 146 | | return static_cast<uint8_t>(value); | 147 | 29 | } else { | 148 | 29 | return static_cast<uint16_t>(value); | 149 | 29 | } | 150 | 29 | } |
|
151 | | |
152 | | std::array<bool, RANGE> _data; |
153 | | size_t _size = 0; |
154 | | }; |
155 | | |
156 | | } // namespace doris |