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