Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 : #include "gdk.h"
15 : #include "gdk_analytic.h"
16 : #include "gdk_calc_private.h"
17 :
18 : BAT *
19 225 : GDKinitialize_segment_tree(void)
20 : {
21 : /* The tree is allocated using raw bytes, so use a GDK type of size 1 */
22 225 : BAT *st = COLnew(0, TYPE_bte, 0, TRANSIENT);
23 :
24 225 : if (!st)
25 : return NULL;
26 225 : assert(st->tshift == 0);
27 225 : BATsetcount(st, 0);
28 225 : st->tsorted = st->trevsorted = st->tkey = st->tnonil = st->tnil = false;
29 225 : st->tnosorted = st->tnorevsorted = 0;
30 225 : return st;
31 : }
32 :
33 : gdk_return
34 41528 : GDKrebuild_segment_tree(oid ncount, oid data_size, BAT *st, void **segment_tree, oid **levels_offset, oid *nlevels)
35 : {
36 41528 : oid total_size, next_tree_size = ncount, counter = ncount, next_levels = 1; /* there will be at least one level */
37 :
38 41528 : assert(ncount > 0);
39 71738 : do { /* compute the next number of levels */
40 71738 : counter = (oid) ceil((dbl)counter / SEGMENT_TREE_FANOUT);
41 71738 : next_tree_size += counter;
42 71738 : next_levels++;
43 71738 : } while (counter > 1);
44 :
45 41528 : *nlevels = next_levels; /* set the logical size of levels before the physical one */
46 41528 : next_tree_size *= data_size;
47 : /* round up to multiple of sizeof(oid) */
48 41528 : next_tree_size = ((next_tree_size + SIZEOF_OID - 1) / SIZEOF_OID) * SIZEOF_OID;
49 41528 : total_size = next_tree_size + next_levels * sizeof(oid);
50 :
51 41528 : if (total_size > BATcount(st)) {
52 227 : total_size = (((total_size) + 1023) & ~1023); /* align to a multiple of 1024 bytes */
53 227 : if (BATextend(st, total_size) != GDK_SUCCEED)
54 : return GDK_FAIL;
55 227 : BATsetcount(st, total_size);
56 227 : *segment_tree = (void*)Tloc(st, 0);
57 227 : *levels_offset = (oid*)((bte*)Tloc(st, 0) + next_tree_size); /* levels offset will be next to the segment tree */
58 : } else {
59 41301 : *levels_offset = (oid*)(*(bte**)segment_tree + next_tree_size); /* no reallocation, just update location of levels offset */
60 : }
61 : return GDK_SUCCEED;
62 : }
63 :
64 : #define NTILE_CALC(TPE, NEXT_VALUE, LNG_HGE, UPCAST, VALIDATION) \
65 : do { \
66 : UPCAST j = 0, ncnt = (UPCAST) (i - k); \
67 : for (; k < i; k++, j++) { \
68 : TPE val = NEXT_VALUE; \
69 : if (is_##TPE##_nil(val)) { \
70 : has_nils = true; \
71 : rb[k] = TPE##_nil; \
72 : } else { \
73 : UPCAST nval = (UPCAST) (LNG_HGE); \
74 : VALIDATION /* validation must come after null check */ \
75 : if (nval >= ncnt) { \
76 : rb[k] = (TPE)(j + 1); \
77 : } else { \
78 : UPCAST bsize = ncnt / nval; \
79 : UPCAST top = ncnt - nval * bsize; \
80 : UPCAST small = top * (bsize + 1); \
81 : if ((UPCAST) j < small) \
82 : rb[k] = (TPE)(1 + j / (bsize + 1)); \
83 : else \
84 : rb[k] = (TPE)(1 + top + (j - small) / bsize); \
85 : } \
86 : } \
87 : } \
88 : } while (0)
89 :
90 : #define ANALYTICAL_NTILE(IMP, TPE, NEXT_VALUE, LNG_HGE, UPCAST, VALIDATION) \
91 : do { \
92 : TPE *rb = (TPE*)Tloc(r, 0); \
93 : if (p) { \
94 : while (i < cnt) { \
95 : if (np[i]) { \
96 : ntile##IMP##TPE: \
97 : NTILE_CALC(TPE, NEXT_VALUE, LNG_HGE, UPCAST, VALIDATION); \
98 : } \
99 : if (!last) \
100 : i++; \
101 : } \
102 : } \
103 : if (!last) { \
104 : last = true; \
105 : i = cnt; \
106 : goto ntile##IMP##TPE; \
107 : } \
108 : } while (0)
109 :
110 : #define ANALYTICAL_NTILE_SINGLE_IMP(TPE, LNG_HGE, UPCAST) \
111 : do { \
112 : TPE ntl = *(TPE*) ntile; \
113 : if (!is_##TPE##_nil(ntl) && ntl <= 0) goto invalidntile; \
114 : ANALYTICAL_NTILE(SINGLE, TPE, ntl, LNG_HGE, UPCAST, ;); \
115 : } while (0)
116 :
117 : #define ANALYTICAL_NTILE_MULTI_IMP(TPE, LNG_HGE, UPCAST) \
118 : do { \
119 : const TPE *restrict nn = (TPE*)ni.base; \
120 : ANALYTICAL_NTILE(MULTI, TPE, nn[k], LNG_HGE, UPCAST, if (val <= 0) goto invalidntile;); \
121 : } while (0)
122 :
123 : gdk_return
124 61 : GDKanalyticalntile(BAT *r, BAT *b, BAT *p, BAT *n, int tpe, const void *restrict ntile)
125 : {
126 61 : BATiter bi = bat_iterator(b);
127 61 : BATiter pi = bat_iterator(p);
128 61 : BATiter ni = bat_iterator(n);
129 61 : lng i = 0, k = 0, cnt = (lng) BATcount(b);
130 61 : const bit *restrict np = pi.base;
131 61 : bool has_nils = false, last = false;
132 :
133 61 : assert((n && !ntile) || (!n && ntile));
134 :
135 61 : if (ntile) {
136 34 : switch (tpe) {
137 33 : case TYPE_bte:
138 674 : ANALYTICAL_NTILE_SINGLE_IMP(bte, val, BUN);
139 : break;
140 0 : case TYPE_sht:
141 0 : ANALYTICAL_NTILE_SINGLE_IMP(sht, val, BUN);
142 : break;
143 0 : case TYPE_int:
144 0 : ANALYTICAL_NTILE_SINGLE_IMP(int, val, BUN);
145 : break;
146 1 : case TYPE_lng:
147 : #if SIZEOF_OID == SIZEOF_INT
148 : ANALYTICAL_NTILE_SINGLE_IMP(lng, val, lng);
149 : #else
150 162 : ANALYTICAL_NTILE_SINGLE_IMP(lng, val, BUN);
151 : #endif
152 : break;
153 : #ifdef HAVE_HGE
154 0 : case TYPE_hge:
155 : #if SIZEOF_OID == SIZEOF_INT
156 : ANALYTICAL_NTILE_SINGLE_IMP(hge, (val > (hge) GDK_int_max) ? GDK_int_max : (lng) val, lng);
157 : #else
158 0 : ANALYTICAL_NTILE_SINGLE_IMP(hge, (val > (hge) GDK_lng_max) ? GDK_lng_max : (lng) val, BUN);
159 : #endif
160 : #endif
161 : default:
162 0 : goto nosupport;
163 : }
164 : } else {
165 27 : switch (tpe) {
166 1 : case TYPE_bte:
167 12 : ANALYTICAL_NTILE_MULTI_IMP(bte, val, BUN);
168 : break;
169 0 : case TYPE_sht:
170 0 : ANALYTICAL_NTILE_MULTI_IMP(sht, val, BUN);
171 : break;
172 26 : case TYPE_int:
173 420 : ANALYTICAL_NTILE_MULTI_IMP(int, val, BUN);
174 : break;
175 0 : case TYPE_lng:
176 : #if SIZEOF_OID == SIZEOF_INT
177 : ANALYTICAL_NTILE_MULTI_IMP(lng, val, lng);
178 : #else
179 0 : ANALYTICAL_NTILE_MULTI_IMP(lng, val, BUN);
180 : #endif
181 : break;
182 : #ifdef HAVE_HGE
183 0 : case TYPE_hge:
184 : #if SIZEOF_OID == SIZEOF_INT
185 : ANALYTICAL_NTILE_MULTI_IMP(hge, val > (hge) GDK_int_max ? GDK_int_max : (lng) val, lng);
186 : #else
187 0 : ANALYTICAL_NTILE_MULTI_IMP(hge, val > (hge) GDK_lng_max ? GDK_lng_max : (lng) val, BUN);
188 : #endif
189 : break;
190 : #endif
191 0 : default:
192 0 : goto nosupport;
193 : }
194 : }
195 61 : bat_iterator_end(&bi);
196 61 : bat_iterator_end(&pi);
197 61 : bat_iterator_end(&ni);
198 61 : BATsetcount(r, BATcount(b));
199 61 : r->tnonil = !has_nils;
200 61 : r->tnil = has_nils;
201 61 : return GDK_SUCCEED;
202 0 : nosupport:
203 0 : bat_iterator_end(&bi);
204 0 : bat_iterator_end(&pi);
205 0 : bat_iterator_end(&ni);
206 0 : GDKerror("42000!type %s not supported for the ntile type.\n", ATOMname(tpe));
207 0 : return GDK_FAIL;
208 0 : invalidntile:
209 0 : bat_iterator_end(&bi);
210 0 : bat_iterator_end(&pi);
211 0 : bat_iterator_end(&ni);
212 0 : GDKerror("42000!ntile must be greater than zero.\n");
213 0 : return GDK_FAIL;
214 : }
215 :
216 : #define ANALYTICAL_FIRST_FIXED(TPE) \
217 : do { \
218 : const TPE *bp = (TPE*)bi.base; \
219 : TPE *rb = (TPE*)Tloc(r, 0); \
220 : for (; k < cnt; k++) { \
221 : const TPE *bs = bp + start[k], *be = bp + end[k]; \
222 : TPE curval = (be > bs) ? *bs : TPE##_nil; \
223 : rb[k] = curval; \
224 : has_nils |= is_##TPE##_nil(curval); \
225 : } \
226 : } while (0)
227 :
228 : gdk_return
229 36 : GDKanalyticalfirst(BAT *r, BAT *b, BAT *s, BAT *e, int tpe)
230 : {
231 36 : BATiter bi = bat_iterator(b);
232 36 : BATiter si = bat_iterator(s);
233 36 : BATiter ei = bat_iterator(e);
234 36 : bool has_nils = false;
235 36 : oid k = 0, cnt = BATcount(b);
236 36 : const oid *restrict start = si.base, *restrict end = ei.base;
237 36 : const void *nil = ATOMnilptr(tpe);
238 36 : int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe);
239 :
240 72 : switch (ATOMbasetype(tpe)) {
241 1 : case TYPE_bte:
242 11 : ANALYTICAL_FIRST_FIXED(bte);
243 : break;
244 0 : case TYPE_sht:
245 0 : ANALYTICAL_FIRST_FIXED(sht);
246 : break;
247 25 : case TYPE_int:
248 845627 : ANALYTICAL_FIRST_FIXED(int);
249 : break;
250 1 : case TYPE_lng:
251 12 : ANALYTICAL_FIRST_FIXED(lng);
252 : break;
253 : #ifdef HAVE_HGE
254 0 : case TYPE_hge:
255 0 : ANALYTICAL_FIRST_FIXED(hge);
256 : break;
257 : #endif
258 0 : case TYPE_flt:
259 0 : ANALYTICAL_FIRST_FIXED(flt);
260 : break;
261 2 : case TYPE_dbl:
262 14 : ANALYTICAL_FIRST_FIXED(dbl);
263 : break;
264 7 : default:{
265 7 : if (ATOMvarsized(tpe)) {
266 245752 : for (; k < cnt; k++) {
267 245745 : const void *curval = (end[k] > start[k]) ? BUNtvar(bi, start[k]) : nil;
268 245745 : if (tfastins_nocheckVAR(r, k, curval) != GDK_SUCCEED) {
269 0 : bat_iterator_end(&bi);
270 0 : bat_iterator_end(&si);
271 0 : bat_iterator_end(&ei);
272 0 : return GDK_FAIL;
273 : }
274 245745 : has_nils |= atomcmp(curval, nil) == 0;
275 : }
276 : } else {
277 0 : uint16_t width = r->twidth;
278 0 : uint8_t *restrict rcast = (uint8_t *) Tloc(r, 0);
279 0 : for (; k < cnt; k++) {
280 0 : const void *curval = (end[k] > start[k]) ? BUNtloc(bi, start[k]) : nil;
281 0 : memcpy(rcast, curval, width);
282 0 : rcast += width;
283 0 : has_nils |= atomcmp(curval, nil) == 0;
284 : }
285 : }
286 : }
287 : }
288 36 : bat_iterator_end(&bi);
289 36 : bat_iterator_end(&si);
290 36 : bat_iterator_end(&ei);
291 :
292 36 : BATsetcount(r, cnt);
293 36 : r->tnonil = !has_nils;
294 36 : r->tnil = has_nils;
295 36 : return GDK_SUCCEED;
296 : }
297 :
298 : #define ANALYTICAL_LAST_FIXED(TPE) \
299 : do { \
300 : const TPE *bp = (TPE*)bi.base; \
301 : TPE *rb = (TPE*)Tloc(r, 0); \
302 : for (; k < cnt; k++) { \
303 : const TPE *bs = bp + start[k], *be = bp + end[k]; \
304 : TPE curval = (be > bs) ? *(be - 1) : TPE##_nil; \
305 : rb[k] = curval; \
306 : has_nils |= is_##TPE##_nil(curval); \
307 : } \
308 : } while (0)
309 :
310 : gdk_return
311 31 : GDKanalyticallast(BAT *r, BAT *b, BAT *s, BAT *e, int tpe)
312 : {
313 31 : BATiter bi = bat_iterator(b);
314 31 : BATiter si = bat_iterator(s);
315 31 : BATiter ei = bat_iterator(e);
316 31 : bool has_nils = false;
317 31 : oid k = 0, cnt = BATcount(b);
318 31 : const oid *restrict start = si.base, *restrict end = ei.base;
319 31 : const void *nil = ATOMnilptr(tpe);
320 31 : int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe);
321 :
322 62 : switch (ATOMbasetype(tpe)) {
323 1 : case TYPE_bte:
324 11 : ANALYTICAL_LAST_FIXED(bte);
325 : break;
326 0 : case TYPE_sht:
327 0 : ANALYTICAL_LAST_FIXED(sht);
328 : break;
329 22 : case TYPE_int:
330 339 : ANALYTICAL_LAST_FIXED(int);
331 : break;
332 1 : case TYPE_lng:
333 12 : ANALYTICAL_LAST_FIXED(lng);
334 : break;
335 : #ifdef HAVE_HGE
336 0 : case TYPE_hge:
337 0 : ANALYTICAL_LAST_FIXED(hge);
338 : break;
339 : #endif
340 0 : case TYPE_flt:
341 0 : ANALYTICAL_LAST_FIXED(flt);
342 : break;
343 2 : case TYPE_dbl:
344 14 : ANALYTICAL_LAST_FIXED(dbl);
345 : break;
346 5 : default:{
347 5 : if (ATOMvarsized(tpe)) {
348 50 : for (; k < cnt; k++) {
349 45 : const void *curval = (end[k] > start[k]) ? BUNtvar(bi, end[k] - 1) : nil;
350 45 : if (tfastins_nocheckVAR(r, k, curval) != GDK_SUCCEED) {
351 0 : bat_iterator_end(&bi);
352 0 : bat_iterator_end(&si);
353 0 : bat_iterator_end(&ei);
354 0 : return GDK_FAIL;
355 : }
356 45 : has_nils |= atomcmp(curval, nil) == 0;
357 : }
358 : } else {
359 0 : uint16_t width = r->twidth;
360 0 : uint8_t *restrict rcast = (uint8_t *) Tloc(r, 0);
361 0 : for (; k < cnt; k++) {
362 0 : const void *curval = (end[k] > start[k]) ? BUNtloc(bi, end[k] - 1) : nil;
363 0 : memcpy(rcast, curval, width);
364 0 : rcast += width;
365 0 : has_nils |= atomcmp(curval, nil) == 0;
366 : }
367 : }
368 : }
369 : }
370 31 : bat_iterator_end(&bi);
371 31 : bat_iterator_end(&si);
372 31 : bat_iterator_end(&ei);
373 31 : BATsetcount(r, cnt);
374 31 : r->tnonil = !has_nils;
375 31 : r->tnil = has_nils;
376 31 : return GDK_SUCCEED;
377 : }
378 :
379 : #define ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(TPE) \
380 : do { \
381 : const TPE *bp = (TPE*)bi.base; \
382 : TPE *rb = (TPE*)Tloc(r, 0); \
383 : if (is_lng_nil(nth)) { \
384 : has_nils = true; \
385 : for (; k < cnt; k++) \
386 : rb[k] = TPE##_nil; \
387 : } else { \
388 : nth--; \
389 : for (; k < cnt; k++) { \
390 : const TPE *bs = bp + start[k]; \
391 : const TPE *be = bp + end[k]; \
392 : TPE curval = (be > bs && nth < (lng)(end[k] - start[k])) ? *(bs + nth) : TPE##_nil; \
393 : rb[k] = curval; \
394 : has_nils |= is_##TPE##_nil(curval); \
395 : } \
396 : } \
397 : } while (0)
398 :
399 : #define ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE) \
400 : do { \
401 : const TPE *bp = (TPE*)bi.base; \
402 : TPE curval, *rb = (TPE*)Tloc(r, 0); \
403 : for (; k < cnt; k++) { \
404 : lng lnth = tp[k]; \
405 : const TPE *bs = bp + start[k]; \
406 : const TPE *be = bp + end[k]; \
407 : if (!is_lng_nil(lnth) && lnth <= 0) goto invalidnth; \
408 : if (is_lng_nil(lnth) || be <= bs || lnth - 1 > (lng)(end[k] - start[k])) { \
409 : curval = TPE##_nil; \
410 : has_nils = true; \
411 : } else { \
412 : curval = *(bs + lnth - 1); \
413 : has_nils |= is_##TPE##_nil(curval); \
414 : } \
415 : rb[k] = curval; \
416 : } \
417 : } while (0)
418 :
419 : gdk_return
420 40 : GDKanalyticalnthvalue(BAT *r, BAT *b, BAT *s, BAT *e, BAT *t, lng *pnth, int tpe)
421 : {
422 40 : BATiter bi = bat_iterator(b);
423 40 : BATiter si = bat_iterator(s);
424 40 : BATiter ei = bat_iterator(e);
425 40 : BATiter ti = bat_iterator(t);
426 40 : bool has_nils = false;
427 40 : oid k = 0, cnt = bi.count;
428 40 : const oid *restrict start = si.base, *restrict end = ei.base;
429 40 : lng nth = pnth ? *pnth : 0;
430 40 : const lng *restrict tp = ti.base;
431 40 : const void *nil = ATOMnilptr(tpe);
432 40 : int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe);
433 :
434 40 : if (t && t->ttype != TYPE_lng)
435 0 : goto nosupport;
436 :
437 40 : if (t) {
438 10 : switch (ATOMbasetype(tpe)) {
439 3 : case TYPE_bte:
440 33 : ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(bte);
441 : break;
442 0 : case TYPE_sht:
443 0 : ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(sht);
444 : break;
445 2 : case TYPE_int:
446 22 : ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(int);
447 : break;
448 0 : case TYPE_lng:
449 0 : ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(lng);
450 : break;
451 : #ifdef HAVE_HGE
452 0 : case TYPE_hge:
453 0 : ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(hge);
454 : break;
455 : #endif
456 0 : case TYPE_flt:
457 0 : ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(flt);
458 : break;
459 0 : case TYPE_dbl:
460 0 : ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(dbl);
461 : break;
462 0 : default:{
463 0 : const void *curval = nil;
464 0 : if (ATOMvarsized(tpe)) {
465 0 : for (; k < cnt; k++) {
466 0 : lng lnth = tp[k];
467 0 : if (!is_lng_nil(nth) && nth <= 0) goto invalidnth;
468 0 : if (is_lng_nil(lnth) || end[k] <= start[k] || lnth - 1 > (lng)(end[k] - start[k])) {
469 : curval = (void *) nil;
470 : has_nils = true;
471 : } else {
472 0 : curval = BUNtvar(bi, start[k] + (oid)(lnth - 1));
473 0 : has_nils |= atomcmp(curval, nil) == 0;
474 : }
475 0 : if (tfastins_nocheckVAR(r, k, curval) != GDK_SUCCEED) {
476 0 : bat_iterator_end(&bi);
477 0 : bat_iterator_end(&si);
478 0 : bat_iterator_end(&ei);
479 0 : bat_iterator_end(&ti);
480 0 : return GDK_FAIL;
481 : }
482 : }
483 : } else {
484 0 : uint8_t *restrict rcast = (uint8_t *) Tloc(r, 0);
485 0 : uint16_t width = r->twidth;
486 0 : for (; k < cnt; k++) {
487 0 : lng lnth = tp[k];
488 0 : if (!is_lng_nil(nth) && nth <= 0) goto invalidnth;
489 0 : if (is_lng_nil(lnth) || end[k] <= start[k] || lnth - 1 > (lng)(end[k] - start[k])) {
490 : curval = (void *) nil;
491 : has_nils = true;
492 : } else {
493 0 : curval = BUNtloc(bi, start[k] + (oid)(lnth - 1));
494 0 : has_nils |= atomcmp(curval, nil) == 0;
495 : }
496 0 : memcpy(rcast, curval, width);
497 0 : rcast += width;
498 : }
499 : }
500 : }
501 : }
502 : } else {
503 35 : if (!is_lng_nil(nth) && nth <= 0) {
504 0 : goto invalidnth;
505 : }
506 70 : switch (ATOMbasetype(tpe)) {
507 1 : case TYPE_bte:
508 11 : ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(bte);
509 : break;
510 0 : case TYPE_sht:
511 0 : ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(sht);
512 : break;
513 23 : case TYPE_int:
514 243 : ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(int);
515 : break;
516 0 : case TYPE_lng:
517 0 : ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(lng);
518 : break;
519 : #ifdef HAVE_HGE
520 0 : case TYPE_hge:
521 0 : ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(hge);
522 : break;
523 : #endif
524 0 : case TYPE_flt:
525 0 : ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(flt);
526 : break;
527 0 : case TYPE_dbl:
528 0 : ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(dbl);
529 : break;
530 11 : default:{
531 11 : if (ATOMvarsized(tpe)) {
532 11 : if (is_lng_nil(nth)) {
533 0 : has_nils = true;
534 0 : for (; k < cnt; k++)
535 0 : if (tfastins_nocheckVAR(r, k, nil) != GDK_SUCCEED) {
536 0 : bat_iterator_end(&bi);
537 0 : bat_iterator_end(&si);
538 0 : bat_iterator_end(&ei);
539 0 : bat_iterator_end(&ti);
540 0 : return GDK_FAIL;
541 : }
542 : } else {
543 11 : nth--;
544 112 : for (; k < cnt; k++) {
545 101 : const void *curval = (end[k] > start[k] && nth < (lng)(end[k] - start[k])) ? BUNtvar(bi, start[k] + (oid) nth) : nil;
546 101 : if (tfastins_nocheckVAR(r, k, curval) != GDK_SUCCEED) {
547 0 : bat_iterator_end(&bi);
548 0 : bat_iterator_end(&si);
549 0 : bat_iterator_end(&ei);
550 0 : bat_iterator_end(&ti);
551 0 : return GDK_FAIL;
552 : }
553 101 : has_nils |= atomcmp(curval, nil) == 0;
554 : }
555 : }
556 : } else {
557 0 : uint16_t width = r->twidth;
558 0 : uint8_t *restrict rcast = (uint8_t *) Tloc(r, 0);
559 0 : if (is_lng_nil(nth)) {
560 0 : has_nils = true;
561 0 : for (; k < cnt; k++) {
562 0 : memcpy(rcast, nil, width);
563 0 : rcast += width;
564 : }
565 : } else {
566 0 : nth--;
567 0 : for (; k < cnt; k++) {
568 0 : const void *curval = (end[k] > start[k] && nth < (lng)(end[k] - start[k])) ? BUNtloc(bi, start[k] + (oid) nth) : nil;
569 0 : memcpy(rcast, curval, width);
570 0 : rcast += width;
571 0 : has_nils |= atomcmp(curval, nil) == 0;
572 : }
573 : }
574 : }
575 : }
576 : }
577 : }
578 40 : bat_iterator_end(&bi);
579 40 : bat_iterator_end(&si);
580 40 : bat_iterator_end(&ei);
581 40 : bat_iterator_end(&ti);
582 :
583 40 : BATsetcount(r, cnt);
584 40 : r->tnonil = !has_nils;
585 40 : r->tnil = has_nils;
586 40 : return GDK_SUCCEED;
587 0 : nosupport:
588 0 : bat_iterator_end(&bi);
589 0 : bat_iterator_end(&si);
590 0 : bat_iterator_end(&ei);
591 0 : bat_iterator_end(&ti);
592 0 : GDKerror("42000!type %s not supported for the nth_value.\n", ATOMname(t->ttype));
593 0 : return GDK_FAIL;
594 0 : invalidnth:
595 0 : bat_iterator_end(&bi);
596 0 : bat_iterator_end(&si);
597 0 : bat_iterator_end(&ei);
598 0 : bat_iterator_end(&ti);
599 0 : GDKerror("42000!nth_value must be greater than zero.\n");
600 0 : return GDK_FAIL;
601 : }
602 :
603 : #define ANALYTICAL_LAG_CALC(TPE) \
604 : do { \
605 : for (i = 0; i < lag && rb < rp; i++, rb++) \
606 : *rb = def; \
607 : has_nils |= (lag > 0 && is_##TPE##_nil(def)); \
608 : for (; rb < rp; rb++, bp++) { \
609 : next = *bp; \
610 : *rb = next; \
611 : has_nils |= is_##TPE##_nil(next); \
612 : } \
613 : } while (0)
614 :
615 : #define ANALYTICAL_LAG_IMP(TPE) \
616 : do { \
617 : TPE *rp, *rb, *rend, \
618 : def = *((TPE *) default_value), next; \
619 : const TPE *bp, *nbp; \
620 : bp = (TPE*)bi.base; \
621 : rb = rp = (TPE*)Tloc(r, 0); \
622 : rend = rb + cnt; \
623 : if (lag == BUN_NONE) { \
624 : has_nils = true; \
625 : for (; rb < rend; rb++) \
626 : *rb = TPE##_nil; \
627 : } else if (p) { \
628 : pnp = np = (bit*)pi.base; \
629 : end = np + cnt; \
630 : for (; np < end; np++) { \
631 : if (*np) { \
632 : ncnt = (np - pnp); \
633 : rp += ncnt; \
634 : nbp = bp + ncnt; \
635 : ANALYTICAL_LAG_CALC(TPE); \
636 : bp = nbp; \
637 : pnp = np; \
638 : } \
639 : } \
640 : rp += (np - pnp); \
641 : ANALYTICAL_LAG_CALC(TPE); \
642 : } else { \
643 : rp += cnt; \
644 : ANALYTICAL_LAG_CALC(TPE); \
645 : } \
646 : } while (0)
647 :
648 : #define ANALYTICAL_LAG_OTHERS \
649 : do { \
650 : for (i = 0; i < lag && k < j; i++, k++) { \
651 : if (BUNappend(r, default_value, false) != GDK_SUCCEED) { \
652 : bat_iterator_end(&bi); \
653 : bat_iterator_end(&pi); \
654 : return GDK_FAIL; \
655 : } \
656 : } \
657 : has_nils |= (lag > 0 && atomcmp(default_value, nil) == 0); \
658 : for (l = k - lag; k < j; k++, l++) { \
659 : curval = BUNtail(bi, l); \
660 : if (BUNappend(r, curval, false) != GDK_SUCCEED) { \
661 : bat_iterator_end(&bi); \
662 : bat_iterator_end(&pi); \
663 : return GDK_FAIL; \
664 : } \
665 : has_nils |= atomcmp(curval, nil) == 0; \
666 : } \
667 : } while (0)
668 :
669 : gdk_return
670 30 : GDKanalyticallag(BAT *r, BAT *b, BAT *p, BUN lag, const void *restrict default_value, int tpe)
671 : {
672 30 : BATiter bi = bat_iterator(b);
673 30 : BATiter pi = bat_iterator(p);
674 30 : int (*atomcmp) (const void *, const void *);
675 30 : const void *restrict nil;
676 30 : BUN i = 0, j = 0, k = 0, l = 0, ncnt, cnt = BATcount(b);
677 30 : bit *np, *pnp, *end;
678 30 : bool has_nils = false;
679 :
680 30 : assert(default_value);
681 :
682 60 : switch (ATOMbasetype(tpe)) {
683 3 : case TYPE_bte:
684 33 : ANALYTICAL_LAG_IMP(bte);
685 : break;
686 0 : case TYPE_sht:
687 0 : ANALYTICAL_LAG_IMP(sht);
688 : break;
689 21 : case TYPE_int:
690 337 : ANALYTICAL_LAG_IMP(int);
691 : break;
692 1 : case TYPE_lng:
693 23 : ANALYTICAL_LAG_IMP(lng);
694 : break;
695 : #ifdef HAVE_HGE
696 0 : case TYPE_hge:
697 0 : ANALYTICAL_LAG_IMP(hge);
698 : break;
699 : #endif
700 0 : case TYPE_flt:
701 0 : ANALYTICAL_LAG_IMP(flt);
702 : break;
703 0 : case TYPE_dbl:
704 0 : ANALYTICAL_LAG_IMP(dbl);
705 : break;
706 5 : default:{
707 5 : const void *restrict curval;
708 5 : nil = ATOMnilptr(tpe);
709 5 : atomcmp = ATOMcompare(tpe);
710 5 : if (lag == BUN_NONE) {
711 0 : has_nils = true;
712 0 : for (j = 0; j < cnt; j++) {
713 0 : if (BUNappend(r, nil, false) != GDK_SUCCEED) {
714 0 : bat_iterator_end(&bi);
715 0 : bat_iterator_end(&pi);
716 0 : return GDK_FAIL;
717 : }
718 : }
719 5 : } else if (p) {
720 3 : pnp = np = (bit *) pi.base;
721 3 : end = np + cnt;
722 30 : for (; np < end; np++) {
723 27 : if (*np) {
724 9 : j += (np - pnp);
725 31 : ANALYTICAL_LAG_OTHERS;
726 : pnp = np;
727 : }
728 : }
729 3 : j += (np - pnp);
730 8 : ANALYTICAL_LAG_OTHERS;
731 : } else {
732 4 : j += cnt;
733 20 : ANALYTICAL_LAG_OTHERS;
734 : }
735 : }
736 : }
737 30 : bat_iterator_end(&bi);
738 30 : bat_iterator_end(&pi);
739 30 : BATsetcount(r, cnt);
740 30 : r->tnonil = !has_nils;
741 30 : r->tnil = has_nils;
742 30 : return GDK_SUCCEED;
743 : }
744 :
745 : #define LEAD_CALC(TPE) \
746 : do { \
747 : if (lead < ncnt) { \
748 : bp += lead; \
749 : l = ncnt - lead; \
750 : for (i = 0; i < l; i++, rb++, bp++) { \
751 : next = *bp; \
752 : *rb = next; \
753 : has_nils |= is_##TPE##_nil(next); \
754 : } \
755 : } else { \
756 : bp += ncnt; \
757 : } \
758 : for (;rb < rp; rb++) \
759 : *rb = def; \
760 : has_nils |= (lead > 0 && is_##TPE##_nil(def)); \
761 : } while (0)
762 :
763 : #define ANALYTICAL_LEAD_IMP(TPE) \
764 : do { \
765 : TPE *rp, *rb, *bp, *rend, \
766 : def = *((TPE *) default_value), next; \
767 : bp = (TPE*)bi.base; \
768 : rb = rp = (TPE*)Tloc(r, 0); \
769 : rend = rb + cnt; \
770 : if (lead == BUN_NONE) { \
771 : has_nils = true; \
772 : for (; rb < rend; rb++) \
773 : *rb = TPE##_nil; \
774 : } else if (p) { \
775 : pnp = np = (bit*)pi.base; \
776 : end = np + cnt; \
777 : for (; np < end; np++) { \
778 : if (*np) { \
779 : ncnt = (np - pnp); \
780 : rp += ncnt; \
781 : LEAD_CALC(TPE); \
782 : pnp = np; \
783 : } \
784 : } \
785 : ncnt = (np - pnp); \
786 : rp += ncnt; \
787 : LEAD_CALC(TPE); \
788 : } else { \
789 : ncnt = cnt; \
790 : rp += ncnt; \
791 : LEAD_CALC(TPE); \
792 : } \
793 : } while (0)
794 :
795 : #define ANALYTICAL_LEAD_OTHERS \
796 : do { \
797 : j += ncnt; \
798 : if (lead < ncnt) { \
799 : m = ncnt - lead; \
800 : for (i = 0,n = k + lead; i < m; i++, n++) { \
801 : curval = BUNtail(bi, n); \
802 : if (BUNappend(r, curval, false) != GDK_SUCCEED) { \
803 : bat_iterator_end(&bi); \
804 : bat_iterator_end(&pi); \
805 : return GDK_FAIL; \
806 : } \
807 : has_nils |= atomcmp(curval, nil) == 0; \
808 : } \
809 : k += i; \
810 : } \
811 : for (; k < j; k++) { \
812 : if (BUNappend(r, default_value, false) != GDK_SUCCEED) { \
813 : bat_iterator_end(&bi); \
814 : bat_iterator_end(&pi); \
815 : return GDK_FAIL; \
816 : } \
817 : } \
818 : has_nils |= (lead > 0 && atomcmp(default_value, nil) == 0); \
819 : } while (0)
820 :
821 : gdk_return
822 29 : GDKanalyticallead(BAT *r, BAT *b, BAT *p, BUN lead, const void *restrict default_value, int tpe)
823 : {
824 29 : BATiter bi = bat_iterator(b);
825 29 : BATiter pi = bat_iterator(p);
826 29 : int (*atomcmp) (const void *, const void *);
827 29 : const void *restrict nil;
828 29 : BUN i = 0, j = 0, k = 0, l = 0, ncnt, cnt = BATcount(b);
829 29 : bit *np, *pnp, *end;
830 29 : bool has_nils = false;
831 :
832 29 : assert(default_value);
833 :
834 58 : switch (ATOMbasetype(tpe)) {
835 4 : case TYPE_bte:
836 35 : ANALYTICAL_LEAD_IMP(bte);
837 : break;
838 0 : case TYPE_sht:
839 0 : ANALYTICAL_LEAD_IMP(sht);
840 : break;
841 18 : case TYPE_int:
842 296 : ANALYTICAL_LEAD_IMP(int);
843 : break;
844 1 : case TYPE_lng:
845 23 : ANALYTICAL_LEAD_IMP(lng);
846 : break;
847 : #ifdef HAVE_HGE
848 0 : case TYPE_hge:
849 0 : ANALYTICAL_LEAD_IMP(hge);
850 : break;
851 : #endif
852 0 : case TYPE_flt:
853 0 : ANALYTICAL_LEAD_IMP(flt);
854 : break;
855 0 : case TYPE_dbl:
856 0 : ANALYTICAL_LEAD_IMP(dbl);
857 : break;
858 6 : default:{
859 6 : BUN m = 0, n = 0;
860 6 : const void *restrict curval;
861 6 : nil = ATOMnilptr(tpe);
862 6 : atomcmp = ATOMcompare(tpe);
863 6 : if (lead == BUN_NONE) {
864 0 : has_nils = true;
865 0 : for (j = 0; j < cnt; j++) {
866 0 : if (BUNappend(r, nil, false) != GDK_SUCCEED) {
867 0 : bat_iterator_end(&bi);
868 0 : bat_iterator_end(&pi);
869 0 : return GDK_FAIL;
870 : }
871 : }
872 6 : } else if (p) {
873 4 : pnp = np = (bit *) pi.base;
874 4 : end = np + cnt;
875 42 : for (; np < end; np++) {
876 38 : if (*np) {
877 12 : ncnt = (np - pnp);
878 56 : ANALYTICAL_LEAD_OTHERS;
879 12 : pnp = np;
880 : }
881 : }
882 4 : ncnt = (np - pnp);
883 14 : ANALYTICAL_LEAD_OTHERS;
884 : } else {
885 2 : ncnt = cnt;
886 20 : ANALYTICAL_LEAD_OTHERS;
887 : }
888 : }
889 : }
890 29 : bat_iterator_end(&bi);
891 29 : bat_iterator_end(&pi);
892 29 : BATsetcount(r, cnt);
893 29 : r->tnonil = !has_nils;
894 29 : r->tnil = has_nils;
895 29 : return GDK_SUCCEED;
896 : }
897 :
898 : #define ANALYTICAL_MIN_MAX_CALC_FIXED_UNBOUNDED_TILL_CURRENT_ROW(TPE, MIN_MAX) \
899 : do { \
900 : TPE curval = TPE##_nil; \
901 : for (; k < i;) { \
902 : j = k; \
903 : do { \
904 : if (!is_##TPE##_nil(bp[k])) { \
905 : if (is_##TPE##_nil(curval)) \
906 : curval = bp[k]; \
907 : else \
908 : curval = MIN_MAX(bp[k], curval); \
909 : } \
910 : k++; \
911 : } while (k < i && !op[k]); \
912 : for (; j < k; j++) \
913 : rb[j] = curval; \
914 : has_nils |= is_##TPE##_nil(curval); \
915 : } \
916 : } while (0)
917 :
918 : #define ANALYTICAL_MIN_MAX_CALC_FIXED_CURRENT_ROW_TILL_UNBOUNDED(TPE, MIN_MAX) \
919 : do { \
920 : TPE curval = TPE##_nil; \
921 : l = i - 1; \
922 : for (j = l; ; j--) { \
923 : if (!is_##TPE##_nil(bp[j])) { \
924 : if (is_##TPE##_nil(curval)) \
925 : curval = bp[j]; \
926 : else \
927 : curval = MIN_MAX(bp[j], curval); \
928 : } \
929 : if (op[j] || j == k) { \
930 : for (; ; l--) { \
931 : rb[l] = curval; \
932 : if (l == j) \
933 : break; \
934 : } \
935 : has_nils |= is_##TPE##_nil(curval); \
936 : if (j == k) \
937 : break; \
938 : l = j - 1; \
939 : } \
940 : } \
941 : k = i; \
942 : } while (0)
943 :
944 : #define ANALYTICAL_MIN_MAX_CALC_FIXED_ALL_ROWS(TPE, MIN_MAX) \
945 : do { \
946 : TPE curval = TPE##_nil; \
947 : for (j = k; j < i; j++) { \
948 : TPE v = bp[j]; \
949 : if (!is_##TPE##_nil(v)) { \
950 : if (is_##TPE##_nil(curval)) \
951 : curval = v; \
952 : else \
953 : curval = MIN_MAX(v, curval); \
954 : } \
955 : } \
956 : for (; k < i; k++) \
957 : rb[k] = curval; \
958 : has_nils |= is_##TPE##_nil(curval); \
959 : } while (0)
960 :
961 : #define ANALYTICAL_MIN_MAX_CALC_FIXED_CURRENT_ROW(TPE, MIN_MAX) \
962 : do { \
963 : for (; k < i; k++) { \
964 : TPE v = bp[k]; \
965 : rb[k] = v; \
966 : has_nils |= is_##TPE##_nil(v); \
967 : } \
968 : } while (0)
969 :
970 : #define INIT_AGGREGATE_MIN_MAX_FIXED(TPE, MIN_MAX, NOTHING) \
971 : do { \
972 : computed = TPE##_nil; \
973 : } while (0)
974 : #define COMPUTE_LEVEL0_MIN_MAX_FIXED(X, TPE, MIN_MAX, NOTHING) \
975 : do { \
976 : computed = bp[j + X]; \
977 : } while (0)
978 : #define COMPUTE_LEVELN_MIN_MAX_FIXED(VAL, TPE, MIN_MAX, NOTHING) \
979 : do { \
980 : if (!is_##TPE##_nil(VAL)) { \
981 : if (is_##TPE##_nil(computed)) \
982 : computed = VAL; \
983 : else \
984 : computed = MIN_MAX(computed, VAL); \
985 : } \
986 : } while (0)
987 : #define FINALIZE_AGGREGATE_MIN_MAX_FIXED(TPE, MIN_MAX, NOTHING) \
988 : do { \
989 : rb[k] = computed; \
990 : has_nils |= is_##TPE##_nil(computed); \
991 : } while (0)
992 : #define ANALYTICAL_MIN_MAX_CALC_FIXED_OTHERS(TPE, MIN_MAX) \
993 : do { \
994 : oid ncount = i - k; \
995 : if ((res = GDKrebuild_segment_tree(ncount, sizeof(TPE), st, &segment_tree, &levels_offset, &nlevels)) != GDK_SUCCEED) \
996 : goto cleanup; \
997 : populate_segment_tree(TPE, ncount, INIT_AGGREGATE_MIN_MAX_FIXED, COMPUTE_LEVEL0_MIN_MAX_FIXED, COMPUTE_LEVELN_MIN_MAX_FIXED, TPE, MIN_MAX, NOTHING); \
998 : for (; k < i; k++) \
999 : compute_on_segment_tree(TPE, start[k] - j, end[k] - j, INIT_AGGREGATE_MIN_MAX_FIXED, COMPUTE_LEVELN_MIN_MAX_FIXED, FINALIZE_AGGREGATE_MIN_MAX_FIXED, TPE, MIN_MAX, NOTHING); \
1000 : j = k; \
1001 : } while (0)
1002 :
1003 : #define ANALYTICAL_MIN_MAX_CALC_OTHERS_UNBOUNDED_TILL_CURRENT_ROW(GT_LT) \
1004 : do { \
1005 : const void *curval = nil; \
1006 : if (ATOMvarsized(tpe)) { \
1007 : for (; k < i;) { \
1008 : j = k; \
1009 : do { \
1010 : const void *next = BUNtvar(bi, k); \
1011 : if (atomcmp(next, nil) != 0) { \
1012 : if (atomcmp(curval, nil) == 0) \
1013 : curval = next; \
1014 : else \
1015 : curval = atomcmp(next, curval) GT_LT 0 ? curval : next; \
1016 : } \
1017 : k++; \
1018 : } while (k < i && !op[k]); \
1019 : for (; j < k; j++) \
1020 : if ((res = tfastins_nocheckVAR(r, j, curval)) != GDK_SUCCEED) \
1021 : goto cleanup; \
1022 : has_nils |= atomcmp(curval, nil) == 0; \
1023 : } \
1024 : } else { \
1025 : for (; k < i;) { \
1026 : j = k; \
1027 : do { \
1028 : const void *next = BUNtloc(bi, k); \
1029 : if (atomcmp(next, nil) != 0) { \
1030 : if (atomcmp(curval, nil) == 0) \
1031 : curval = next; \
1032 : else \
1033 : curval = atomcmp(next, curval) GT_LT 0 ? curval : next; \
1034 : } \
1035 : k++; \
1036 : } while (k < i && !op[k]); \
1037 : for (; j < k; j++) { \
1038 : memcpy(rcast, curval, width); \
1039 : rcast += width; \
1040 : } \
1041 : has_nils |= atomcmp(curval, nil) == 0; \
1042 : } \
1043 : } \
1044 : } while (0)
1045 :
1046 : #define ANALYTICAL_MIN_MAX_CALC_OTHERS_CURRENT_ROW_TILL_UNBOUNDED(GT_LT) \
1047 : do { \
1048 : const void *curval = nil; \
1049 : l = i - 1; \
1050 : if (ATOMvarsized(tpe)) { \
1051 : for (j = l; ; j--) { \
1052 : const void *next = BUNtvar(bi, j); \
1053 : if (atomcmp(next, nil) != 0) { \
1054 : if (atomcmp(curval, nil) == 0) \
1055 : curval = next; \
1056 : else \
1057 : curval = atomcmp(next, curval) GT_LT 0 ? curval : next; \
1058 : } \
1059 : if (op[j] || j == k) { \
1060 : for (; ; l--) { \
1061 : if ((res = tfastins_nocheckVAR(r, l, curval)) != GDK_SUCCEED) \
1062 : goto cleanup; \
1063 : if (l == j) \
1064 : break; \
1065 : } \
1066 : has_nils |= atomcmp(curval, nil) == 0; \
1067 : if (j == k) \
1068 : break; \
1069 : l = j - 1; \
1070 : } \
1071 : } \
1072 : } else { \
1073 : for (j = l; ; j--) { \
1074 : const void *next = BUNtloc(bi, j); \
1075 : if (atomcmp(next, nil) != 0) { \
1076 : if (atomcmp(curval, nil) == 0) \
1077 : curval = next; \
1078 : else \
1079 : curval = atomcmp(next, curval) GT_LT 0 ? curval : next; \
1080 : } \
1081 : if (op[j] || j == k) { \
1082 : BUN x = l * width; \
1083 : for (; ; l--) { \
1084 : memcpy(rcast + x, curval, width); \
1085 : x -= width; \
1086 : if (l == j) \
1087 : break; \
1088 : } \
1089 : has_nils |= atomcmp(curval, nil) == 0; \
1090 : if (j == k) \
1091 : break; \
1092 : l = j - 1; \
1093 : } \
1094 : } \
1095 : } \
1096 : k = i; \
1097 : } while (0)
1098 :
1099 : #define ANALYTICAL_MIN_MAX_CALC_OTHERS_ALL_ROWS(GT_LT) \
1100 : do { \
1101 : const void *curval = (void*) nil; \
1102 : if (ATOMvarsized(tpe)) { \
1103 : for (j = k; j < i; j++) { \
1104 : const void *next = BUNtvar(bi, j); \
1105 : if (atomcmp(next, nil) != 0) { \
1106 : if (atomcmp(curval, nil) == 0) \
1107 : curval = next; \
1108 : else \
1109 : curval = atomcmp(next, curval) GT_LT 0 ? curval : next; \
1110 : } \
1111 : } \
1112 : for (; k < i; k++) \
1113 : if ((res = tfastins_nocheckVAR(r, k, curval)) != GDK_SUCCEED) \
1114 : goto cleanup; \
1115 : } else { \
1116 : for (j = k; j < i; j++) { \
1117 : const void *next = BUNtloc(bi, j); \
1118 : if (atomcmp(next, nil) != 0) { \
1119 : if (atomcmp(curval, nil) == 0) \
1120 : curval = next; \
1121 : else \
1122 : curval = atomcmp(next, curval) GT_LT 0 ? curval : next; \
1123 : } \
1124 : } \
1125 : for (; k < i; k++) { \
1126 : memcpy(rcast, curval, width); \
1127 : rcast += width; \
1128 : } \
1129 : } \
1130 : has_nils |= atomcmp(curval, nil) == 0; \
1131 : } while (0)
1132 :
1133 : #define ANALYTICAL_MIN_MAX_CALC_OTHERS_CURRENT_ROW(GT_LT) \
1134 : do { \
1135 : if (ATOMvarsized(tpe)) { \
1136 : for (; k < i; k++) { \
1137 : const void *next = BUNtvar(bi, k); \
1138 : if ((res = tfastins_nocheckVAR(r, k, next)) != GDK_SUCCEED) \
1139 : goto cleanup; \
1140 : has_nils |= atomcmp(next, nil) == 0; \
1141 : } \
1142 : } else { \
1143 : for (; k < i; k++) { \
1144 : const void *next = BUNtloc(bi, k); \
1145 : memcpy(rcast, next, width); \
1146 : rcast += width; \
1147 : has_nils |= atomcmp(next, nil) == 0; \
1148 : } \
1149 : } \
1150 : } while (0)
1151 :
1152 : #define INIT_AGGREGATE_MIN_MAX_OTHERS(GT_LT, NOTHING1, NOTHING2) \
1153 : do { \
1154 : computed = (void*) nil; \
1155 : } while (0)
1156 : #define COMPUTE_LEVEL0_MIN_MAX_OTHERS(X, GT_LT, NOTHING1, NOTHING2) \
1157 : do { \
1158 : computed = BUNtail(bi, j + X); \
1159 : } while (0)
1160 : #define COMPUTE_LEVELN_MIN_MAX_OTHERS(VAL, GT_LT, NOTHING1, NOTHING2) \
1161 : do { \
1162 : if (atomcmp(VAL, nil) != 0) { \
1163 : if (atomcmp(computed, nil) == 0) \
1164 : computed = VAL; \
1165 : else \
1166 : computed = atomcmp(VAL, computed) GT_LT 0 ? computed : VAL; \
1167 : } \
1168 : } while (0)
1169 : #define FINALIZE_AGGREGATE_MIN_MAX_OTHERS(GT_LT, NOTHING1, NOTHING2) \
1170 : do { \
1171 : if (ATOMvarsized(tpe)) { \
1172 : if ((res = tfastins_nocheckVAR(r, k, computed)) != GDK_SUCCEED) \
1173 : goto cleanup; \
1174 : } else { \
1175 : memcpy(rcast, computed, width); \
1176 : rcast += width; \
1177 : } \
1178 : has_nils |= atomcmp(computed, nil) == 0; \
1179 : } while (0)
1180 : #define ANALYTICAL_MIN_MAX_CALC_OTHERS_OTHERS(GT_LT) \
1181 : do { \
1182 : oid ncount = i - k; \
1183 : if ((res = GDKrebuild_segment_tree(ncount, sizeof(void*), st, &segment_tree, &levels_offset, &nlevels)) != GDK_SUCCEED) \
1184 : goto cleanup; \
1185 : populate_segment_tree(void*, ncount, INIT_AGGREGATE_MIN_MAX_OTHERS, COMPUTE_LEVEL0_MIN_MAX_OTHERS, COMPUTE_LEVELN_MIN_MAX_OTHERS, GT_LT, NOTHING, NOTHING); \
1186 : for (; k < i; k++) \
1187 : compute_on_segment_tree(void*, start[k] - j, end[k] - j, INIT_AGGREGATE_MIN_MAX_OTHERS, COMPUTE_LEVELN_MIN_MAX_OTHERS, FINALIZE_AGGREGATE_MIN_MAX_OTHERS, GT_LT, NOTHING, NOTHING); \
1188 : j = k; \
1189 : } while (0)
1190 :
1191 : #define ANALYTICAL_MIN_MAX_PARTITIONS(TPE, MIN_MAX, IMP) \
1192 : do { \
1193 : TPE *restrict bp = (TPE*)bi.base, *rb = (TPE*)Tloc(r, 0); \
1194 : if (p) { \
1195 : while (i < cnt) { \
1196 : if (np[i]) { \
1197 : minmaxfixed##TPE##IMP: \
1198 : ANALYTICAL_MIN_MAX_CALC_FIXED_##IMP(TPE, MIN_MAX); \
1199 : } \
1200 : if (!last) \
1201 : i++; \
1202 : } \
1203 : } \
1204 : if (!last) { /* hack to reduce code explosion, there's no need to duplicate the code to iterate each partition */ \
1205 : last = true; \
1206 : i = cnt; \
1207 : goto minmaxfixed##TPE##IMP; \
1208 : } \
1209 : } while (0)
1210 :
1211 : #ifdef HAVE_HGE
1212 : #define ANALYTICAL_MIN_MAX_LIMIT(MIN_MAX, IMP) \
1213 : case TYPE_hge: \
1214 : ANALYTICAL_MIN_MAX_PARTITIONS(hge, MIN_MAX, IMP); \
1215 : break;
1216 : #else
1217 : #define ANALYTICAL_MIN_MAX_LIMIT(MIN_MAX, IMP)
1218 : #endif
1219 :
1220 : #define ANALYTICAL_MIN_MAX_BRANCHES(MIN_MAX, GT_LT, IMP) \
1221 : do { \
1222 : switch (ATOMbasetype(tpe)) { \
1223 : case TYPE_bte: \
1224 : ANALYTICAL_MIN_MAX_PARTITIONS(bte, MIN_MAX, IMP); \
1225 : break; \
1226 : case TYPE_sht: \
1227 : ANALYTICAL_MIN_MAX_PARTITIONS(sht, MIN_MAX, IMP); \
1228 : break; \
1229 : case TYPE_int: \
1230 : ANALYTICAL_MIN_MAX_PARTITIONS(int, MIN_MAX, IMP); \
1231 : break; \
1232 : case TYPE_lng: \
1233 : ANALYTICAL_MIN_MAX_PARTITIONS(lng, MIN_MAX, IMP); \
1234 : break; \
1235 : ANALYTICAL_MIN_MAX_LIMIT(MIN_MAX, IMP) \
1236 : case TYPE_flt: \
1237 : ANALYTICAL_MIN_MAX_PARTITIONS(flt, MIN_MAX, IMP); \
1238 : break; \
1239 : case TYPE_dbl: \
1240 : ANALYTICAL_MIN_MAX_PARTITIONS(dbl, MIN_MAX, IMP); \
1241 : break; \
1242 : default: { \
1243 : if (p) { \
1244 : while (i < cnt) { \
1245 : if (np[i]) { \
1246 : minmaxvarsized##IMP: \
1247 : ANALYTICAL_MIN_MAX_CALC_OTHERS_##IMP(GT_LT); \
1248 : } \
1249 : if (!last) \
1250 : i++; \
1251 : } \
1252 : } \
1253 : if (!last) { \
1254 : last = true; \
1255 : i = cnt; \
1256 : goto minmaxvarsized##IMP; \
1257 : } \
1258 : } \
1259 : } \
1260 : } while (0)
1261 :
1262 : #define ANALYTICAL_MIN_MAX(OP, MIN_MAX, GT_LT) \
1263 : gdk_return \
1264 : GDKanalytical##OP(BAT *r, BAT *p, BAT *o, BAT *b, BAT *s, BAT *e, int tpe, int frame_type) \
1265 : { \
1266 : BATiter pi = bat_iterator(p); \
1267 : BATiter oi = bat_iterator(o); \
1268 : BATiter bi = bat_iterator(b); \
1269 : BATiter si = bat_iterator(s); \
1270 : BATiter ei = bat_iterator(e); \
1271 : bool has_nils = false, last = false; \
1272 : oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b), *restrict start = si.base, *restrict end = ei.base, \
1273 : *levels_offset = NULL, nlevels = 0; \
1274 : bit *np = pi.base, *op = oi.base; \
1275 : const void *nil = ATOMnilptr(tpe); \
1276 : int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe); \
1277 : void *segment_tree = NULL; \
1278 : gdk_return res = GDK_SUCCEED; \
1279 : uint16_t width = r->twidth; \
1280 : uint8_t *restrict rcast = (uint8_t *) Tloc(r, 0); \
1281 : BAT *st = NULL; \
1282 : \
1283 : if (cnt > 0) { \
1284 : switch (frame_type) { \
1285 : case 3: /* unbounded until current row */ \
1286 : ANALYTICAL_MIN_MAX_BRANCHES(MIN_MAX, GT_LT, UNBOUNDED_TILL_CURRENT_ROW); \
1287 : break; \
1288 : case 4: /* current row until unbounded */ \
1289 : ANALYTICAL_MIN_MAX_BRANCHES(MIN_MAX, GT_LT, CURRENT_ROW_TILL_UNBOUNDED); \
1290 : break; \
1291 : case 5: /* all rows */ \
1292 : ANALYTICAL_MIN_MAX_BRANCHES(MIN_MAX, GT_LT, ALL_ROWS); \
1293 : break; \
1294 : case 6: /* current row */ \
1295 : ANALYTICAL_MIN_MAX_BRANCHES(MIN_MAX, GT_LT, CURRENT_ROW); \
1296 : break; \
1297 : default: \
1298 : if ((st = GDKinitialize_segment_tree()) == NULL) { \
1299 : res = GDK_FAIL; \
1300 : goto cleanup; \
1301 : } \
1302 : ANALYTICAL_MIN_MAX_BRANCHES(MIN_MAX, GT_LT, OTHERS); \
1303 : break; \
1304 : } \
1305 : } \
1306 : \
1307 : BATsetcount(r, cnt); \
1308 : r->tnonil = !has_nils; \
1309 : r->tnil = has_nils; \
1310 : cleanup: \
1311 : bat_iterator_end(&pi); \
1312 : bat_iterator_end(&oi); \
1313 : bat_iterator_end(&bi); \
1314 : bat_iterator_end(&si); \
1315 : bat_iterator_end(&ei); \
1316 : BBPreclaim(st); \
1317 : return res; \
1318 : }
1319 :
1320 3381 : ANALYTICAL_MIN_MAX(min, MIN, >)
1321 15178781 : ANALYTICAL_MIN_MAX(max, MAX, <)
1322 :
1323 : /* Counting no nils for fixed sizes */
1324 : #define ANALYTICAL_COUNT_FIXED_UNBOUNDED_TILL_CURRENT_ROW(TPE) \
1325 : do { \
1326 : curval = 0; \
1327 : if (count_all) { \
1328 : for (; k < i;) { \
1329 : j = k; \
1330 : do { \
1331 : k++; \
1332 : } while (k < i && !op[k]); \
1333 : curval += k - j; \
1334 : for (; j < k; j++) \
1335 : rb[j] = curval; \
1336 : } \
1337 : } else { \
1338 : for (; k < i;) { \
1339 : j = k; \
1340 : do { \
1341 : curval += !is_##TPE##_nil(bp[k]); \
1342 : k++; \
1343 : } while (k < i && !op[k]); \
1344 : for (; j < k; j++) \
1345 : rb[j] = curval; \
1346 : } \
1347 : } \
1348 : } while (0)
1349 :
1350 : #define ANALYTICAL_COUNT_FIXED_CURRENT_ROW_TILL_UNBOUNDED(TPE) \
1351 : do { \
1352 : curval = 0; \
1353 : l = i - 1; \
1354 : if (count_all) { \
1355 : for (j = l; ; j--) { \
1356 : if (op[j] || j == k) { \
1357 : curval += l - j + 1; \
1358 : for (; ; l--) { \
1359 : rb[l] = curval; \
1360 : if (l == j) \
1361 : break; \
1362 : } \
1363 : if (j == k) \
1364 : break; \
1365 : l = j - 1; \
1366 : } \
1367 : } \
1368 : } else { \
1369 : for (j = l; ; j--) { \
1370 : curval += !is_##TPE##_nil(bp[j]); \
1371 : if (op[j] || j == k) { \
1372 : for (; ; l--) { \
1373 : rb[l] = curval; \
1374 : if (l == j) \
1375 : break; \
1376 : } \
1377 : if (j == k) \
1378 : break; \
1379 : l = j - 1; \
1380 : } \
1381 : } \
1382 : } \
1383 : k = i; \
1384 : } while (0)
1385 :
1386 : #define ANALYTICAL_COUNT_FIXED_ALL_ROWS(TPE) \
1387 : do { \
1388 : if (count_all) { \
1389 : curval = (lng)(i - k); \
1390 : for (; k < i; k++) \
1391 : rb[k] = curval; \
1392 : } else { \
1393 : curval = 0; \
1394 : for (; j < i; j++) \
1395 : curval += !is_##TPE##_nil(bp[j]); \
1396 : for (; k < i; k++) \
1397 : rb[k] = curval; \
1398 : } \
1399 : } while (0)
1400 :
1401 : #define ANALYTICAL_COUNT_FIXED_CURRENT_ROW(TPE) \
1402 : do { \
1403 : if (count_all) { \
1404 : for (; k < i; k++) \
1405 : rb[k] = 1; \
1406 : } else { \
1407 : for (; k < i; k++) \
1408 : rb[k] = !is_##TPE##_nil(bp[k]); \
1409 : } \
1410 : } while (0)
1411 :
1412 : #define INIT_AGGREGATE_COUNT(TPE, NOTHING1, NOTHING2) \
1413 : do { \
1414 : computed = 0; \
1415 : } while (0)
1416 : #define COMPUTE_LEVEL0_COUNT_FIXED(X, TPE, NOTHING1, NOTHING2) \
1417 : do { \
1418 : computed = !is_##TPE##_nil(bp[j + X]); \
1419 : } while (0)
1420 : #define COMPUTE_LEVELN_COUNT(VAL, NOTHING1, NOTHING2, NOTHING3) \
1421 : do { \
1422 : computed += VAL; \
1423 : } while (0)
1424 : #define FINALIZE_AGGREGATE_COUNT(NOTHING1, NOTHING2, NOTHING3) \
1425 : do { \
1426 : rb[k] = computed; \
1427 : } while (0)
1428 : #define ANALYTICAL_COUNT_FIXED_OTHERS(TPE) \
1429 : do { \
1430 : if (count_all) { /* no segment tree required for the global case (it scales in O(n)) */ \
1431 : for (; k < i; k++) \
1432 : rb[k] = (end[k] > start[k]) ? (lng)(end[k] - start[k]) : 0; \
1433 : } else { \
1434 : oid ncount = i - k; \
1435 : if ((res = GDKrebuild_segment_tree(ncount, sizeof(lng), st, &segment_tree, &levels_offset, &nlevels)) != GDK_SUCCEED) \
1436 : goto cleanup; \
1437 : populate_segment_tree(lng, ncount, INIT_AGGREGATE_COUNT, COMPUTE_LEVEL0_COUNT_FIXED, COMPUTE_LEVELN_COUNT, TPE, NOTHING, NOTHING); \
1438 : for (; k < i; k++) \
1439 : compute_on_segment_tree(lng, start[k] - j, end[k] - j, INIT_AGGREGATE_COUNT, COMPUTE_LEVELN_COUNT, FINALIZE_AGGREGATE_COUNT, TPE, NOTHING, NOTHING); \
1440 : j = k; \
1441 : } \
1442 : } while (0)
1443 :
1444 : /* Counting no nils for other types */
1445 : #define ANALYTICAL_COUNT_OTHERS_UNBOUNDED_TILL_CURRENT_ROW \
1446 : do { \
1447 : curval = 0; \
1448 : if (count_all) { \
1449 : for (; k < i;) { \
1450 : j = k; \
1451 : do { \
1452 : k++; \
1453 : } while (k < i && !op[k]); \
1454 : curval += k - j; \
1455 : for (; j < k; j++) \
1456 : rb[j] = curval; \
1457 : } \
1458 : } else { \
1459 : for (; k < i; ) { \
1460 : j = k; \
1461 : do { \
1462 : curval += cmp(BUNtail(bi, k), nil) != 0; \
1463 : k++; \
1464 : } while (k < i && !op[k]); \
1465 : for (; j < k; j++) \
1466 : rb[j] = curval; \
1467 : } \
1468 : } \
1469 : } while (0)
1470 :
1471 : #define ANALYTICAL_COUNT_OTHERS_CURRENT_ROW_TILL_UNBOUNDED \
1472 : do { \
1473 : curval = 0; \
1474 : l = i - 1; \
1475 : if (count_all) { \
1476 : for (j = l; ; j--) { \
1477 : if (op[j] || j == k) { \
1478 : curval += l - j + 1; \
1479 : for (; ; l--) { \
1480 : rb[l] = curval; \
1481 : if (l == j) \
1482 : break; \
1483 : } \
1484 : if (j == k) \
1485 : break; \
1486 : l = j - 1; \
1487 : } \
1488 : } \
1489 : } else { \
1490 : for (j = l; ; j--) { \
1491 : curval += cmp(BUNtail(bi, j), nil) != 0; \
1492 : if (op[j] || j == k) { \
1493 : for (; ; l--) { \
1494 : rb[l] = curval; \
1495 : if (l == j) \
1496 : break; \
1497 : } \
1498 : if (j == k) \
1499 : break; \
1500 : l = j - 1; \
1501 : } \
1502 : } \
1503 : } \
1504 : k = i; \
1505 : } while (0)
1506 :
1507 : #define ANALYTICAL_COUNT_OTHERS_ALL_ROWS \
1508 : do { \
1509 : curval = 0; \
1510 : if (count_all) { \
1511 : curval = (lng)(i - k); \
1512 : } else { \
1513 : for (; j < i; j++) \
1514 : curval += cmp(BUNtail(bi, j), nil) != 0; \
1515 : } \
1516 : for (; k < i; k++) \
1517 : rb[k] = curval; \
1518 : } while (0)
1519 :
1520 : #define ANALYTICAL_COUNT_OTHERS_CURRENT_ROW \
1521 : do { \
1522 : if (count_all) { \
1523 : for (; k < i; k++) \
1524 : rb[k] = 1; \
1525 : } else { \
1526 : for (; k < i; k++) \
1527 : rb[k] = cmp(BUNtail(bi, k), nil) != 0; \
1528 : } \
1529 : } while (0)
1530 :
1531 : #define COMPUTE_LEVEL0_COUNT_OTHERS(X, NOTHING1, NOTHING2, NOTHING3) \
1532 : do { \
1533 : computed = cmp(BUNtail(bi, j + X), nil) != 0; \
1534 : } while (0)
1535 : #define ANALYTICAL_COUNT_OTHERS_OTHERS \
1536 : do { \
1537 : if (count_all) { /* no segment tree required for the global case (it scales in O(n)) */ \
1538 : for (; k < i; k++) \
1539 : rb[k] = (end[k] > start[k]) ? (lng)(end[k] - start[k]) : 0; \
1540 : } else { \
1541 : oid ncount = i - k; \
1542 : if ((res = GDKrebuild_segment_tree(ncount, sizeof(lng), st, &segment_tree, &levels_offset, &nlevels)) != GDK_SUCCEED) \
1543 : goto cleanup; \
1544 : populate_segment_tree(lng, ncount, INIT_AGGREGATE_COUNT, COMPUTE_LEVEL0_COUNT_OTHERS, COMPUTE_LEVELN_COUNT, NOTHING, NOTHING, NOTHING); \
1545 : for (; k < i; k++) \
1546 : compute_on_segment_tree(lng, start[k] - j, end[k] - j, INIT_AGGREGATE_COUNT, COMPUTE_LEVELN_COUNT, FINALIZE_AGGREGATE_COUNT, NOTHING, NOTHING, NOTHING); \
1547 : j = k; \
1548 : } \
1549 : } while (0)
1550 :
1551 : /* Now do the count analytic function branches */
1552 : #define ANALYTICAL_COUNT_FIXED_PARTITIONS(TPE, IMP) \
1553 : do { \
1554 : TPE *restrict bp = (TPE*) bheap; \
1555 : if (p) { \
1556 : while (i < cnt) { \
1557 : if (np[i]) { \
1558 : count##TPE##IMP: \
1559 : ANALYTICAL_COUNT_FIXED_##IMP(TPE); \
1560 : } \
1561 : if (!last) \
1562 : i++; \
1563 : } \
1564 : } \
1565 : if (!last) { \
1566 : last = true; \
1567 : i = cnt; \
1568 : goto count##TPE##IMP; \
1569 : } \
1570 : } while (0)
1571 :
1572 : #ifdef HAVE_HGE
1573 : #define ANALYTICAL_COUNT_LIMIT(IMP) \
1574 : case TYPE_hge: \
1575 : ANALYTICAL_COUNT_FIXED_PARTITIONS(hge, IMP); \
1576 : break;
1577 : #else
1578 : #define ANALYTICAL_COUNT_LIMIT(IMP)
1579 : #endif
1580 :
1581 : #define ANALYTICAL_COUNT_BRANCHES(IMP) \
1582 : do { \
1583 : switch (ATOMbasetype(tpe)) { \
1584 : case TYPE_bte: \
1585 : ANALYTICAL_COUNT_FIXED_PARTITIONS(bte, IMP); \
1586 : break; \
1587 : case TYPE_sht: \
1588 : ANALYTICAL_COUNT_FIXED_PARTITIONS(sht, IMP); \
1589 : break; \
1590 : case TYPE_int: \
1591 : ANALYTICAL_COUNT_FIXED_PARTITIONS(int, IMP); \
1592 : break; \
1593 : case TYPE_lng: \
1594 : ANALYTICAL_COUNT_FIXED_PARTITIONS(lng, IMP); \
1595 : break; \
1596 : ANALYTICAL_COUNT_LIMIT(IMP) \
1597 : case TYPE_flt: \
1598 : ANALYTICAL_COUNT_FIXED_PARTITIONS(flt, IMP); \
1599 : break; \
1600 : case TYPE_dbl: \
1601 : ANALYTICAL_COUNT_FIXED_PARTITIONS(dbl, IMP); \
1602 : break; \
1603 : default: { \
1604 : if (p) { \
1605 : while (i < cnt) { \
1606 : if (np[i]) { \
1607 : countothers##IMP: \
1608 : ANALYTICAL_COUNT_OTHERS_##IMP; \
1609 : } \
1610 : if (!last) \
1611 : i++; \
1612 : } \
1613 : } \
1614 : if (!last) { \
1615 : last = true; \
1616 : i = cnt; \
1617 : goto countothers##IMP; \
1618 : } \
1619 : } \
1620 : } \
1621 : } while (0)
1622 :
1623 : gdk_return
1624 159 : GDKanalyticalcount(BAT *r, BAT *p, BAT *o, BAT *b, BAT *s, BAT *e, bit ignore_nils, int tpe, int frame_type)
1625 : {
1626 159 : BATiter pi = bat_iterator(p);
1627 159 : BATiter oi = bat_iterator(o);
1628 159 : BATiter bi = bat_iterator(b);
1629 159 : BATiter si = bat_iterator(s);
1630 159 : BATiter ei = bat_iterator(e);
1631 159 : oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b), *restrict start = si.base, *restrict end = ei.base,
1632 159 : *levels_offset = NULL, nlevels = 0;
1633 159 : lng curval = 0, *rb = (lng *) Tloc(r, 0);
1634 159 : bit *np = pi.base, *op = oi.base;
1635 159 : const void *restrict nil = ATOMnilptr(tpe);
1636 159 : int (*cmp) (const void *, const void *) = ATOMcompare(tpe);
1637 159 : const void *restrict bheap = bi.base;
1638 159 : bool count_all = !ignore_nils || bi.nonil, last = false;
1639 159 : void *segment_tree = NULL;
1640 159 : gdk_return res = GDK_SUCCEED;
1641 159 : BAT *st = NULL;
1642 :
1643 159 : if (cnt > 0) {
1644 159 : switch (frame_type) {
1645 38 : case 3: /* unbounded until current row */
1646 988 : ANALYTICAL_COUNT_BRANCHES(UNBOUNDED_TILL_CURRENT_ROW);
1647 : break;
1648 3 : case 4: /* current row until unbounded */
1649 43 : ANALYTICAL_COUNT_BRANCHES(CURRENT_ROW_TILL_UNBOUNDED);
1650 : break;
1651 32 : case 5: /* all rows */
1652 681 : ANALYTICAL_COUNT_BRANCHES(ALL_ROWS);
1653 : break;
1654 8 : case 6: /* current row */
1655 96 : ANALYTICAL_COUNT_BRANCHES(CURRENT_ROW);
1656 : break;
1657 78 : default:
1658 78 : if (!count_all && (st = GDKinitialize_segment_tree()) == NULL) {
1659 0 : res = GDK_FAIL;
1660 0 : goto cleanup;
1661 : }
1662 2948 : ANALYTICAL_COUNT_BRANCHES(OTHERS);
1663 : break;
1664 : }
1665 : }
1666 :
1667 159 : BATsetcount(r, cnt);
1668 159 : r->tnonil = true;
1669 159 : r->tnil = false;
1670 159 : cleanup:
1671 159 : bat_iterator_end(&pi);
1672 159 : bat_iterator_end(&oi);
1673 159 : bat_iterator_end(&bi);
1674 159 : bat_iterator_end(&si);
1675 159 : bat_iterator_end(&ei);
1676 159 : BBPreclaim(st);
1677 159 : return res;
1678 : }
1679 :
1680 : /* sum on fixed size integers */
1681 : #define ANALYTICAL_SUM_IMP_NUM_UNBOUNDED_TILL_CURRENT_ROW(TPE1, TPE2) \
1682 : do { \
1683 : TPE2 curval = TPE2##_nil; \
1684 : for (; k < i;) { \
1685 : j = k; \
1686 : do { \
1687 : if (!is_##TPE1##_nil(bp[k])) { \
1688 : if (is_##TPE2##_nil(curval)) \
1689 : curval = (TPE2) bp[k]; \
1690 : else \
1691 : ADD_WITH_CHECK(bp[k], curval, TPE2, curval, GDK_##TPE2##_max, goto calc_overflow); \
1692 : } \
1693 : k++; \
1694 : } while (k < i && !op[k]); \
1695 : for (; j < k; j++) \
1696 : rb[j] = curval; \
1697 : has_nils |= is_##TPE2##_nil(curval); \
1698 : } \
1699 : } while (0)
1700 :
1701 : #define ANALYTICAL_SUM_IMP_NUM_CURRENT_ROW_TILL_UNBOUNDED(TPE1, TPE2) \
1702 : do { \
1703 : TPE2 curval = TPE2##_nil; \
1704 : l = i - 1; \
1705 : for (j = l; ; j--) { \
1706 : if (!is_##TPE1##_nil(bp[j])) { \
1707 : if (is_##TPE2##_nil(curval)) \
1708 : curval = (TPE2) bp[j]; \
1709 : else \
1710 : ADD_WITH_CHECK(bp[j], curval, TPE2, curval, GDK_##TPE2##_max, goto calc_overflow); \
1711 : } \
1712 : if (op[j] || j == k) { \
1713 : for (; ; l--) { \
1714 : rb[l] = curval; \
1715 : if (l == j) \
1716 : break; \
1717 : } \
1718 : has_nils |= is_##TPE2##_nil(curval); \
1719 : if (j == k) \
1720 : break; \
1721 : l = j - 1; \
1722 : } \
1723 : } \
1724 : k = i; \
1725 : } while (0)
1726 :
1727 : #define ANALYTICAL_SUM_IMP_NUM_ALL_ROWS(TPE1, TPE2) \
1728 : do { \
1729 : TPE2 curval = TPE2##_nil; \
1730 : for (; j < i; j++) { \
1731 : TPE1 v = bp[j]; \
1732 : if (!is_##TPE1##_nil(v)) { \
1733 : if (is_##TPE2##_nil(curval)) \
1734 : curval = (TPE2) v; \
1735 : else \
1736 : ADD_WITH_CHECK(v, curval, TPE2, curval, GDK_##TPE2##_max, goto calc_overflow); \
1737 : } \
1738 : } \
1739 : for (; k < i; k++) \
1740 : rb[k] = curval; \
1741 : has_nils |= is_##TPE2##_nil(curval); \
1742 : } while (0)
1743 :
1744 : #define ANALYTICAL_SUM_IMP_NUM_CURRENT_ROW(TPE1, TPE2) \
1745 : do { \
1746 : for (; k < i; k++) { \
1747 : TPE1 v = bp[k]; \
1748 : if (is_##TPE1##_nil(v)) { \
1749 : rb[k] = TPE2##_nil; \
1750 : has_nils = true; \
1751 : } else { \
1752 : rb[k] = (TPE2) v; \
1753 : } \
1754 : } \
1755 : } while (0)
1756 :
1757 : #define INIT_AGGREGATE_SUM(NOTHING1, TPE2, NOTHING2) \
1758 : do { \
1759 : computed = TPE2##_nil; \
1760 : } while (0)
1761 : #define COMPUTE_LEVEL0_SUM(X, TPE1, TPE2, NOTHING) \
1762 : do { \
1763 : TPE1 v = bp[j + X]; \
1764 : computed = is_##TPE1##_nil(v) ? TPE2##_nil : (TPE2) v; \
1765 : } while (0)
1766 : #define COMPUTE_LEVELN_SUM_NUM(VAL, NOTHING1, TPE2, NOTHING2) \
1767 : do { \
1768 : if (!is_##TPE2##_nil(VAL)) { \
1769 : if (is_##TPE2##_nil(computed)) \
1770 : computed = VAL; \
1771 : else \
1772 : ADD_WITH_CHECK(VAL, computed, TPE2, computed, GDK_##TPE2##_max, goto calc_overflow); \
1773 : } \
1774 : } while (0)
1775 : #define FINALIZE_AGGREGATE_SUM(NOTHING1, TPE2, NOTHING2) \
1776 : do { \
1777 : rb[k] = computed; \
1778 : has_nils |= is_##TPE2##_nil(computed); \
1779 : } while (0)
1780 : #define ANALYTICAL_SUM_IMP_NUM_OTHERS(TPE1, TPE2) \
1781 : do { \
1782 : oid ncount = i - k; \
1783 : if ((res = GDKrebuild_segment_tree(ncount, sizeof(TPE2), st, &segment_tree, &levels_offset, &nlevels)) != GDK_SUCCEED) \
1784 : goto cleanup; \
1785 : populate_segment_tree(TPE2, ncount, INIT_AGGREGATE_SUM, COMPUTE_LEVEL0_SUM, COMPUTE_LEVELN_SUM_NUM, TPE1, TPE2, NOTHING); \
1786 : for (; k < i; k++) \
1787 : compute_on_segment_tree(TPE2, start[k] - j, end[k] - j, INIT_AGGREGATE_SUM, COMPUTE_LEVELN_SUM_NUM, FINALIZE_AGGREGATE_SUM, TPE1, TPE2, NOTHING); \
1788 : j = k; \
1789 : } while (0)
1790 :
1791 : /* sum on floating-points */
1792 : /* TODO go through a version of dofsum which returns the current partials for all the cases */
1793 : #define ANALYTICAL_SUM_IMP_FP_UNBOUNDED_TILL_CURRENT_ROW(TPE1, TPE2) ANALYTICAL_SUM_IMP_NUM_UNBOUNDED_TILL_CURRENT_ROW(TPE1, TPE2)
1794 : #define ANALYTICAL_SUM_IMP_FP_CURRENT_ROW_TILL_UNBOUNDED(TPE1, TPE2) ANALYTICAL_SUM_IMP_NUM_CURRENT_ROW_TILL_UNBOUNDED(TPE1, TPE2)
1795 :
1796 : #define ANALYTICAL_SUM_IMP_FP_ALL_ROWS(TPE1, TPE2) \
1797 : do { \
1798 : TPE1 *bs = bp + k; \
1799 : BUN parcel = i - k; \
1800 : TPE2 curval = TPE2##_nil; \
1801 : if (dofsum(bs, 0, \
1802 : &(struct canditer){.tpe = cand_dense, .ncand = parcel,}, \
1803 : &curval, 1, TYPE_##TPE1, \
1804 : TYPE_##TPE2, NULL, 0, 0, true, \
1805 : true) == BUN_NONE) { \
1806 : goto bailout; \
1807 : } \
1808 : for (; k < i; k++) \
1809 : rb[k] = curval; \
1810 : has_nils |= is_##TPE2##_nil(curval); \
1811 : } while (0)
1812 :
1813 : #define ANALYTICAL_SUM_IMP_FP_CURRENT_ROW(TPE1, TPE2) ANALYTICAL_SUM_IMP_NUM_CURRENT_ROW(TPE1, TPE2)
1814 : #define ANALYTICAL_SUM_IMP_FP_OTHERS(TPE1, TPE2) ANALYTICAL_SUM_IMP_NUM_OTHERS(TPE1, TPE2)
1815 :
1816 : #define ANALYTICAL_SUM_CALC(TPE1, TPE2, IMP) \
1817 : do { \
1818 : TPE1 *restrict bp = (TPE1*)bi.base; \
1819 : TPE2 *rb = (TPE2*)Tloc(r, 0); \
1820 : if (p) { \
1821 : while (i < cnt) { \
1822 : if (np[i]) { \
1823 : sum##TPE1##TPE2##IMP: \
1824 : IMP(TPE1, TPE2); \
1825 : } \
1826 : if (!last) \
1827 : i++; \
1828 : } \
1829 : } \
1830 : if (!last) { \
1831 : last = true; \
1832 : i = cnt; \
1833 : goto sum##TPE1##TPE2##IMP; \
1834 : } \
1835 : } while (0)
1836 :
1837 : #ifdef HAVE_HGE
1838 : #define ANALYTICAL_SUM_LIMIT(IMP) \
1839 : case TYPE_hge:{ \
1840 : switch (tp1) { \
1841 : case TYPE_bte: \
1842 : ANALYTICAL_SUM_CALC(bte, hge, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1843 : break; \
1844 : case TYPE_sht: \
1845 : ANALYTICAL_SUM_CALC(sht, hge, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1846 : break; \
1847 : case TYPE_int: \
1848 : ANALYTICAL_SUM_CALC(int, hge, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1849 : break; \
1850 : case TYPE_lng: \
1851 : ANALYTICAL_SUM_CALC(lng, hge, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1852 : break; \
1853 : case TYPE_hge: \
1854 : ANALYTICAL_SUM_CALC(hge, hge, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1855 : break; \
1856 : default: \
1857 : goto nosupport; \
1858 : } \
1859 : break; \
1860 : }
1861 : #else
1862 : #define ANALYTICAL_SUM_LIMIT(IMP)
1863 : #endif
1864 :
1865 : #define ANALYTICAL_SUM_BRANCHES(IMP) \
1866 : do { \
1867 : switch (tp2) { \
1868 : case TYPE_bte:{ \
1869 : switch (tp1) { \
1870 : case TYPE_bte: \
1871 : ANALYTICAL_SUM_CALC(bte, bte, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1872 : break; \
1873 : default: \
1874 : goto nosupport; \
1875 : } \
1876 : break; \
1877 : } \
1878 : case TYPE_sht:{ \
1879 : switch (tp1) { \
1880 : case TYPE_bte: \
1881 : ANALYTICAL_SUM_CALC(bte, sht, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1882 : break; \
1883 : case TYPE_sht: \
1884 : ANALYTICAL_SUM_CALC(sht, sht, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1885 : break; \
1886 : default: \
1887 : goto nosupport; \
1888 : } \
1889 : break; \
1890 : } \
1891 : case TYPE_int:{ \
1892 : switch (tp1) { \
1893 : case TYPE_bte: \
1894 : ANALYTICAL_SUM_CALC(bte, int, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1895 : break; \
1896 : case TYPE_sht: \
1897 : ANALYTICAL_SUM_CALC(sht, int, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1898 : break; \
1899 : case TYPE_int: \
1900 : ANALYTICAL_SUM_CALC(int, int, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1901 : break; \
1902 : default: \
1903 : goto nosupport; \
1904 : } \
1905 : break; \
1906 : } \
1907 : case TYPE_lng:{ \
1908 : switch (tp1) { \
1909 : case TYPE_bte: \
1910 : ANALYTICAL_SUM_CALC(bte, lng, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1911 : break; \
1912 : case TYPE_sht: \
1913 : ANALYTICAL_SUM_CALC(sht, lng, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1914 : break; \
1915 : case TYPE_int: \
1916 : ANALYTICAL_SUM_CALC(int, lng, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1917 : break; \
1918 : case TYPE_lng: \
1919 : ANALYTICAL_SUM_CALC(lng, lng, ANALYTICAL_SUM_IMP_NUM_##IMP); \
1920 : break; \
1921 : default: \
1922 : goto nosupport; \
1923 : } \
1924 : break; \
1925 : } \
1926 : ANALYTICAL_SUM_LIMIT(IMP) \
1927 : case TYPE_flt:{ \
1928 : switch (tp1) { \
1929 : case TYPE_flt: \
1930 : ANALYTICAL_SUM_CALC(flt, flt, ANALYTICAL_SUM_IMP_FP_##IMP); \
1931 : break; \
1932 : default: \
1933 : goto nosupport; \
1934 : } \
1935 : break; \
1936 : } \
1937 : case TYPE_dbl:{ \
1938 : switch (tp1) { \
1939 : case TYPE_flt: \
1940 : ANALYTICAL_SUM_CALC(flt, dbl, ANALYTICAL_SUM_IMP_FP_##IMP); \
1941 : break; \
1942 : case TYPE_dbl: \
1943 : ANALYTICAL_SUM_CALC(dbl, dbl, ANALYTICAL_SUM_IMP_FP_##IMP); \
1944 : break; \
1945 : default: \
1946 : goto nosupport; \
1947 : } \
1948 : break; \
1949 : } \
1950 : default: \
1951 : goto nosupport; \
1952 : } \
1953 : } while (0)
1954 :
1955 : gdk_return
1956 130 : GDKanalyticalsum(BAT *r, BAT *p, BAT *o, BAT *b, BAT *s, BAT *e, int tp1, int tp2, int frame_type)
1957 : {
1958 130 : BATiter pi = bat_iterator(p);
1959 130 : BATiter oi = bat_iterator(o);
1960 130 : BATiter bi = bat_iterator(b);
1961 130 : BATiter si = bat_iterator(s);
1962 130 : BATiter ei = bat_iterator(e);
1963 130 : bool has_nils = false, last = false;
1964 130 : oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b), *restrict start = si.base, *restrict end = ei.base,
1965 130 : *levels_offset = NULL, nlevels = 0;
1966 130 : bit *np = pi.base, *op = oi.base;
1967 130 : void *segment_tree = NULL;
1968 130 : gdk_return res = GDK_SUCCEED;
1969 130 : BAT *st = NULL;
1970 :
1971 130 : if (cnt > 0) {
1972 128 : switch (frame_type) {
1973 47 : case 3: /* unbounded until current row */
1974 1272 : ANALYTICAL_SUM_BRANCHES(UNBOUNDED_TILL_CURRENT_ROW);
1975 : break;
1976 0 : case 4: /* current row until unbounded */
1977 0 : ANALYTICAL_SUM_BRANCHES(CURRENT_ROW_TILL_UNBOUNDED);
1978 : break;
1979 32 : case 5: /* all rows */
1980 20617 : ANALYTICAL_SUM_BRANCHES(ALL_ROWS);
1981 : break;
1982 2 : case 6: /* current row */
1983 34 : ANALYTICAL_SUM_BRANCHES(CURRENT_ROW);
1984 : break;
1985 47 : default:
1986 47 : if ((st = GDKinitialize_segment_tree()) == NULL) {
1987 0 : res = GDK_FAIL;
1988 0 : goto cleanup;
1989 : }
1990 8374199 : ANALYTICAL_SUM_BRANCHES(OTHERS);
1991 : break;
1992 : }
1993 : }
1994 :
1995 130 : BATsetcount(r, cnt);
1996 130 : r->tnonil = !has_nils;
1997 130 : r->tnil = has_nils;
1998 130 : goto cleanup; /* all these gotos seem confusing but it cleans up the ending of the operator */
1999 0 : bailout:
2000 0 : GDKerror("42000!error while calculating floating-point sum\n");
2001 0 : res = GDK_FAIL;
2002 0 : goto cleanup;
2003 0 : calc_overflow:
2004 0 : GDKerror("22003!overflow in calculation.\n");
2005 0 : res = GDK_FAIL;
2006 130 : cleanup:
2007 130 : bat_iterator_end(&pi);
2008 130 : bat_iterator_end(&oi);
2009 130 : bat_iterator_end(&bi);
2010 130 : bat_iterator_end(&si);
2011 130 : bat_iterator_end(&ei);
2012 130 : BBPreclaim(st);
2013 130 : return res;
2014 0 : nosupport:
2015 0 : GDKerror("42000!type combination (sum(%s)->%s) not supported.\n", ATOMname(tp1), ATOMname(tp2));
2016 0 : res = GDK_FAIL;
2017 0 : goto cleanup;
2018 : }
2019 :
2020 : /* product on integers */
2021 : #define PROD_NUM(TPE1, TPE2, TPE3, ARG) \
2022 : do { \
2023 : if (!is_##TPE1##_nil(ARG)) { \
2024 : if (is_##TPE2##_nil(curval)) \
2025 : curval = (TPE2) ARG; \
2026 : else \
2027 : MUL4_WITH_CHECK(ARG, curval, TPE2, curval, GDK_##TPE2##_max, TPE3, goto calc_overflow); \
2028 : } \
2029 : } while(0)
2030 :
2031 : #define ANALYTICAL_PROD_CALC_NUM_UNBOUNDED_TILL_CURRENT_ROW(TPE1, TPE2, TPE3) \
2032 : do { \
2033 : TPE2 curval = TPE2##_nil; \
2034 : for (; k < i;) { \
2035 : j = k; \
2036 : do { \
2037 : PROD_NUM(TPE1, TPE2, TPE3, bp[k]); \
2038 : k++; \
2039 : } while (k < i && !op[k]); \
2040 : for (; j < k; j++) \
2041 : rb[j] = curval; \
2042 : has_nils |= is_##TPE2##_nil(curval); \
2043 : } \
2044 : } while (0)
2045 :
2046 : #define ANALYTICAL_PROD_CALC_NUM_CURRENT_ROW_TILL_UNBOUNDED(TPE1, TPE2, TPE3) \
2047 : do { \
2048 : TPE2 curval = TPE2##_nil; \
2049 : l = i - 1; \
2050 : for (j = l; ; j--) { \
2051 : PROD_NUM(TPE1, TPE2, TPE3, bp[j]); \
2052 : if (op[j] || j == k) { \
2053 : for (; ; l--) { \
2054 : rb[l] = curval; \
2055 : if (l == j) \
2056 : break; \
2057 : } \
2058 : has_nils |= is_##TPE2##_nil(curval); \
2059 : if (j == k) \
2060 : break; \
2061 : l = j - 1; \
2062 : } \
2063 : } \
2064 : k = i; \
2065 : } while (0)
2066 :
2067 : #define ANALYTICAL_PROD_CALC_NUM_ALL_ROWS(TPE1, TPE2, TPE3) \
2068 : do { \
2069 : TPE2 curval = TPE2##_nil; \
2070 : for (; j < i; j++) { \
2071 : TPE1 v = bp[j]; \
2072 : PROD_NUM(TPE1, TPE2, TPE3, v); \
2073 : } \
2074 : for (; k < i; k++) \
2075 : rb[k] = curval; \
2076 : has_nils |= is_##TPE2##_nil(curval); \
2077 : } while (0)
2078 :
2079 : #define ANALYTICAL_PROD_CALC_NUM_CURRENT_ROW(TPE1, TPE2, TPE3) \
2080 : do { \
2081 : for (; k < i; k++) { \
2082 : TPE1 v = bp[k]; \
2083 : if (is_##TPE1##_nil(v)) { \
2084 : rb[k] = TPE2##_nil; \
2085 : has_nils = true; \
2086 : } else { \
2087 : rb[k] = (TPE2) v; \
2088 : } \
2089 : } \
2090 : } while (0)
2091 :
2092 : #define INIT_AGGREGATE_PROD(NOTHING1, TPE2, NOTHING2) \
2093 : do { \
2094 : computed = TPE2##_nil; \
2095 : } while (0)
2096 : #define COMPUTE_LEVEL0_PROD(X, TPE1, TPE2, NOTHING) \
2097 : do { \
2098 : TPE1 v = bp[j + X]; \
2099 : computed = is_##TPE1##_nil(v) ? TPE2##_nil : (TPE2) v; \
2100 : } while (0)
2101 : #define COMPUTE_LEVELN_PROD_NUM(VAL, NOTHING, TPE2, TPE3) \
2102 : do { \
2103 : if (!is_##TPE2##_nil(VAL)) { \
2104 : if (is_##TPE2##_nil(computed)) \
2105 : computed = VAL; \
2106 : else \
2107 : MUL4_WITH_CHECK(VAL, computed, TPE2, computed, GDK_##TPE2##_max, TPE3, goto calc_overflow); \
2108 : } \
2109 : } while (0)
2110 : #define FINALIZE_AGGREGATE_PROD(NOTHING1, TPE2, NOTHING2) \
2111 : do { \
2112 : rb[k] = computed; \
2113 : has_nils |= is_##TPE2##_nil(computed); \
2114 : } while (0)
2115 : #define ANALYTICAL_PROD_CALC_NUM_OTHERS(TPE1, TPE2, TPE3) \
2116 : do { \
2117 : oid ncount = i - k; \
2118 : if ((res = GDKrebuild_segment_tree(ncount, sizeof(TPE2), st, &segment_tree, &levels_offset, &nlevels)) != GDK_SUCCEED) \
2119 : goto cleanup; \
2120 : populate_segment_tree(TPE2, ncount, INIT_AGGREGATE_PROD, COMPUTE_LEVEL0_PROD, COMPUTE_LEVELN_PROD_NUM, TPE1, TPE2, TPE3); \
2121 : for (; k < i; k++) \
2122 : compute_on_segment_tree(TPE2, start[k] - j, end[k] - j, INIT_AGGREGATE_PROD, COMPUTE_LEVELN_PROD_NUM, FINALIZE_AGGREGATE_PROD, TPE1, TPE2, TPE3); \
2123 : j = k; \
2124 : } while (0)
2125 :
2126 : /* product on integers while checking for overflows on the output */
2127 : #define PROD_NUM_LIMIT(TPE1, TPE2, REAL_IMP, ARG) \
2128 : do { \
2129 : if (!is_##TPE1##_nil(ARG)) { \
2130 : if (is_##TPE2##_nil(curval)) \
2131 : curval = (TPE2) ARG; \
2132 : else \
2133 : REAL_IMP(ARG, curval, curval, GDK_##TPE2##_max, goto calc_overflow); \
2134 : } \
2135 : } while(0)
2136 :
2137 : #define ANALYTICAL_PROD_CALC_NUM_LIMIT_UNBOUNDED_TILL_CURRENT_ROW(TPE1, TPE2, REAL_IMP) \
2138 : do { \
2139 : TPE2 curval = TPE2##_nil; \
2140 : for (; k < i;) { \
2141 : j = k; \
2142 : do { \
2143 : PROD_NUM_LIMIT(TPE1, TPE2, REAL_IMP, bp[k]); \
2144 : k++; \
2145 : } while (k < i && !op[k]); \
2146 : for (; j < k; j++) \
2147 : rb[j] = curval; \
2148 : has_nils |= is_##TPE2##_nil(curval); \
2149 : } \
2150 : } while (0)
2151 :
2152 : #define ANALYTICAL_PROD_CALC_NUM_LIMIT_CURRENT_ROW_TILL_UNBOUNDED(TPE1, TPE2, REAL_IMP) \
2153 : do { \
2154 : TPE2 curval = TPE2##_nil; \
2155 : l = i - 1; \
2156 : for (j = l; ; j--) { \
2157 : PROD_NUM_LIMIT(TPE1, TPE2, REAL_IMP, bp[j]); \
2158 : if (op[j] || j == k) { \
2159 : for (; ; l--) { \
2160 : rb[l] = curval; \
2161 : if (l == j) \
2162 : break; \
2163 : } \
2164 : has_nils |= is_##TPE2##_nil(curval); \
2165 : if (j == k) \
2166 : break; \
2167 : l = j - 1; \
2168 : } \
2169 : } \
2170 : k = i; \
2171 : } while (0)
2172 :
2173 : #define ANALYTICAL_PROD_CALC_NUM_LIMIT_ALL_ROWS(TPE1, TPE2, REAL_IMP) \
2174 : do { \
2175 : TPE2 curval = TPE2##_nil; \
2176 : for (; j < i; j++) { \
2177 : TPE1 v = bp[j]; \
2178 : PROD_NUM_LIMIT(TPE1, TPE2, REAL_IMP, v); \
2179 : } \
2180 : for (; k < i; k++) \
2181 : rb[k] = curval; \
2182 : has_nils |= is_##TPE2##_nil(curval); \
2183 : } while (0)
2184 :
2185 : #define ANALYTICAL_PROD_CALC_NUM_LIMIT_CURRENT_ROW(TPE1, TPE2, REAL_IMP) \
2186 : do { \
2187 : for (; k < i; k++) { \
2188 : TPE1 v = bp[k]; \
2189 : if (is_##TPE1##_nil(v)) { \
2190 : rb[k] = TPE2##_nil; \
2191 : has_nils = true; \
2192 : } else { \
2193 : rb[k] = (TPE2) v; \
2194 : } \
2195 : } \
2196 : } while (0)
2197 :
2198 : #define COMPUTE_LEVELN_PROD_NUM_LIMIT(VAL, NOTHING, TPE2, REAL_IMP) \
2199 : do { \
2200 : if (!is_##TPE2##_nil(VAL)) { \
2201 : if (is_##TPE2##_nil(computed)) \
2202 : computed = VAL; \
2203 : else \
2204 : REAL_IMP(VAL, computed, computed, GDK_##TPE2##_max, goto calc_overflow); \
2205 : } \
2206 : } while (0)
2207 : #define ANALYTICAL_PROD_CALC_NUM_LIMIT_OTHERS(TPE1, TPE2, REAL_IMP) \
2208 : do { \
2209 : oid ncount = i - k; \
2210 : if ((res = GDKrebuild_segment_tree(ncount, sizeof(TPE2), st, &segment_tree, &levels_offset, &nlevels)) != GDK_SUCCEED) \
2211 : goto cleanup; \
2212 : populate_segment_tree(TPE2, ncount, INIT_AGGREGATE_PROD, COMPUTE_LEVEL0_PROD, COMPUTE_LEVELN_PROD_NUM_LIMIT, TPE1, TPE2, REAL_IMP); \
2213 : for (; k < i; k++) \
2214 : compute_on_segment_tree(TPE2, start[k] - j, end[k] - j, INIT_AGGREGATE_PROD, COMPUTE_LEVELN_PROD_NUM_LIMIT, FINALIZE_AGGREGATE_PROD, TPE1, TPE2, REAL_IMP); \
2215 : j = k; \
2216 : } while (0)
2217 :
2218 : /* product on floating-points */
2219 : #define PROD_FP(TPE1, TPE2, ARG) \
2220 : do { \
2221 : if (!is_##TPE1##_nil(ARG)) { \
2222 : if (is_##TPE2##_nil(curval)) { \
2223 : curval = (TPE2) ARG; \
2224 : } else if (ABSOLUTE(curval) > 1 && GDK_##TPE2##_max / ABSOLUTE(ARG) < ABSOLUTE(curval)) { \
2225 : goto calc_overflow; \
2226 : } else { \
2227 : curval *= ARG; \
2228 : } \
2229 : } \
2230 : } while(0)
2231 :
2232 : #define ANALYTICAL_PROD_CALC_FP_UNBOUNDED_TILL_CURRENT_ROW(TPE1, TPE2, ARG3) /* ARG3 is ignored here */ \
2233 : do { \
2234 : TPE2 curval = TPE2##_nil; \
2235 : for (; k < i;) { \
2236 : j = k; \
2237 : do { \
2238 : PROD_FP(TPE1, TPE2, bp[k]); \
2239 : k++; \
2240 : } while (k < i && !op[k]); \
2241 : for (; j < k; j++) \
2242 : rb[j] = curval; \
2243 : has_nils |= is_##TPE2##_nil(curval); \
2244 : } \
2245 : } while (0)
2246 :
2247 : #define ANALYTICAL_PROD_CALC_FP_CURRENT_ROW_TILL_UNBOUNDED(TPE1, TPE2, ARG3) /* ARG3 is ignored here */ \
2248 : do { \
2249 : TPE2 curval = TPE2##_nil; \
2250 : l = i - 1; \
2251 : for (j = l; ; j--) { \
2252 : PROD_FP(TPE1, TPE2, bp[j]); \
2253 : if (op[j] || j == k) { \
2254 : for (; ; l--) { \
2255 : rb[l] = curval; \
2256 : if (l == j) \
2257 : break; \
2258 : } \
2259 : has_nils |= is_##TPE2##_nil(curval); \
2260 : if (j == k) \
2261 : break; \
2262 : l = j - 1; \
2263 : } \
2264 : } \
2265 : k = i; \
2266 : } while (0)
2267 :
2268 : #define ANALYTICAL_PROD_CALC_FP_ALL_ROWS(TPE1, TPE2, ARG3) /* ARG3 is ignored here */ \
2269 : do { \
2270 : TPE2 curval = TPE2##_nil; \
2271 : for (; j < i; j++) { \
2272 : TPE1 v = bp[j]; \
2273 : PROD_FP(TPE1, TPE2, v); \
2274 : } \
2275 : for (; k < i; k++) \
2276 : rb[k] = curval; \
2277 : has_nils |= is_##TPE2##_nil(curval); \
2278 : } while (0)
2279 :
2280 : #define ANALYTICAL_PROD_CALC_FP_CURRENT_ROW(TPE1, TPE2, ARG3) /* ARG3 is ignored here */ \
2281 : do { \
2282 : for (; k < i; k++) { \
2283 : TPE1 v = bp[k]; \
2284 : if (is_##TPE1##_nil(v)) { \
2285 : rb[k] = TPE2##_nil; \
2286 : has_nils = true; \
2287 : } else { \
2288 : rb[k] = (TPE2) v; \
2289 : } \
2290 : } \
2291 : } while (0)
2292 :
2293 : #define COMPUTE_LEVELN_PROD_FP(VAL, NOTHING1, TPE2, NOTHING2) \
2294 : do { \
2295 : if (!is_##TPE2##_nil(VAL)) { \
2296 : if (is_##TPE2##_nil(computed)) { \
2297 : computed = VAL; \
2298 : } else if (ABSOLUTE(computed) > 1 && GDK_##TPE2##_max / ABSOLUTE(VAL) < ABSOLUTE(computed)) { \
2299 : goto calc_overflow; \
2300 : } else { \
2301 : computed *= VAL; \
2302 : } \
2303 : } \
2304 : } while (0)
2305 : #define ANALYTICAL_PROD_CALC_FP_OTHERS(TPE1, TPE2, ARG3) /* ARG3 is ignored here */ \
2306 : do { \
2307 : oid ncount = i - k; \
2308 : if ((res = GDKrebuild_segment_tree(ncount, sizeof(TPE2), st, &segment_tree, &levels_offset, &nlevels)) != GDK_SUCCEED) \
2309 : goto cleanup; \
2310 : populate_segment_tree(TPE2, ncount, INIT_AGGREGATE_PROD, COMPUTE_LEVEL0_PROD, COMPUTE_LEVELN_PROD_FP, TPE1, TPE2, ARG3); \
2311 : for (; k < i; k++) \
2312 : compute_on_segment_tree(TPE2, start[k] - j, end[k] - j, INIT_AGGREGATE_PROD, COMPUTE_LEVELN_PROD_FP, FINALIZE_AGGREGATE_PROD, TPE1, TPE2, ARG3); \
2313 : j = k; \
2314 : } while (0)
2315 :
2316 : #define ANALYTICAL_PROD_CALC_NUM_PARTITIONS(TPE1, TPE2, TPE3_OR_REAL_IMP, IMP) \
2317 : do { \
2318 : TPE1 *restrict bp = (TPE1*)bi.base; \
2319 : TPE2 *rb = (TPE2*)Tloc(r, 0); \
2320 : if (p) { \
2321 : while (i < cnt) { \
2322 : if (np[i]) { \
2323 : prod##TPE1##TPE2##IMP: \
2324 : IMP(TPE1, TPE2, TPE3_OR_REAL_IMP); \
2325 : } \
2326 : if (!last) \
2327 : i++; \
2328 : } \
2329 : } \
2330 : if (!last) { \
2331 : last = true; \
2332 : i = cnt; \
2333 : goto prod##TPE1##TPE2##IMP; \
2334 : } \
2335 : } while (0)
2336 :
2337 : #ifdef HAVE_HGE
2338 : #define ANALYTICAL_PROD_LIMIT(IMP) \
2339 : case TYPE_lng:{ \
2340 : switch (tp1) { \
2341 : case TYPE_bte: \
2342 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(bte, lng, hge, ANALYTICAL_PROD_CALC_NUM_##IMP); \
2343 : break; \
2344 : case TYPE_sht: \
2345 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(sht, lng, hge, ANALYTICAL_PROD_CALC_NUM_##IMP); \
2346 : break; \
2347 : case TYPE_int: \
2348 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(int, lng, hge, ANALYTICAL_PROD_CALC_NUM_##IMP); \
2349 : break; \
2350 : case TYPE_lng: \
2351 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(lng, lng, hge, ANALYTICAL_PROD_CALC_NUM_##IMP); \
2352 : break; \
2353 : default: \
2354 : goto nosupport; \
2355 : } \
2356 : break; \
2357 : } \
2358 : case TYPE_hge:{ \
2359 : switch (tp1) { \
2360 : case TYPE_bte: \
2361 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(bte, hge, HGEMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
2362 : break; \
2363 : case TYPE_sht: \
2364 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(sht, hge, HGEMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
2365 : break; \
2366 : case TYPE_int: \
2367 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(int, hge, HGEMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
2368 : break; \
2369 : case TYPE_lng: \
2370 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(lng, hge, HGEMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
2371 : break; \
2372 : case TYPE_hge: \
2373 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(hge, hge, HGEMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
2374 : break; \
2375 : default: \
2376 : goto nosupport; \
2377 : } \
2378 : break; \
2379 : }
2380 : #else
2381 : #define ANALYTICAL_PROD_LIMIT(IMP) \
2382 : case TYPE_lng:{ \
2383 : switch (tp1) { \
2384 : case TYPE_bte: \
2385 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(bte, lng, LNGMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
2386 : break; \
2387 : case TYPE_sht: \
2388 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(sht, lng, LNGMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
2389 : break; \
2390 : case TYPE_int: \
2391 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(int, lng, LNGMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
2392 : break; \
2393 : case TYPE_lng: \
2394 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(lng, lng, LNGMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
2395 : break; \
2396 : default: \
2397 : goto nosupport; \
2398 : } \
2399 : break; \
2400 : }
2401 : #endif
2402 :
2403 : #define ANALYTICAL_PROD_BRANCHES(IMP) \
2404 : do { \
2405 : switch (tp2) { \
2406 : case TYPE_bte:{ \
2407 : switch (tp1) { \
2408 : case TYPE_bte: \
2409 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(bte, bte, sht, ANALYTICAL_PROD_CALC_NUM_##IMP); \
2410 : break; \
2411 : default: \
2412 : goto nosupport; \
2413 : } \
2414 : break; \
2415 : } \
2416 : case TYPE_sht:{ \
2417 : switch (tp1) { \
2418 : case TYPE_bte: \
2419 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(bte, sht, int, ANALYTICAL_PROD_CALC_NUM_##IMP); \
2420 : break; \
2421 : case TYPE_sht: \
2422 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(sht, sht, int, ANALYTICAL_PROD_CALC_NUM_##IMP); \
2423 : break; \
2424 : default: \
2425 : goto nosupport; \
2426 : } \
2427 : break; \
2428 : } \
2429 : case TYPE_int:{ \
2430 : switch (tp1) { \
2431 : case TYPE_bte: \
2432 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(bte, int, lng, ANALYTICAL_PROD_CALC_NUM_##IMP); \
2433 : break; \
2434 : case TYPE_sht: \
2435 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(sht, int, lng, ANALYTICAL_PROD_CALC_NUM_##IMP); \
2436 : break; \
2437 : case TYPE_int: \
2438 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(int, int, lng, ANALYTICAL_PROD_CALC_NUM_##IMP); \
2439 : break; \
2440 : default: \
2441 : goto nosupport; \
2442 : } \
2443 : break; \
2444 : } \
2445 : ANALYTICAL_PROD_LIMIT(IMP) \
2446 : case TYPE_flt:{ \
2447 : switch (tp1) { \
2448 : case TYPE_flt: \
2449 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(flt, flt, ;, ANALYTICAL_PROD_CALC_FP_##IMP); \
2450 : break; \
2451 : default: \
2452 : goto nosupport; \
2453 : } \
2454 : break; \
2455 : } \
2456 : case TYPE_dbl:{ \
2457 : switch (tp1) { \
2458 : case TYPE_flt: \
2459 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(flt, dbl, ;, ANALYTICAL_PROD_CALC_FP_##IMP); \
2460 : break; \
2461 : case TYPE_dbl: \
2462 : ANALYTICAL_PROD_CALC_NUM_PARTITIONS(dbl, dbl, ;, ANALYTICAL_PROD_CALC_FP_##IMP); \
2463 : break; \
2464 : default: \
2465 : goto nosupport; \
2466 : } \
2467 : break; \
2468 : } \
2469 : default: \
2470 : goto nosupport; \
2471 : } \
2472 : } while (0)
2473 :
2474 : gdk_return
2475 31 : GDKanalyticalprod(BAT *r, BAT *p, BAT *o, BAT *b, BAT *s, BAT *e, int tp1, int tp2, int frame_type)
2476 : {
2477 31 : BATiter pi = bat_iterator(p);
2478 31 : BATiter oi = bat_iterator(o);
2479 31 : BATiter bi = bat_iterator(b);
2480 31 : BATiter si = bat_iterator(s);
2481 31 : BATiter ei = bat_iterator(e);
2482 31 : bool has_nils = false, last = false;
2483 31 : oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b), *restrict start = si.base, *restrict end = ei.base,
2484 31 : *levels_offset = NULL, nlevels = 0;
2485 31 : bit *np = pi.base, *op = oi.base;
2486 31 : void *segment_tree = NULL;
2487 31 : gdk_return res = GDK_SUCCEED;
2488 31 : BAT *st = NULL;
2489 :
2490 31 : if (cnt > 0) {
2491 31 : switch (frame_type) {
2492 12 : case 3: /* unbounded until current row */
2493 403 : ANALYTICAL_PROD_BRANCHES(UNBOUNDED_TILL_CURRENT_ROW);
2494 : break;
2495 0 : case 4: /* current row until unbounded */
2496 0 : ANALYTICAL_PROD_BRANCHES(CURRENT_ROW_TILL_UNBOUNDED);
2497 : break;
2498 7 : case 5: /* all rows */
2499 191 : ANALYTICAL_PROD_BRANCHES(ALL_ROWS);
2500 : break;
2501 0 : case 6: /* current row */
2502 0 : ANALYTICAL_PROD_BRANCHES(CURRENT_ROW);
2503 : break;
2504 12 : default:
2505 12 : if ((st = GDKinitialize_segment_tree()) == NULL) {
2506 0 : res = GDK_FAIL;
2507 0 : goto cleanup;
2508 : }
2509 956 : ANALYTICAL_PROD_BRANCHES(OTHERS);
2510 : break;
2511 : }
2512 : }
2513 :
2514 31 : BATsetcount(r, cnt);
2515 31 : r->tnonil = !has_nils;
2516 31 : r->tnil = has_nils;
2517 31 : goto cleanup; /* all these gotos seem confusing but it cleans up the ending of the operator */
2518 0 : calc_overflow:
2519 0 : GDKerror("22003!overflow in calculation.\n");
2520 0 : res = GDK_FAIL;
2521 31 : cleanup:
2522 31 : bat_iterator_end(&pi);
2523 31 : bat_iterator_end(&oi);
2524 31 : bat_iterator_end(&bi);
2525 31 : bat_iterator_end(&si);
2526 31 : bat_iterator_end(&ei);
2527 31 : BBPreclaim(st);
2528 31 : return res;
2529 0 : nosupport:
2530 0 : GDKerror("42000!type combination (prod(%s)->%s) not supported.\n", ATOMname(tp1), ATOMname(tp2));
2531 0 : res = GDK_FAIL;
2532 0 : goto cleanup;
2533 : }
|