forked from heavyai/heavydb
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathArrayOps.cpp
More file actions
331 lines (289 loc) · 17.2 KB
/
ArrayOps.cpp
File metadata and controls
331 lines (289 loc) · 17.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
/*
* Copyright 2017 MapD Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file ArrayOps.cpp
* @author Alex Suhan <alex@mapd.com>
* @brief Functions to support array operations used by the executor.
*
* Copyright (c) 2014 MapD Technologies, Inc. All rights reserved.
**/
#include <stdint.h>
#include "TypePunning.h"
#include "../Shared/funcannotations.h"
#include "../Utils/ChunkIter.h"
#ifdef EXECUTE_INCLUDE
extern "C" DEVICE uint32_t array_size(int8_t* chunk_iter_, const uint64_t row_pos, const uint32_t elem_log_sz) {
ChunkIter* chunk_iter = reinterpret_cast<ChunkIter*>(chunk_iter_);
ArrayDatum ad;
bool is_end;
ChunkIter_get_nth(chunk_iter, row_pos, &ad, &is_end);
return ad.is_null ? 0 : ad.length >> elem_log_sz;
}
extern "C" DEVICE bool array_is_null(int8_t* chunk_iter_, const uint64_t row_pos) {
ChunkIter* chunk_iter = reinterpret_cast<ChunkIter*>(chunk_iter_);
ArrayDatum ad;
bool is_end;
ChunkIter_get_nth(chunk_iter, row_pos, &ad, &is_end);
return ad.is_null;
}
#define ARRAY_AT(type) \
extern "C" DEVICE type array_at_##type(int8_t* chunk_iter_, const uint64_t row_pos, const uint32_t elem_idx) { \
ChunkIter* chunk_iter = reinterpret_cast<ChunkIter*>(chunk_iter_); \
ArrayDatum ad; \
bool is_end; \
ChunkIter_get_nth(chunk_iter, row_pos, &ad, &is_end); \
return reinterpret_cast<type*>(ad.pointer)[elem_idx]; \
}
ARRAY_AT(int8_t)
ARRAY_AT(int16_t)
ARRAY_AT(int32_t)
ARRAY_AT(int64_t)
ARRAY_AT(float)
ARRAY_AT(double)
#undef ARRAY_AT
#define ARRAY_ANY(type, needle_type, oper_name, oper) \
extern "C" DEVICE bool array_any_##oper_name##_##type##_##needle_type( \
int8_t* chunk_iter_, const uint64_t row_pos, const needle_type needle, const type null_val) { \
ChunkIter* chunk_iter = reinterpret_cast<ChunkIter*>(chunk_iter_); \
ArrayDatum ad; \
bool is_end; \
ChunkIter_get_nth(chunk_iter, row_pos, &ad, &is_end); \
const size_t elem_count = ad.length / sizeof(type); \
for (size_t i = 0; i < elem_count; ++i) { \
const needle_type val = reinterpret_cast<type*>(ad.pointer)[i]; \
if (val != null_val && val oper needle) { \
return true; \
} \
} \
return false; \
}
#define ARRAY_ALL(type, needle_type, oper_name, oper) \
extern "C" DEVICE bool array_all_##oper_name##_##type##_##needle_type( \
int8_t* chunk_iter_, const uint64_t row_pos, const needle_type needle, const type null_val) { \
ChunkIter* chunk_iter = reinterpret_cast<ChunkIter*>(chunk_iter_); \
ArrayDatum ad; \
bool is_end; \
ChunkIter_get_nth(chunk_iter, row_pos, &ad, &is_end); \
const size_t elem_count = ad.length / sizeof(type); \
for (size_t i = 0; i < elem_count; ++i) { \
const needle_type val = reinterpret_cast<type*>(ad.pointer)[i]; \
if (!(val != null_val && val oper needle)) { \
return false; \
} \
} \
return true; \
}
#define ARRAY_ALL_ANY_ALL_TYPES(oper_name, oper, needle_type) \
ARRAY_ANY(int8_t, needle_type, oper_name, oper) \
ARRAY_ALL(int8_t, needle_type, oper_name, oper) \
ARRAY_ANY(int16_t, needle_type, oper_name, oper) \
ARRAY_ALL(int16_t, needle_type, oper_name, oper) \
ARRAY_ANY(int32_t, needle_type, oper_name, oper) \
ARRAY_ALL(int32_t, needle_type, oper_name, oper) \
ARRAY_ANY(int64_t, needle_type, oper_name, oper) \
ARRAY_ALL(int64_t, needle_type, oper_name, oper) \
ARRAY_ANY(float, needle_type, oper_name, oper) \
ARRAY_ALL(float, needle_type, oper_name, oper) \
ARRAY_ANY(double, needle_type, oper_name, oper) \
ARRAY_ALL(double, needle_type, oper_name, oper)
ARRAY_ALL_ANY_ALL_TYPES(eq, ==, int8_t)
ARRAY_ALL_ANY_ALL_TYPES(ne, !=, int8_t)
ARRAY_ALL_ANY_ALL_TYPES(lt, <, int8_t)
ARRAY_ALL_ANY_ALL_TYPES(le, <=, int8_t)
ARRAY_ALL_ANY_ALL_TYPES(gt, >, int8_t)
ARRAY_ALL_ANY_ALL_TYPES(ge, >=, int8_t)
ARRAY_ALL_ANY_ALL_TYPES(eq, ==, int16_t)
ARRAY_ALL_ANY_ALL_TYPES(ne, !=, int16_t)
ARRAY_ALL_ANY_ALL_TYPES(lt, <, int16_t)
ARRAY_ALL_ANY_ALL_TYPES(le, <=, int16_t)
ARRAY_ALL_ANY_ALL_TYPES(gt, >, int16_t)
ARRAY_ALL_ANY_ALL_TYPES(ge, >=, int16_t)
ARRAY_ALL_ANY_ALL_TYPES(eq, ==, int32_t)
ARRAY_ALL_ANY_ALL_TYPES(ne, !=, int32_t)
ARRAY_ALL_ANY_ALL_TYPES(lt, <, int32_t)
ARRAY_ALL_ANY_ALL_TYPES(le, <=, int32_t)
ARRAY_ALL_ANY_ALL_TYPES(gt, >, int32_t)
ARRAY_ALL_ANY_ALL_TYPES(ge, >=, int32_t)
ARRAY_ALL_ANY_ALL_TYPES(eq, ==, int64_t)
ARRAY_ALL_ANY_ALL_TYPES(ne, !=, int64_t)
ARRAY_ALL_ANY_ALL_TYPES(lt, <, int64_t)
ARRAY_ALL_ANY_ALL_TYPES(le, <=, int64_t)
ARRAY_ALL_ANY_ALL_TYPES(gt, >, int64_t)
ARRAY_ALL_ANY_ALL_TYPES(ge, >=, int64_t)
ARRAY_ALL_ANY_ALL_TYPES(eq, ==, float)
ARRAY_ALL_ANY_ALL_TYPES(ne, !=, float)
ARRAY_ALL_ANY_ALL_TYPES(lt, <, float)
ARRAY_ALL_ANY_ALL_TYPES(le, <=, float)
ARRAY_ALL_ANY_ALL_TYPES(gt, >, float)
ARRAY_ALL_ANY_ALL_TYPES(ge, >=, float)
ARRAY_ALL_ANY_ALL_TYPES(eq, ==, double)
ARRAY_ALL_ANY_ALL_TYPES(ne, !=, double)
ARRAY_ALL_ANY_ALL_TYPES(lt, <, double)
ARRAY_ALL_ANY_ALL_TYPES(le, <=, double)
ARRAY_ALL_ANY_ALL_TYPES(gt, >, double)
ARRAY_ALL_ANY_ALL_TYPES(ge, >=, double)
#undef ARRAY_ALL_ANY_ALL_TYPES
#undef ARRAY_ALL
#undef ARRAY_ANY
#define ARRAY_AT_CHECKED(type) \
extern "C" DEVICE type array_at_##type##_checked( \
int8_t* chunk_iter_, const uint64_t row_pos, const int64_t elem_idx, const type null_val) { \
if (elem_idx <= 0) { \
return null_val; \
} \
ChunkIter* chunk_iter = reinterpret_cast<ChunkIter*>(chunk_iter_); \
ArrayDatum ad; \
bool is_end; \
ChunkIter_get_nth(chunk_iter, row_pos, &ad, &is_end); \
if (ad.is_null || static_cast<size_t>(elem_idx) > ad.length / sizeof(type)) { \
return null_val; \
} \
return reinterpret_cast<type*>(ad.pointer)[elem_idx - 1]; \
}
ARRAY_AT_CHECKED(int8_t)
ARRAY_AT_CHECKED(int16_t)
ARRAY_AT_CHECKED(int32_t)
ARRAY_AT_CHECKED(int64_t)
ARRAY_AT_CHECKED(float)
ARRAY_AT_CHECKED(double)
#undef ARRAY_AT_CHECKED
extern "C" DEVICE int8_t* array_buff(int8_t* chunk_iter_, const uint64_t row_pos) {
ChunkIter* chunk_iter = reinterpret_cast<ChunkIter*>(chunk_iter_);
ArrayDatum ad;
bool is_end;
ChunkIter_get_nth(chunk_iter, row_pos, &ad, &is_end);
return ad.pointer;
}
#ifndef __CUDACC__
#include <set>
extern "C" ALWAYS_INLINE int64_t elem_bitcast_int8_t(const int8_t val) {
return val;
}
extern "C" ALWAYS_INLINE int64_t elem_bitcast_int16_t(const int16_t val) {
return val;
}
extern "C" ALWAYS_INLINE int64_t elem_bitcast_int32_t(const int32_t val) {
return val;
}
extern "C" ALWAYS_INLINE int64_t elem_bitcast_int64_t(const int64_t val) {
return val;
}
extern "C" ALWAYS_INLINE int64_t elem_bitcast_float(const float val) {
const double dval{val};
return *reinterpret_cast<const int64_t*>(may_alias_ptr(&dval));
}
extern "C" ALWAYS_INLINE int64_t elem_bitcast_double(const double val) {
return *reinterpret_cast<const int64_t*>(may_alias_ptr(&val));
}
#define COUNT_DISTINCT_ARRAY(type) \
extern "C" void agg_count_distinct_array_##type( \
int64_t* agg, int8_t* chunk_iter_, const uint64_t row_pos, const type null_val) { \
ChunkIter* chunk_iter = reinterpret_cast<ChunkIter*>(chunk_iter_); \
ArrayDatum ad; \
bool is_end; \
ChunkIter_get_nth(chunk_iter, row_pos, &ad, &is_end); \
const size_t elem_count{ad.length / sizeof(type)}; \
for (size_t i = 0; i < elem_count; ++i) { \
const auto val = reinterpret_cast<type*>(ad.pointer)[i]; \
if (val != null_val) { \
reinterpret_cast<std::set<int64_t>*>(*agg)->insert(elem_bitcast_##type(val)); \
} \
} \
}
COUNT_DISTINCT_ARRAY(int8_t)
COUNT_DISTINCT_ARRAY(int16_t)
COUNT_DISTINCT_ARRAY(int32_t)
COUNT_DISTINCT_ARRAY(int64_t)
COUNT_DISTINCT_ARRAY(float)
COUNT_DISTINCT_ARRAY(double)
#undef COUNT_DISTINCT_ARRAY
#include <string>
extern "C" uint64_t string_decompress(const int32_t string_id, const int64_t string_dict_handle);
#define ARRAY_STR_ANY(type, oper_name, oper) \
extern "C" bool array_any_##oper_name##_str_##type(int8_t* chunk_iter_, \
const uint64_t row_pos, \
const char* needle_ptr, \
const uint32_t needle_len, \
const int64_t string_dict_handle, \
const type null_val) { \
ChunkIter* chunk_iter = reinterpret_cast<ChunkIter*>(chunk_iter_); \
ArrayDatum ad; \
bool is_end; \
ChunkIter_get_nth(chunk_iter, row_pos, &ad, &is_end); \
const size_t elem_count = ad.length / sizeof(type); \
std::string needle_str(needle_ptr, needle_len); \
for (size_t i = 0; i < elem_count; ++i) { \
const type val = reinterpret_cast<type*>(ad.pointer)[i]; \
if (val != null_val) { \
uint64_t str_and_len = string_decompress(val, string_dict_handle); \
const char* str = reinterpret_cast<const char*>(str_and_len & 0xffffffffffff); \
const uint16_t len = str_and_len >> 48; \
std::string val_str(str, len); \
if (val_str oper needle_str) { \
return true; \
} \
} \
} \
return false; \
}
#define ARRAY_STR_ALL(type, oper_name, oper) \
extern "C" bool array_all_##oper_name##_str_##type(int8_t* chunk_iter_, \
const uint64_t row_pos, \
const char* needle_ptr, \
const uint32_t needle_len, \
const int64_t string_dict_handle, \
const type null_val) { \
ChunkIter* chunk_iter = reinterpret_cast<ChunkIter*>(chunk_iter_); \
ArrayDatum ad; \
bool is_end; \
ChunkIter_get_nth(chunk_iter, row_pos, &ad, &is_end); \
const size_t elem_count = ad.length / sizeof(type); \
std::string needle_str(needle_ptr, needle_len); \
for (size_t i = 0; i < elem_count; ++i) { \
const type val = reinterpret_cast<type*>(ad.pointer)[i]; \
if (val == null_val) { \
return false; \
} \
uint64_t str_and_len = string_decompress(val, string_dict_handle); \
const char* str = reinterpret_cast<const char*>(str_and_len & 0xffffffffffff); \
const uint16_t len = str_and_len >> 48; \
std::string val_str(str, len); \
if (!(val_str oper needle_str)) { \
return false; \
} \
} \
return true; \
}
#define ARRAY_STR_ALL_ANY_ALL_TYPES(oper_name, oper) \
ARRAY_STR_ANY(int8_t, oper_name, oper) \
ARRAY_STR_ALL(int8_t, oper_name, oper) \
ARRAY_STR_ANY(int16_t, oper_name, oper) \
ARRAY_STR_ALL(int16_t, oper_name, oper) \
ARRAY_STR_ANY(int32_t, oper_name, oper) \
ARRAY_STR_ALL(int32_t, oper_name, oper) \
ARRAY_STR_ANY(int64_t, oper_name, oper) \
ARRAY_STR_ALL(int64_t, oper_name, oper)
ARRAY_STR_ALL_ANY_ALL_TYPES(eq, ==)
ARRAY_STR_ALL_ANY_ALL_TYPES(ne, !=)
ARRAY_STR_ALL_ANY_ALL_TYPES(lt, <)
ARRAY_STR_ALL_ANY_ALL_TYPES(le, <=)
ARRAY_STR_ALL_ANY_ALL_TYPES(gt, >)
ARRAY_STR_ALL_ANY_ALL_TYPES(ge, >=)
#undef ARRAY_ALL_ANY_ALL_TYPES
#undef ARRAY_STR_ALL
#undef ARRAY_STR_ANY
#endif
#endif // EXECUTE_INCLUDE