MiniOB 1
MiniOB is one mini database, helping developers to learn how database works.
载入中...
搜索中...
未找到
arithmetic_operator.hpp
1/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
2miniob is licensed under Mulan PSL v2.
3You can use this software according to the terms and conditions of the Mulan PSL v2.
4You may obtain a copy of Mulan PSL v2 at:
5 http://license.coscl.org.cn/MulanPSL2
6THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
7EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
8MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
9See the Mulan PSL v2 for more details. */
10
11#pragma once
12
13#if defined(USE_SIMD)
14#include "common/math/simd_util.h"
15#endif
16
17#include "storage/common/column.h"
18
19struct Equal
20{
21 template <class T>
22 static inline bool operation(const T &left, const T &right)
23 {
24 return left == right;
25 }
26#if defined(USE_SIMD)
27 static inline __m256 operation(const __m256 &left, const __m256 &right)
28 {
29 return _mm256_cmp_ps(left, right, _CMP_EQ_OS);
30 }
31
32 static inline __m256i operation(const __m256i &left, const __m256i &right) { return _mm256_cmpeq_epi32(left, right); }
33#endif
34};
36{
37 template <class T>
38 static inline bool operation(const T &left, const T &right)
39 {
40 return left != right;
41 }
42#if defined(USE_SIMD)
43 static inline __m256 operation(const __m256 &left, const __m256 &right)
44 {
45 return _mm256_cmp_ps(left, right, _CMP_NEQ_OS);
46 }
47
48 static inline __m256i operation(const __m256i &left, const __m256i &right)
49 {
50 return _mm256_xor_si256(_mm256_set1_epi32(-1), _mm256_cmpeq_epi32(left, right));
51 }
52#endif
53};
54
56{
57 template <class T>
58 static inline bool operation(const T &left, const T &right)
59 {
60 return left > right;
61 }
62#if defined(USE_SIMD)
63 static inline __m256 operation(const __m256 &left, const __m256 &right)
64 {
65 return _mm256_cmp_ps(left, right, _CMP_GT_OS);
66 }
67
68 static inline __m256i operation(const __m256i &left, const __m256i &right) { return _mm256_cmpgt_epi32(left, right); }
69#endif
70};
71
73{
74 template <class T>
75 static inline bool operation(const T &left, const T &right)
76 {
77 return left >= right;
78 }
79
80#if defined(USE_SIMD)
81 static inline __m256 operation(const __m256 &left, const __m256 &right)
82 {
83 return _mm256_cmp_ps(left, right, _CMP_GE_OS);
84 }
85
86 static inline __m256i operation(const __m256i &left, const __m256i &right)
87 {
88 return _mm256_cmpgt_epi32(left, right) | _mm256_cmpeq_epi32(left, right);
89 }
90#endif
91};
92
94{
95 template <class T>
96 static inline bool operation(const T &left, const T &right)
97 {
98 return left < right;
99 }
100#if defined(USE_SIMD)
101 static inline __m256 operation(const __m256 &left, const __m256 &right)
102 {
103 return _mm256_cmp_ps(left, right, _CMP_LT_OS);
104 }
105
106 static inline __m256i operation(const __m256i &left, const __m256i &right) { return _mm256_cmpgt_epi32(right, left); }
107#endif
108};
109
111{
112 template <class T>
113 static inline bool operation(const T &left, const T &right)
114 {
115 return left <= right;
116 }
117#if defined(USE_SIMD)
118 static inline __m256 operation(const __m256 &left, const __m256 &right)
119 {
120 return _mm256_cmp_ps(left, right, _CMP_LE_OS);
121 }
122
123 static inline __m256i operation(const __m256i &left, const __m256i &right)
124 {
125 return _mm256_or_si256(_mm256_cmpgt_epi32(right, left), _mm256_cmpeq_epi32(left, right));
126 }
127#endif
128};
129
131{
132 template <class T>
133 static inline T operation(T left, T right)
134 {
135 return left + right;
136 }
137
138#if defined(USE_SIMD)
139 static inline __m256 operation(__m256 left, __m256 right) { return _mm256_add_ps(left, right); }
140
141 static inline __m256i operation(__m256i left, __m256i right) { return _mm256_add_epi32(left, right); }
142#endif
143};
144
146{
147 template <class T>
148 static inline T operation(T left, T right)
149 {
150 return left - right;
151 }
152 // your code here
153#if defined(USE_SIMD)
154 static inline __m256 operation(__m256 left, __m256 right) { exit(-1); }
155
156 static inline __m256i operation(__m256i left, __m256i right) { exit(-1); }
157#endif
158};
159
161{
162 template <class T>
163 static inline T operation(T left, T right)
164 {
165 return left * right;
166 }
167// your code here
168#if defined(USE_SIMD)
169 static inline __m256 operation(__m256 left, __m256 right) { exit(-1); }
170
171 static inline __m256i operation(__m256i left, __m256i right) { exit(-1); }
172#endif
173};
174
176{
177 template <class T>
178 static inline T operation(T left, T right)
179 {
180 // TODO: `right = 0` is invalid
181 return left / right;
182 }
183
184#if defined(USE_SIMD)
185 static inline __m256 operation(__m256 left, __m256 right) { return _mm256_div_ps(left, right); }
186 static inline __m256i operation(__m256i left, __m256i right)
187 {
188
189 __m256 left_float = _mm256_cvtepi32_ps(left);
190 __m256 right_float = _mm256_cvtepi32_ps(right);
191 __m256 result_float = _mm256_div_ps(left_float, right_float);
192 return _mm256_cvttps_epi32(result_float);
193 ;
194 }
195#endif
196};
197
199{
200 template <class T>
201 static inline T operation(T input)
202 {
203 return -input;
204 }
205};
206
207template <typename T, bool LEFT_CONSTANT, bool RIGHT_CONSTANT, class OP>
208void compare_operation(T *left, T *right, int n, vector<uint8_t> &result)
209{
210#if defined(USE_SIMD)
211 int i = 0;
212 if constexpr (is_same<T, float>::value) {
213 for (; i <= n - SIMD_WIDTH; i += SIMD_WIDTH) {
214 __m256 left_value, right_value;
215
216 if constexpr (LEFT_CONSTANT) {
217 left_value = _mm256_set1_ps(left[0]);
218 } else {
219 left_value = _mm256_loadu_ps(&left[i]);
220 }
221
222 if constexpr (RIGHT_CONSTANT) {
223 right_value = _mm256_set1_ps(right[0]);
224 } else {
225 right_value = _mm256_loadu_ps(&right[i]);
226 }
227
228 __m256 result_values = OP::operation(left_value, right_value);
229 __m256i mask = _mm256_castps_si256(result_values);
230
231 for (int j = 0; j < SIMD_WIDTH; j++) {
232 result[i + j] &= mm256_extract_epi32_var_indx(mask, j) ? 1 : 0;
233 }
234 }
235 } else if constexpr (is_same<T, int>::value) {
236 for (; i <= n - SIMD_WIDTH; i += SIMD_WIDTH) {
237 __m256i left_value, right_value;
238
239 if (LEFT_CONSTANT) {
240 left_value = _mm256_set1_epi32(left[0]);
241 } else {
242 left_value = _mm256_loadu_si256((__m256i *)&left[i]);
243 }
244
245 if (RIGHT_CONSTANT) {
246 right_value = _mm256_set1_epi32(right[0]);
247 } else {
248 right_value = _mm256_loadu_si256((__m256i *)&right[i]);
249 }
250
251 __m256i result_values = OP::operation(left_value, right_value);
252
253 for (int j = 0; j < SIMD_WIDTH; j++) {
254 result[i + j] &= mm256_extract_epi32_var_indx(result_values, j) ? 1 : 0;
255 }
256 }
257 }
258
259 for (; i < n; i++) {
260 auto &left_value = left[LEFT_CONSTANT ? 0 : i];
261 auto &right_value = right[RIGHT_CONSTANT ? 0 : i];
262 result[i] &= OP::operation(left_value, right_value) ? 1 : 0;
263 }
264#else
265 for (int i = 0; i < n; i++) {
266 auto &left_value = left[LEFT_CONSTANT ? 0 : i];
267 auto &right_value = right[RIGHT_CONSTANT ? 0 : i];
268 result[i] &= OP::operation(left_value, right_value) ? 1 : 0;
269 }
270#endif
271}
272
273template <bool LEFT_CONSTANT, bool RIGHT_CONSTANT, typename T, class OP>
274void binary_operator(T *left_data, T *right_data, T *result_data, int size)
275{
276#if defined(USE_SIMD)
277 int i = 0;
278
279 if constexpr (is_same<T, float>::value) {
280 for (; i <= size - SIMD_WIDTH; i += SIMD_WIDTH) {
281 __m256 left_value, right_value;
282
283 if (LEFT_CONSTANT) {
284 left_value = _mm256_set1_ps(left_data[0]);
285 } else {
286 left_value = _mm256_loadu_ps(&left_data[i]);
287 }
288
289 if (RIGHT_CONSTANT) {
290 right_value = _mm256_set1_ps(right_data[0]);
291 } else {
292 right_value = _mm256_loadu_ps(&right_data[i]);
293 }
294
295 __m256 result_value = OP::operation(left_value, right_value);
296 _mm256_storeu_ps(&result_data[i], result_value);
297 }
298 } else if constexpr (is_same<T, int>::value) {
299 for (; i <= size - SIMD_WIDTH; i += SIMD_WIDTH) {
300 __m256i left_value, right_value;
301
302 if (LEFT_CONSTANT) {
303 left_value = _mm256_set1_epi32(left_data[0]);
304 } else {
305 left_value = _mm256_loadu_si256((const __m256i *)&left_data[i]);
306 }
307
308 if (RIGHT_CONSTANT) {
309 right_value = _mm256_set1_epi32(right_data[0]);
310 } else {
311 right_value = _mm256_loadu_si256((const __m256i *)&right_data[i]);
312 }
313
314 __m256i result_value = OP::operation(left_value, right_value);
315 _mm256_storeu_si256((__m256i *)&result_data[i], result_value);
316 }
317 }
318
319 // 处理剩余未对齐的数据
320 for (; i < size; i++) {
321 auto &left_value = left_data[LEFT_CONSTANT ? 0 : i];
322 auto &right_value = right_data[RIGHT_CONSTANT ? 0 : i];
323 result_data[i] = OP::template operation<T>(left_value, right_value);
324 }
325#else
326 for (int i = 0; i < size; i++) {
327 auto &left_value = left_data[LEFT_CONSTANT ? 0 : i];
328 auto &right_value = right_data[RIGHT_CONSTANT ? 0 : i];
329 result_data[i] = OP::template operation<T>(left_value, right_value);
330 }
331#endif
332}
333
334template <bool CONSTANT, typename T, class OP>
335void unary_operator(T *input, T *result_data, int size)
336{
337 for (int i = 0; i < size; i++) {
338 auto &value = input[CONSTANT ? 0 : i];
339 result_data[i] = OP::template operation<T>(value);
340 }
341}
342
343// TODO: optimized with simd
344template <typename T, bool LEFT_CONSTANT, bool RIGHT_CONSTANT>
345void compare_result(T *left, T *right, int n, vector<uint8_t> &result, CompOp op)
346{
347 switch (op) {
348 case CompOp::EQUAL_TO: {
349 compare_operation<T, LEFT_CONSTANT, RIGHT_CONSTANT, Equal>(left, right, n, result);
350 break;
351 }
352 case CompOp::NOT_EQUAL: {
353 compare_operation<T, LEFT_CONSTANT, RIGHT_CONSTANT, NotEqual>(left, right, n, result);
354 break;
355 }
356 case CompOp::GREAT_EQUAL: {
357 compare_operation<T, LEFT_CONSTANT, RIGHT_CONSTANT, GreatEqual>(left, right, n, result);
358 break;
359 }
360 case CompOp::GREAT_THAN: {
361 compare_operation<T, LEFT_CONSTANT, RIGHT_CONSTANT, GreatThan>(left, right, n, result);
362 break;
363 }
364 case CompOp::LESS_EQUAL: {
365 compare_operation<T, LEFT_CONSTANT, RIGHT_CONSTANT, LessEqual>(left, right, n, result);
366 break;
367 }
368 case CompOp::LESS_THAN: {
369 compare_operation<T, LEFT_CONSTANT, RIGHT_CONSTANT, LessThan>(left, right, n, result);
370 break;
371 }
372 default: break;
373 }
374}
CompOp
描述比较运算符
Definition: parse_defs.h:46
@ GREAT_EQUAL
">="
Definition: parse_defs.h:51
@ LESS_THAN
"<"
Definition: parse_defs.h:50
@ EQUAL_TO
"="
Definition: parse_defs.h:47
@ LESS_EQUAL
"<="
Definition: parse_defs.h:48
@ GREAT_THAN
">"
Definition: parse_defs.h:52
@ NOT_EQUAL
"<>"
Definition: parse_defs.h:49
Definition: arithmetic_operator.hpp:131
Definition: arithmetic_operator.hpp:176
Definition: arithmetic_operator.hpp:20
Definition: arithmetic_operator.hpp:73
Definition: arithmetic_operator.hpp:56
Definition: arithmetic_operator.hpp:111
Definition: arithmetic_operator.hpp:94
Definition: arithmetic_operator.hpp:161
Definition: arithmetic_operator.hpp:199
Definition: arithmetic_operator.hpp:36
Definition: arithmetic_operator.hpp:146