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_time.h"
17 : #include "gdk_calc_private.h"
18 :
19 : #define ANALYTICAL_DIFF_IMP(TPE) \
20 : do { \
21 : const TPE *restrict bp = (TPE*)bi.base; \
22 : TPE prev = bp[0]; \
23 : if (np) { \
24 : for (; i < cnt; i++) { \
25 : TPE next = bp[i]; \
26 : if (next != prev) { \
27 : rb[i] = TRUE; \
28 : prev = next; \
29 : } else { \
30 : rb[i] = np[i]; \
31 : } \
32 : } \
33 : } else if (npbit) { \
34 : for (; i < cnt; i++) { \
35 : TPE next = bp[i]; \
36 : if (next != prev) { \
37 : rb[i] = TRUE; \
38 : prev = next; \
39 : } else { \
40 : rb[i] = npb; \
41 : } \
42 : } \
43 : } else { \
44 : for (; i < cnt; i++) { \
45 : TPE next = bp[i]; \
46 : if (next == prev) { \
47 : rb[i] = FALSE; \
48 : } else { \
49 : rb[i] = TRUE; \
50 : prev = next; \
51 : } \
52 : } \
53 : } \
54 : } while (0)
55 :
56 : /* We use NaN for floating point null values, which always output false on equality tests */
57 : #define ANALYTICAL_DIFF_FLOAT_IMP(TPE) \
58 : do { \
59 : const TPE *restrict bp = (TPE*)bi.base; \
60 : TPE prev = bp[0]; \
61 : if (np) { \
62 : for (; i < cnt; i++) { \
63 : TPE next = bp[i]; \
64 : if (next != prev && (!is_##TPE##_nil(next) || !is_##TPE##_nil(prev))) { \
65 : rb[i] = TRUE; \
66 : prev = next; \
67 : } else { \
68 : rb[i] = np[i]; \
69 : } \
70 : } \
71 : } else if (npbit) { \
72 : for (; i < cnt; i++) { \
73 : TPE next = bp[i]; \
74 : if (next != prev && (!is_##TPE##_nil(next) || !is_##TPE##_nil(prev))) { \
75 : rb[i] = TRUE; \
76 : prev = next; \
77 : } else { \
78 : rb[i] = npb; \
79 : } \
80 : } \
81 : } else { \
82 : for (; i < cnt; i++) { \
83 : TPE next = bp[i]; \
84 : if (next == prev || (is_##TPE##_nil(next) && is_##TPE##_nil(prev))) { \
85 : rb[i] = FALSE; \
86 : } else { \
87 : rb[i] = TRUE; \
88 : prev = next; \
89 : } \
90 : } \
91 : } \
92 : } while (0)
93 :
94 : BAT *
95 1914 : GDKanalyticaldiff(BAT *b, BAT *p, const bit *restrict npbit, int tpe)
96 : {
97 1914 : BUN i = 0, cnt = BATcount(b);
98 1914 : BATiter pi = bat_iterator(p);
99 1914 : BATiter bi = bat_iterator(b);
100 1914 : BAT *r = COLnew(b->hseqbase, TYPE_bit, BATcount(b), TRANSIENT);
101 1914 : if (r == NULL)
102 : return NULL;
103 1914 : bit *restrict rb = (bit *) Tloc(r, 0), npb = npbit ? *npbit : 0;
104 1914 : const bit *restrict np = (bit *) pi.base;
105 :
106 3755 : switch (ATOMbasetype(tpe)) {
107 231 : case TYPE_bte:
108 1765228 : ANALYTICAL_DIFF_IMP(bte);
109 : break;
110 413 : case TYPE_sht:
111 13682 : ANALYTICAL_DIFF_IMP(sht);
112 : break;
113 938 : case TYPE_int:
114 7509724 : ANALYTICAL_DIFF_IMP(int);
115 : break;
116 84 : case TYPE_lng:
117 301046 : ANALYTICAL_DIFF_IMP(lng);
118 : break;
119 : #ifdef HAVE_HGE
120 17 : case TYPE_hge:
121 302895 : ANALYTICAL_DIFF_IMP(hge);
122 : break;
123 : #endif
124 5 : case TYPE_flt:
125 5 : if (bi.nonil) {
126 0 : ANALYTICAL_DIFF_IMP(flt);
127 : } else { /* Because of NaN values, use this path */
128 55 : ANALYTICAL_DIFF_FLOAT_IMP(flt);
129 : }
130 : break;
131 23 : case TYPE_dbl:
132 23 : if (bi.nonil) {
133 246015 : ANALYTICAL_DIFF_IMP(dbl);
134 : } else { /* Because of NaN values, use this path */
135 709 : ANALYTICAL_DIFF_FLOAT_IMP(dbl);
136 : }
137 : break;
138 203 : default:{
139 203 : const void *v = BUNtail(bi, 0), *next;
140 203 : int (*atomcmp) (const void *, const void *) = ATOMcompare(tpe);
141 203 : if (np) {
142 777342 : for (i = 0; i < cnt; i++) {
143 777278 : rb[i] = np[i];
144 777278 : next = BUNtail(bi, i);
145 777278 : if (atomcmp(v, next) != 0) {
146 265636 : rb[i] = TRUE;
147 265636 : v = next;
148 : }
149 : }
150 139 : } else if (npbit) {
151 0 : for (i = 0; i < cnt; i++) {
152 0 : rb[i] = npb;
153 0 : next = BUNtail(bi, i);
154 0 : if (atomcmp(v, next) != 0) {
155 0 : rb[i] = TRUE;
156 0 : v = next;
157 : }
158 : }
159 : } else {
160 1053457 : for (i = 0; i < cnt; i++) {
161 1053318 : next = BUNtail(bi, i);
162 1053318 : if (atomcmp(v, next) != 0) {
163 785 : rb[i] = TRUE;
164 785 : v = next;
165 : } else {
166 1052533 : rb[i] = FALSE;
167 : }
168 : }
169 : }
170 : }
171 : }
172 1914 : bat_iterator_end(&bi);
173 1914 : bat_iterator_end(&pi);
174 1914 : BATsetcount(r, cnt);
175 1914 : r->tnonil = true;
176 1914 : r->tnil = false;
177 1914 : return r;
178 : }
179 :
180 : #define ANALYTICAL_WINDOW_BOUNDS_ROWS_PRECEDING(TPE, LIMIT, UPCAST) \
181 : do { \
182 : j = k; \
183 : for (; k < i; k++) { \
184 : TPE olimit = LIMIT; \
185 : if (is_##TPE##_nil(olimit) || olimit < 0) \
186 : goto invalid_bound; \
187 : oid rlimit = UPCAST; \
188 : rb[k] = rlimit > k - j ? j : k - rlimit + second_half; \
189 : } \
190 : } while (0)
191 :
192 : #define ANALYTICAL_WINDOW_BOUNDS_ROWS_FOLLOWING(TPE, LIMIT, UPCAST) \
193 : do { \
194 : for (; k < i; k++) { \
195 : TPE olimit = LIMIT; \
196 : if (is_##TPE##_nil(olimit) || olimit < 0) \
197 : goto invalid_bound; \
198 : oid rlimit = UPCAST + second_half; \
199 : rb[k] = rlimit > i - k ? i : k + rlimit; \
200 : } \
201 : } while (0)
202 :
203 : #define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(IMP, CARD, TPE, LIMIT, UPCAST) \
204 : do { \
205 : if (p) { \
206 : for (; i < cnt; i++) { \
207 : if (np[i]) { \
208 : rows##TPE##IMP##CARD: \
209 : ANALYTICAL_WINDOW_BOUNDS_ROWS##IMP(TPE, LIMIT, UPCAST); \
210 : } \
211 : } \
212 : } \
213 : if (!last) { \
214 : last = true; \
215 : i = cnt; \
216 : goto rows##TPE##IMP##CARD; \
217 : } \
218 : } while (0)
219 :
220 : #define ANALYTICAL_WINDOW_BOUNDS_GROUPS_PRECEDING(TPE, LIMIT, UPCAST) \
221 : do { \
222 : oid m = k; \
223 : for (; k < i; k++) { \
224 : TPE olimit = LIMIT; \
225 : if (is_##TPE##_nil(olimit) || olimit < 0) \
226 : goto invalid_bound; \
227 : oid rlimit = UPCAST; \
228 : for (j = k; ; j--) { \
229 : if (bp[j]) { \
230 : if (rlimit == 0) \
231 : break; \
232 : rlimit--; \
233 : } \
234 : if (j == m) \
235 : break; \
236 : } \
237 : rb[k] = j; \
238 : } \
239 : } while (0)
240 :
241 : #define ANALYTICAL_WINDOW_BOUNDS_GROUPS_FOLLOWING(TPE, LIMIT, UPCAST) \
242 : do { \
243 : for (; k < i; k++) { \
244 : TPE olimit = LIMIT; \
245 : if (is_##TPE##_nil(olimit) || olimit < 0) \
246 : goto invalid_bound; \
247 : oid rlimit = UPCAST; \
248 : for (j = k + 1; j < i; j++) { \
249 : if (bp[j]) { \
250 : if (rlimit == 0) \
251 : break; \
252 : rlimit--; \
253 : } \
254 : } \
255 : rb[k] = j; \
256 : } \
257 : } while (0)
258 :
259 : #define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(IMP, CARD, TPE, LIMIT, UPCAST) \
260 : do { \
261 : if (p) { \
262 : for (; i < cnt; i++) { \
263 : if (np[i]) { \
264 : groups##TPE##IMP##CARD: \
265 : ANALYTICAL_WINDOW_BOUNDS_GROUPS##IMP(TPE, LIMIT, UPCAST); \
266 : } \
267 : } \
268 : } \
269 : if (!last) { \
270 : last = true; \
271 : i = cnt; \
272 : goto groups##TPE##IMP##CARD; \
273 : } \
274 : } while (0)
275 :
276 : #define ANALYTICAL_WINDOW_BOUNDS_RANGE_PRECEDING(TPE1, LIMIT, TPE2) \
277 : do { \
278 : oid m = k; \
279 : TPE1 v, calc; \
280 : if (bi.nonil) { \
281 : for (; k < i; k++) { \
282 : TPE2 olimit = LIMIT; \
283 : if (is_##TPE2##_nil(olimit) || olimit < 0) \
284 : goto invalid_bound; \
285 : v = bp[k]; \
286 : for (j = k; ; j--) { \
287 : SUB_WITH_CHECK(v, bp[j], TPE1, calc, GDK_##TPE1##_max, goto calc_overflow); \
288 : if (ABSOLUTE(calc) > olimit) { \
289 : j++; \
290 : break; \
291 : } \
292 : if (j == m) \
293 : break; \
294 : } \
295 : rb[k] = j; \
296 : } \
297 : } else { \
298 : for (; k < i; k++) { \
299 : TPE2 olimit = LIMIT; \
300 : if (is_##TPE2##_nil(olimit) || olimit < 0) \
301 : goto invalid_bound; \
302 : v = bp[k]; \
303 : if (is_##TPE1##_nil(v)) { \
304 : for (j = k; ; j--) { \
305 : if (!is_##TPE1##_nil(bp[j])) { \
306 : j++; \
307 : break; \
308 : } \
309 : if (j == m) \
310 : break; \
311 : } \
312 : rb[k] = j; \
313 : } else { \
314 : for (j = k; ; j--) { \
315 : if (is_##TPE1##_nil(bp[j])) { \
316 : j++; \
317 : break; \
318 : } \
319 : SUB_WITH_CHECK(v, bp[j], TPE1, calc, GDK_##TPE1##_max, goto calc_overflow); \
320 : if (ABSOLUTE(calc) > olimit) { \
321 : j++; \
322 : break; \
323 : } \
324 : if (j == m) \
325 : break; \
326 : } \
327 : rb[k] = j; \
328 : } \
329 : } \
330 : } \
331 : } while (0)
332 :
333 : #define ANALYTICAL_WINDOW_BOUNDS_RANGE_FOLLOWING(TPE1, LIMIT, TPE2) \
334 : do { \
335 : TPE1 v, calc; \
336 : if (bi.nonil) { \
337 : for (; k < i; k++) { \
338 : TPE2 olimit = LIMIT; \
339 : if (is_##TPE2##_nil(olimit) || olimit < 0) \
340 : goto invalid_bound; \
341 : v = bp[k]; \
342 : for (j = k + 1; j < i; j++) { \
343 : SUB_WITH_CHECK(v, bp[j], TPE1, calc, GDK_##TPE1##_max, goto calc_overflow); \
344 : if (ABSOLUTE(calc) > olimit) \
345 : break; \
346 : } \
347 : rb[k] = j; \
348 : } \
349 : } else { \
350 : for (; k < i; k++) { \
351 : TPE2 olimit = LIMIT; \
352 : if (is_##TPE2##_nil(olimit) || olimit < 0) \
353 : goto invalid_bound; \
354 : v = bp[k]; \
355 : if (is_##TPE1##_nil(v)) { \
356 : for (j =k + 1; j < i; j++) { \
357 : if (!is_##TPE1##_nil(bp[j])) \
358 : break; \
359 : } \
360 : } else { \
361 : for (j = k + 1; j < i; j++) { \
362 : if (is_##TPE1##_nil(bp[j])) \
363 : break; \
364 : SUB_WITH_CHECK(v, bp[j], TPE1, calc, GDK_##TPE1##_max, goto calc_overflow); \
365 : if (ABSOLUTE(calc) > olimit) \
366 : break; \
367 : } \
368 : } \
369 : rb[k] = j; \
370 : } \
371 : } \
372 : } while (0)
373 :
374 : #define ANALYTICAL_WINDOW_BOUNDS_CALC_NUM(TPE1, IMP, CARD, LIMIT, TPE2) \
375 : do { \
376 : const TPE1 *restrict bp = (TPE1*)bi.base; \
377 : if (np) { \
378 : for (; i < cnt; i++) { \
379 : if (np[i]) { \
380 : range##TPE1##TPE2##IMP##CARD: \
381 : IMP(TPE1, LIMIT, TPE2); \
382 : } \
383 : } \
384 : } \
385 : if (!last) { \
386 : last = true; \
387 : i = cnt; \
388 : goto range##TPE1##TPE2##IMP##CARD; \
389 : } \
390 : } while (0)
391 :
392 : #define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(IMP, CARD, LIMIT, TPE2) \
393 : do { \
394 : switch (tp1) { \
395 : case TYPE_bte: \
396 : ANALYTICAL_WINDOW_BOUNDS_CALC_NUM(bte, ANALYTICAL_WINDOW_BOUNDS_RANGE##IMP, CARD, LIMIT, TPE2); \
397 : break; \
398 : case TYPE_sht: \
399 : ANALYTICAL_WINDOW_BOUNDS_CALC_NUM(sht, ANALYTICAL_WINDOW_BOUNDS_RANGE##IMP, CARD, LIMIT, TPE2); \
400 : break; \
401 : case TYPE_int: \
402 : ANALYTICAL_WINDOW_BOUNDS_CALC_NUM(int, ANALYTICAL_WINDOW_BOUNDS_RANGE##IMP, CARD, LIMIT, TPE2); \
403 : break; \
404 : case TYPE_lng: \
405 : ANALYTICAL_WINDOW_BOUNDS_CALC_NUM(lng, ANALYTICAL_WINDOW_BOUNDS_RANGE##IMP, CARD, LIMIT, TPE2); \
406 : break; \
407 : default: \
408 : goto type_not_supported; \
409 : } \
410 : } while (0)
411 :
412 : #define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_FLT(IMP, CARD, LIMIT) \
413 : do { \
414 : switch (tp1) { \
415 : case TYPE_flt: \
416 : ANALYTICAL_WINDOW_BOUNDS_CALC_NUM(flt, ANALYTICAL_WINDOW_BOUNDS_RANGE##IMP, CARD, LIMIT, flt); \
417 : break; \
418 : default: \
419 : goto type_not_supported; \
420 : } \
421 : } while (0)
422 :
423 : #define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_DBL(IMP, CARD, LIMIT) \
424 : do { \
425 : switch (tp1) { \
426 : case TYPE_dbl: \
427 : ANALYTICAL_WINDOW_BOUNDS_CALC_NUM(dbl, ANALYTICAL_WINDOW_BOUNDS_RANGE##IMP, CARD, LIMIT, dbl); \
428 : break; \
429 : default: \
430 : goto type_not_supported; \
431 : } \
432 : } while (0)
433 :
434 : #ifdef HAVE_HGE
435 : #define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_HGE(IMP, CARD, LIMIT) \
436 : do { \
437 : switch (tp1) { \
438 : case TYPE_bte: \
439 : ANALYTICAL_WINDOW_BOUNDS_CALC_NUM(bte, ANALYTICAL_WINDOW_BOUNDS_RANGE##IMP, CARD, LIMIT, hge); \
440 : break; \
441 : case TYPE_sht: \
442 : ANALYTICAL_WINDOW_BOUNDS_CALC_NUM(sht, ANALYTICAL_WINDOW_BOUNDS_RANGE##IMP, CARD, LIMIT, hge); \
443 : break; \
444 : case TYPE_int: \
445 : ANALYTICAL_WINDOW_BOUNDS_CALC_NUM(int, ANALYTICAL_WINDOW_BOUNDS_RANGE##IMP, CARD, LIMIT, hge); \
446 : break; \
447 : case TYPE_lng: \
448 : ANALYTICAL_WINDOW_BOUNDS_CALC_NUM(lng, ANALYTICAL_WINDOW_BOUNDS_RANGE##IMP, CARD, LIMIT, hge); \
449 : break; \
450 : case TYPE_hge: \
451 : ANALYTICAL_WINDOW_BOUNDS_CALC_NUM(hge, ANALYTICAL_WINDOW_BOUNDS_RANGE##IMP, CARD, LIMIT, hge); \
452 : break; \
453 : default: \
454 : goto type_not_supported; \
455 : } \
456 : } while (0)
457 : #endif
458 :
459 : #define date_sub_month(D,M) date_add_month(D,-(M))
460 : #define timestamp_sub_month(T,M) timestamp_add_month(T,-(M))
461 :
462 : #define daytime_add_msec(D,M) daytime_add_usec(D, 1000*(M))
463 : #define daytime_sub_msec(D,M) daytime_add_usec(D, -1000*(M))
464 : #define date_add_msec(D,M) date_add_day(D,(int) ((M)/(24*60*60*1000)))
465 : #define date_sub_msec(D,M) date_add_day(D,(int) (-(M)/(24*60*60*1000)))
466 : #define timestamp_add_msec(T,M) timestamp_add_usec(T, (M)*1000)
467 : #define timestamp_sub_msec(T,M) timestamp_add_usec(T, -(M)*1000)
468 :
469 : #define ANALYTICAL_WINDOW_BOUNDS_RANGE_MTIME_PRECEDING(TPE1, LIMIT, TPE2, SUB, ADD) \
470 : do { \
471 : oid m = k; \
472 : TPE1 v, vmin, vmax; \
473 : if (bi.nonil) { \
474 : for (; k < i; k++) { \
475 : TPE2 rlimit = LIMIT; \
476 : if (is_##TPE1##_nil(rlimit) || rlimit < 0) \
477 : goto invalid_bound; \
478 : v = bp[k]; \
479 : vmin = SUB(v, rlimit); \
480 : vmax = ADD(v, rlimit); \
481 : for (j=k; ; j--) { \
482 : if ((!is_##TPE1##_nil(vmin) && bp[j] < vmin) || (!is_##TPE1##_nil(vmax) && bp[j] > vmax)) { \
483 : j++; \
484 : break; \
485 : } \
486 : if (j == m) \
487 : break; \
488 : } \
489 : rb[k] = j; \
490 : } \
491 : } else { \
492 : for (; k < i; k++) { \
493 : TPE2 rlimit = LIMIT; \
494 : if (is_##TPE1##_nil(rlimit) || rlimit < 0) \
495 : goto invalid_bound; \
496 : v = bp[k]; \
497 : if (is_##TPE1##_nil(v)) { \
498 : for (j=k; ; j--) { \
499 : if (!is_##TPE1##_nil(bp[j])) { \
500 : j++; \
501 : break; \
502 : } \
503 : if (j == m) \
504 : break; \
505 : } \
506 : rb[k] = j; \
507 : } else { \
508 : vmin = SUB(v, rlimit); \
509 : vmax = ADD(v, rlimit); \
510 : for (j=k; ; j--) { \
511 : if (is_##TPE1##_nil(bp[j])) { \
512 : j++; \
513 : break; \
514 : } \
515 : if ((!is_##TPE1##_nil(vmin) && bp[j] < vmin) || (!is_##TPE1##_nil(vmax) && bp[j] > vmax)) { \
516 : j++; \
517 : break; \
518 : } \
519 : if (j == m) \
520 : break; \
521 : } \
522 : rb[k] = j; \
523 : } \
524 : } \
525 : } \
526 : } while(0)
527 :
528 : #define ANALYTICAL_WINDOW_BOUNDS_RANGE_MTIME_FOLLOWING(TPE1, LIMIT, TPE2, SUB, ADD) \
529 : do { \
530 : TPE1 v, vmin, vmax; \
531 : if (bi.nonil) { \
532 : for (; k < i; k++) { \
533 : TPE2 rlimit = LIMIT; \
534 : if (is_##TPE1##_nil(rlimit) || rlimit < 0) \
535 : goto invalid_bound; \
536 : v = bp[k]; \
537 : vmin = SUB(v, rlimit); \
538 : vmax = ADD(v, rlimit); \
539 : for (j=k+1; j<i; j++) \
540 : if ((!is_##TPE1##_nil(vmin) && bp[j] < vmin) || (!is_##TPE1##_nil(vmax) && bp[j] > vmax)) \
541 : break; \
542 : rb[k] = j; \
543 : } \
544 : } else { \
545 : for (; k < i; k++) { \
546 : TPE2 rlimit = LIMIT; \
547 : if (is_##TPE1##_nil(rlimit) || rlimit < 0) \
548 : goto invalid_bound; \
549 : v = bp[k]; \
550 : if (is_##TPE1##_nil(v)) { \
551 : for (j=k+1; j<i; j++) \
552 : if (!is_##TPE1##_nil(bp[j])) \
553 : break; \
554 : } else { \
555 : vmin = SUB(v, rlimit); \
556 : vmax = ADD(v, rlimit); \
557 : for (j=k+1; j<i; j++) { \
558 : if (is_##TPE1##_nil(bp[j]) || (!is_##TPE1##_nil(vmin) && bp[j] < vmin) || (!is_##TPE1##_nil(vmax) && bp[j] > vmax)) \
559 : break; \
560 : } \
561 : } \
562 : rb[k] = j; \
563 : } \
564 : } \
565 : } while(0)
566 :
567 : #define ANALYTICAL_WINDOW_BOUNDS_CALC_MTIME(TPE1, IMP, CARD, LIMIT, TPE2, SUB, ADD) \
568 : do { \
569 : const TPE1 *restrict bp = (TPE1*)bi.base; \
570 : if (p) { \
571 : for (; i < cnt; i++) { \
572 : if (np[i]) { \
573 : rangemtime##TPE1##TPE2##IMP##CARD: \
574 : IMP(TPE1, LIMIT, TPE2, SUB, ADD); \
575 : } \
576 : } \
577 : } \
578 : if (!last) { \
579 : last = true; \
580 : i = cnt; \
581 : goto rangemtime##TPE1##TPE2##IMP##CARD; \
582 : } \
583 : } while(0)
584 :
585 : #define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_MTIME_MONTH_INTERVAL(IMP, CARD, LIMIT) \
586 : do { \
587 : switch (tp1) { \
588 : case TYPE_date: \
589 : ANALYTICAL_WINDOW_BOUNDS_CALC_MTIME(date, ANALYTICAL_WINDOW_BOUNDS_RANGE_MTIME##IMP, CARD, LIMIT, int, date_sub_month, date_add_month); \
590 : break; \
591 : case TYPE_timestamp: \
592 : ANALYTICAL_WINDOW_BOUNDS_CALC_MTIME(timestamp, ANALYTICAL_WINDOW_BOUNDS_RANGE_MTIME##IMP, CARD, LIMIT, int, timestamp_sub_month, timestamp_add_month); \
593 : break; \
594 : default: \
595 : goto type_not_supported; \
596 : } \
597 : } while(0)
598 :
599 : #define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_MTIME_SEC_INTERVAL(IMP, CARD, LIMIT) \
600 : do { \
601 : switch (tp1) { \
602 : case TYPE_date: \
603 : ANALYTICAL_WINDOW_BOUNDS_CALC_MTIME(date, ANALYTICAL_WINDOW_BOUNDS_RANGE_MTIME##IMP, CARD, LIMIT, lng, date_sub_msec, date_add_msec); \
604 : break; \
605 : case TYPE_daytime: \
606 : ANALYTICAL_WINDOW_BOUNDS_CALC_MTIME(daytime, ANALYTICAL_WINDOW_BOUNDS_RANGE_MTIME##IMP, CARD, LIMIT, lng, daytime_sub_msec, daytime_add_msec); \
607 : break; \
608 : case TYPE_timestamp: \
609 : ANALYTICAL_WINDOW_BOUNDS_CALC_MTIME(timestamp, ANALYTICAL_WINDOW_BOUNDS_RANGE_MTIME##IMP, CARD, LIMIT, lng, timestamp_sub_msec, timestamp_add_msec); \
610 : break; \
611 : default: \
612 : goto type_not_supported; \
613 : } \
614 : } while(0)
615 :
616 : static BAT *
617 182 : GDKanalyticalallbounds(BAT *b, BAT *p, bool preceding)
618 : {
619 182 : BAT *r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT);
620 182 : if (r == NULL)
621 : return NULL;
622 182 : oid *restrict rb = (oid *) Tloc(r, 0), i = 0, k = 0, j = 0, cnt = BATcount(b);
623 182 : BATiter pi = bat_iterator(p);
624 182 : const bit *restrict np = pi.base;
625 :
626 182 : if (preceding) {
627 152 : if (np) {
628 2950692 : for (; i < cnt; i++) {
629 2950601 : if (np[i]) {
630 2144110 : j = k;
631 2144110 : for (; k < i; k++)
632 2104806 : rb[k] = j;
633 : }
634 : }
635 : }
636 152 : i = cnt;
637 152 : j = k;
638 846531 : for (; k < i; k++)
639 846379 : rb[k] = j;
640 : } else { /* following */
641 30 : if (np) {
642 43 : for (; i < cnt; i++) {
643 39 : if (np[i]) {
644 56 : for (; k < i; k++)
645 35 : rb[k] = i;
646 : }
647 : }
648 : }
649 268 : i = cnt;
650 268 : for (; k < i; k++)
651 238 : rb[k] = i;
652 : }
653 :
654 182 : bat_iterator_end(&pi);
655 182 : BATsetcount(r, cnt);
656 182 : r->tnonil = false;
657 182 : r->tnil = false;
658 182 : return r;
659 : }
660 :
661 : #define ANALYTICAL_WINDOW_BOUNDS_PEERS_FIXED_PRECEDING(TPE, NAN_CHECK) \
662 : do { \
663 : TPE prev = bp[k]; \
664 : l = j; \
665 : for (; k < i; k++) { \
666 : TPE next = bp[k]; \
667 : if (next != prev NAN_CHECK) { \
668 : for ( ; j < k ; j++) \
669 : rb[j] = l; \
670 : l = j; \
671 : prev = next; \
672 : } \
673 : } \
674 : for ( ; j < k ; j++) \
675 : rb[j] = l; \
676 : } while (0)
677 :
678 : #define ANALYTICAL_WINDOW_BOUNDS_PEERS_FIXED_FOLLOWING(TPE, NAN_CHECK) \
679 : do { \
680 : TPE prev = bp[k]; \
681 : for (; k < i; k++) { \
682 : TPE next = bp[k]; \
683 : if (next != prev NAN_CHECK) { \
684 : l += k - j; \
685 : for ( ; j < k ; j++) \
686 : rb[j] = l; \
687 : prev = next; \
688 : } \
689 : } \
690 : l += k - j; \
691 : for ( ; j < k ; j++) \
692 : rb[j] = l; \
693 : } while (0)
694 :
695 : #define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(IMP, TPE, NAN_CHECK) \
696 : do { \
697 : const TPE *restrict bp = (TPE*)bi.base; \
698 : if (p) { \
699 : for (; i < cnt; i++) { \
700 : if (np[i]) { \
701 : peers##TPE##IMP: \
702 : ANALYTICAL_WINDOW_BOUNDS_PEERS_FIXED##IMP(TPE, NAN_CHECK); \
703 : } \
704 : } \
705 : } \
706 : if (!last) { \
707 : last = true; \
708 : i = cnt; \
709 : goto peers##TPE##IMP; \
710 : } \
711 : } while (0)
712 :
713 : #define NO_NAN_CHECK /* nulls match on this operator */
714 :
715 : static BAT *
716 109 : GDKanalyticalpeers(BAT *b, BAT *p, bool preceding) /* used in range when the limit is 0, ie match peer rows */
717 : {
718 109 : BAT *r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT);
719 109 : if (r == NULL)
720 : return NULL;
721 109 : oid *restrict rb = (oid *) Tloc(r, 0), i = 0, k = 0, j = 0, l = 0, cnt = BATcount(b);
722 109 : BATiter pi = bat_iterator(p);
723 109 : BATiter bi = bat_iterator(b);
724 109 : const bit *restrict np = pi.base;
725 109 : bool last = false;
726 :
727 190 : switch (ATOMbasetype(bi.type)) {
728 1 : case TYPE_bte:
729 1 : if (preceding) {
730 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_PRECEDING, bte, NO_NAN_CHECK);
731 : } else {
732 6 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_FOLLOWING, bte, NO_NAN_CHECK);
733 : }
734 : break;
735 0 : case TYPE_sht:
736 0 : if (preceding) {
737 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_PRECEDING, sht, NO_NAN_CHECK);
738 : } else {
739 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_FOLLOWING, sht, NO_NAN_CHECK);
740 : }
741 : break;
742 68 : case TYPE_int:
743 68 : if (preceding) {
744 80 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_PRECEDING, int, NO_NAN_CHECK);
745 : } else {
746 2538022 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_FOLLOWING, int, NO_NAN_CHECK);
747 : }
748 : break;
749 19 : case TYPE_lng:
750 19 : if (preceding) {
751 96 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_PRECEDING, lng, NO_NAN_CHECK);
752 : } else {
753 281 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_FOLLOWING, lng, NO_NAN_CHECK);
754 : }
755 : break;
756 : #ifdef HAVE_HGE
757 0 : case TYPE_hge:
758 0 : if (preceding) {
759 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_PRECEDING, hge, NO_NAN_CHECK);
760 : } else {
761 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_FOLLOWING, hge, NO_NAN_CHECK);
762 : }
763 : break;
764 : #endif
765 0 : case TYPE_flt:
766 0 : if (preceding) {
767 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_PRECEDING, flt, && (!is_flt_nil(next) || !is_flt_nil(prev)));
768 : } else {
769 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_FOLLOWING, flt, && (!is_flt_nil(next) || !is_flt_nil(prev)));
770 : }
771 : break;
772 0 : case TYPE_dbl:
773 0 : if (preceding) {
774 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_PRECEDING, dbl, && (!is_dbl_nil(next) || !is_dbl_nil(prev)));
775 : } else {
776 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_PEERS(_FOLLOWING, dbl, && (!is_dbl_nil(next) || !is_dbl_nil(prev)));
777 : }
778 : break;
779 21 : default: {
780 21 : const void *prev, *next;
781 21 : int (*atomcmp) (const void *, const void *) = ATOMcompare(bi.type);
782 :
783 21 : if (preceding) {
784 0 : if (p) {
785 0 : for (; i < cnt; i++) {
786 0 : if (np[i]) {
787 0 : prev = BUNtail(bi, k);
788 : l = j;
789 0 : for (; k < i; k++) {
790 0 : next = BUNtail(bi, k);
791 0 : if (atomcmp(prev, next) != 0) {
792 0 : for ( ; j < k ; j++)
793 0 : rb[j] = l;
794 : l = j;
795 : prev = next;
796 : }
797 : }
798 0 : for ( ; j < k ; j++)
799 0 : rb[j] = l;
800 : }
801 : }
802 : }
803 0 : i = cnt;
804 0 : prev = BUNtail(bi, k);
805 : l = j;
806 0 : for (; k < i; k++) {
807 0 : next = BUNtail(bi, k);
808 0 : if (atomcmp(prev, next) != 0) {
809 0 : for ( ; j < k ; j++)
810 0 : rb[j] = l;
811 : l = j;
812 : prev = next;
813 : }
814 : }
815 0 : for ( ; j < k ; j++)
816 0 : rb[j] = l;
817 : } else {
818 21 : if (p) {
819 245822 : for (; i < cnt; i++) {
820 245808 : if (np[i]) {
821 38 : prev = BUNtail(bi, k);
822 245830 : for (; k < i; k++) {
823 245792 : next = BUNtail(bi, k);
824 245792 : if (atomcmp(prev, next) != 0) {
825 245058 : l += k - j;
826 490812 : for ( ; j < k ; j++)
827 245754 : rb[j] = l;
828 : prev = next;
829 : }
830 : }
831 38 : l += k - j;
832 76 : for ( ; j < k ; j++)
833 38 : rb[j] = l;
834 : }
835 : }
836 : }
837 21 : i = cnt;
838 21 : prev = BUNtail(bi, k);
839 100 : for (; k < i; k++) {
840 79 : next = BUNtail(bi, k);
841 79 : if (atomcmp(prev, next) != 0) {
842 56 : l += k - j;
843 112 : for ( ; j < k ; j++)
844 56 : rb[j] = l;
845 : prev = next;
846 : }
847 : }
848 21 : l += k - j;
849 44 : for ( ; j < k ; j++)
850 23 : rb[j] = l;
851 : }
852 : }
853 : }
854 :
855 109 : bat_iterator_end(&pi);
856 109 : bat_iterator_end(&bi);
857 109 : BATsetcount(r, cnt);
858 109 : r->tnonil = false;
859 109 : r->tnil = false;
860 109 : return r;
861 : }
862 :
863 : static BAT *
864 423 : GDKanalyticalrowbounds(BAT *b, BAT *p, BAT *l, const void *restrict bound, int tp2, bool preceding, oid second_half)
865 : {
866 423 : oid cnt = BATcount(b), nils = 0, i = 0, k = 0, j = 0;
867 423 : BATiter pi = bat_iterator(p);
868 423 : BATiter bi = bat_iterator(b);
869 423 : BATiter li = bat_iterator(l);
870 423 : const bit *restrict np = pi.base;
871 423 : bool last = false;
872 423 : BAT *r = NULL;
873 :
874 423 : if (l) { /* dynamic bounds */
875 14 : if (li.nil)
876 4 : goto invalid_bound;
877 10 : r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT);
878 10 : if (r == NULL)
879 : return NULL;
880 10 : oid *restrict rb = (oid *) Tloc(r, 0);
881 10 : switch (tp2) {
882 0 : case TYPE_bte:{
883 0 : const bte *restrict limit = (bte *) li.base;
884 0 : if (preceding) {
885 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, MULTI, bte, limit[k], (oid) olimit);
886 : } else {
887 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, MULTI, bte, limit[k], (oid) olimit);
888 : }
889 : break;
890 : }
891 0 : case TYPE_sht:{
892 0 : const sht *restrict limit = (sht *) li.base;
893 0 : if (preceding) {
894 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, MULTI, sht, limit[k], (oid) olimit);
895 : } else {
896 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, MULTI, sht, limit[k], (oid) olimit);
897 : }
898 : break;
899 : }
900 4 : case TYPE_int:{
901 4 : const int *restrict limit = (int *) li.base;
902 4 : if (preceding) {
903 48 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, MULTI, int, limit[k], (oid) olimit);
904 : } else {
905 16 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, MULTI, int, limit[k], (oid) olimit);
906 : }
907 : break;
908 : }
909 6 : case TYPE_lng:{
910 6 : const lng *restrict limit = (lng *) li.base;
911 6 : if (preceding) {
912 : #if SIZEOF_OID == SIZEOF_INT
913 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, MULTI, lng, limit[k], (olimit > (lng) GDK_oid_max) ? GDK_oid_max : (oid) olimit);
914 : #else
915 72 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, MULTI, lng, limit[k], (oid) olimit);
916 : #endif
917 : } else {
918 : #if SIZEOF_OID == SIZEOF_INT
919 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, MULTI, lng, limit[k], (olimit > (lng) GDK_oid_max) ? GDK_oid_max : (oid) olimit);
920 : #else
921 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, MULTI, lng, limit[k], (oid) olimit);
922 : #endif
923 : }
924 : break;
925 : }
926 : #ifdef HAVE_HGE
927 0 : case TYPE_hge:{
928 0 : const hge *restrict limit = (hge *) li.base;
929 0 : if (preceding) {
930 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, MULTI, hge, limit[k], (olimit > (hge) GDK_oid_max) ? GDK_oid_max : (oid) olimit);
931 : } else {
932 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, MULTI, hge, limit[k], (olimit > (hge) GDK_oid_max) ? GDK_oid_max : (oid) olimit);
933 : }
934 : break;
935 : }
936 : #endif
937 : default:
938 0 : goto bound_not_supported;
939 : }
940 : } else { /* static bounds, all the limits are cast to the word size */
941 409 : lng limit;
942 409 : switch (tp2) {
943 259 : case TYPE_bte:
944 259 : limit = is_bte_nil(*(bte *) bound) ? lng_nil : (lng) *(bte *) bound;
945 0 : break;
946 0 : case TYPE_sht:
947 0 : limit = is_sht_nil(*(sht *) bound) ? lng_nil : (lng) *(sht *) bound;
948 0 : break;
949 0 : case TYPE_int:
950 0 : limit = is_int_nil(*(int *) bound) ? lng_nil : (lng) *(int *) bound;
951 0 : break;
952 150 : case TYPE_lng: {
953 : #if SIZEOF_OID == SIZEOF_INT
954 : lng nval = *(lng *) bound;
955 : limit = is_lng_nil(nval) ? lng_nil : (nval > (lng) GDK_oid_max) ? GDK_lng_max : (lng) nval;
956 : #else
957 150 : limit = (lng) (*(lng *) bound);
958 : #endif
959 150 : break;
960 : }
961 : #ifdef HAVE_HGE
962 0 : case TYPE_hge: {
963 0 : hge nval = *(hge *) bound;
964 0 : limit = is_hge_nil(nval) ? lng_nil : (nval > (hge) GDK_lng_max) ? GDK_lng_max : (lng) nval;
965 : break;
966 : }
967 : #endif
968 0 : default:
969 0 : goto bound_not_supported;
970 : }
971 409 : if (limit == GDK_lng_max) {
972 57 : bat_iterator_end(&pi);
973 57 : bat_iterator_end(&bi);
974 57 : bat_iterator_end(&li);
975 57 : return GDKanalyticalallbounds(b, p, preceding);
976 : }
977 352 : if (is_lng_nil(limit) || limit < 0) { /* this check is needed if the input is empty */
978 1 : goto invalid_bound;
979 : }
980 351 : r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT);
981 351 : if (r == NULL)
982 : return NULL;
983 351 : oid *restrict rb = (oid *) Tloc(r, 0);
984 351 : if (preceding) {
985 9709 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, SINGLE, lng, limit, (oid) olimit);
986 : } else {
987 3724331 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, SINGLE, lng, limit, (oid) olimit);
988 : }
989 : }
990 :
991 359 : bat_iterator_end(&pi);
992 359 : bat_iterator_end(&bi);
993 359 : bat_iterator_end(&li);
994 359 : BATsetcount(r, cnt);
995 359 : r->tnonil = (nils == 0);
996 359 : r->tnil = (nils > 0);
997 359 : return r;
998 : bound_not_supported:
999 0 : BBPreclaim(r);
1000 0 : bat_iterator_end(&pi);
1001 0 : bat_iterator_end(&bi);
1002 0 : bat_iterator_end(&li);
1003 0 : GDKerror("42000!rows frame bound type %s not supported.\n", ATOMname(tp2));
1004 0 : return NULL;
1005 2 : invalid_bound:
1006 7 : BBPreclaim(r);
1007 7 : bat_iterator_end(&pi);
1008 7 : bat_iterator_end(&bi);
1009 7 : bat_iterator_end(&li);
1010 7 : GDKerror("42000!row frame bound must be non negative and non null.\n");
1011 7 : return NULL;
1012 : }
1013 :
1014 : static BAT *
1015 274 : GDKanalyticalrangebounds(BAT *b, BAT *p, BAT *l, const void *restrict bound, int tp1, int tp2, bool preceding)
1016 : {
1017 274 : oid cnt = BATcount(b), nils = 0, i = 0, k = 0, j = 0;
1018 274 : BATiter pi = bat_iterator(p);
1019 274 : BATiter bi = bat_iterator(b);
1020 274 : BATiter li = bat_iterator(l);
1021 274 : const bit *restrict np = pi.base;
1022 274 : bool last = false;
1023 274 : BAT *r = NULL;
1024 :
1025 274 : if ((tp1 == TYPE_daytime || tp1 == TYPE_date || tp1 == TYPE_timestamp) && tp2 != TYPE_int && tp2 != TYPE_lng)
1026 0 : goto bound_not_supported;
1027 :
1028 274 : if (l) { /* dynamic bounds */
1029 0 : if (li.nil)
1030 0 : goto invalid_bound;
1031 0 : r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT);
1032 0 : if (r == NULL)
1033 : return NULL;
1034 0 : oid *restrict rb = (oid *) Tloc(r, 0);
1035 0 : switch (tp2) {
1036 0 : case TYPE_bte:{
1037 0 : const bte *restrict limit = (bte *) li.base;
1038 0 : if (preceding) {
1039 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_PRECEDING, MULTI, limit[k], bte);
1040 : } else {
1041 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_FOLLOWING, MULTI, limit[k], bte);
1042 : }
1043 : break;
1044 : }
1045 0 : case TYPE_sht:{
1046 0 : const sht *restrict limit = (sht *) li.base;
1047 0 : if (preceding) {
1048 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_PRECEDING, MULTI, limit[k], sht);
1049 : } else {
1050 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_FOLLOWING, MULTI, limit[k], sht);
1051 : }
1052 : break;
1053 : }
1054 0 : case TYPE_int:{
1055 0 : const int *restrict limit = (int *) li.base;
1056 0 : if (tp1 == TYPE_daytime || tp1 == TYPE_date || tp1 == TYPE_timestamp) {
1057 0 : if (preceding) {
1058 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_MTIME_MONTH_INTERVAL(_PRECEDING, MULTI, limit[k]);
1059 : } else {
1060 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_MTIME_MONTH_INTERVAL(_FOLLOWING, MULTI, limit[k]);
1061 : }
1062 0 : } else if (preceding) {
1063 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_PRECEDING, MULTI, limit[k], int);
1064 : } else {
1065 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_FOLLOWING, MULTI, limit[k], int);
1066 : }
1067 : break;
1068 : }
1069 0 : case TYPE_lng:{
1070 0 : const lng *restrict limit = (lng *) li.base;
1071 0 : if (tp1 == TYPE_daytime || tp1 == TYPE_date || tp1 == TYPE_timestamp) {
1072 0 : if (preceding) {
1073 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_MTIME_SEC_INTERVAL(_PRECEDING, MULTI, limit[k]);
1074 : } else {
1075 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_MTIME_SEC_INTERVAL(_FOLLOWING, MULTI, limit[k]);
1076 : }
1077 0 : } else if (preceding) {
1078 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_PRECEDING, MULTI, limit[k], lng);
1079 : } else {
1080 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_FOLLOWING, MULTI, limit[k], lng);
1081 : }
1082 : break;
1083 : }
1084 0 : case TYPE_flt:{
1085 0 : const flt *restrict limit = (flt *) li.base;
1086 0 : if (preceding) {
1087 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_FLT(_PRECEDING, MULTI, limit[k]);
1088 : } else {
1089 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_FLT(_FOLLOWING, MULTI, limit[k]);
1090 : }
1091 : break;
1092 : }
1093 0 : case TYPE_dbl:{
1094 0 : const dbl *restrict limit = (dbl *) li.base;
1095 0 : if (preceding) {
1096 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_DBL(_PRECEDING, MULTI, limit[k]);
1097 : } else {
1098 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_DBL(_FOLLOWING, MULTI, limit[k]);
1099 : }
1100 : break;
1101 : }
1102 : #ifdef HAVE_HGE
1103 0 : case TYPE_hge:{
1104 0 : const hge *restrict limit = (hge *) li.base;
1105 0 : if (preceding) {
1106 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_HGE(_PRECEDING, MULTI, limit[k]);
1107 : } else {
1108 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_HGE(_FOLLOWING, MULTI, limit[k]);
1109 : }
1110 : break;
1111 : }
1112 : #endif
1113 : default:
1114 0 : goto bound_not_supported;
1115 : }
1116 : } else { /* static bounds */
1117 274 : switch (tp2) {
1118 274 : case TYPE_bte:
1119 : case TYPE_sht:
1120 : case TYPE_int:
1121 : case TYPE_lng:{
1122 274 : lng limit = 0;
1123 274 : int int_limit = 0;
1124 274 : switch (tp2) {
1125 20 : case TYPE_bte:{
1126 20 : bte ll = (*(bte *) bound);
1127 20 : if (ll == GDK_bte_max) { /* UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING cases, avoid overflow */
1128 18 : bat_iterator_end(&pi);
1129 18 : bat_iterator_end(&bi);
1130 18 : bat_iterator_end(&li);
1131 18 : return GDKanalyticalallbounds(b, p, preceding);
1132 : }
1133 2 : if (ll == 0) {
1134 1 : bat_iterator_end(&pi);
1135 1 : bat_iterator_end(&bi);
1136 1 : bat_iterator_end(&li);
1137 1 : return GDKanalyticalpeers(b, p, preceding);
1138 : }
1139 1 : limit = is_bte_nil(ll) ? lng_nil : (lng) ll;
1140 : break;
1141 : }
1142 2 : case TYPE_sht:{
1143 2 : sht ll = (*(sht *) bound);
1144 2 : if (ll == GDK_sht_max) {
1145 2 : bat_iterator_end(&pi);
1146 2 : bat_iterator_end(&bi);
1147 2 : bat_iterator_end(&li);
1148 2 : return GDKanalyticalallbounds(b, p, preceding);
1149 : }
1150 0 : if (ll == 0) {
1151 0 : bat_iterator_end(&pi);
1152 0 : bat_iterator_end(&bi);
1153 0 : bat_iterator_end(&li);
1154 0 : return GDKanalyticalpeers(b, p, preceding);
1155 : }
1156 0 : limit = is_sht_nil(ll) ? lng_nil : (lng) ll;
1157 : break;
1158 : }
1159 161 : case TYPE_int:{
1160 161 : int_limit = (*(int *) bound);
1161 161 : if (int_limit == GDK_int_max) {
1162 74 : bat_iterator_end(&pi);
1163 74 : bat_iterator_end(&bi);
1164 74 : bat_iterator_end(&li);
1165 74 : return GDKanalyticalallbounds(b, p, preceding);
1166 : }
1167 87 : if (int_limit == 0) {
1168 64 : bat_iterator_end(&pi);
1169 64 : bat_iterator_end(&bi);
1170 64 : bat_iterator_end(&li);
1171 64 : return GDKanalyticalpeers(b, p, preceding);
1172 : }
1173 23 : limit = is_int_nil(int_limit) ? lng_nil : (lng) int_limit;
1174 : break;
1175 : }
1176 91 : case TYPE_lng:{
1177 91 : limit = (*(lng *) bound);
1178 91 : if (limit == GDK_lng_max) {
1179 30 : bat_iterator_end(&pi);
1180 30 : bat_iterator_end(&bi);
1181 30 : bat_iterator_end(&li);
1182 30 : return GDKanalyticalallbounds(b, p, preceding);
1183 : }
1184 61 : if (limit == 0) {
1185 44 : bat_iterator_end(&pi);
1186 44 : bat_iterator_end(&bi);
1187 44 : bat_iterator_end(&li);
1188 44 : return GDKanalyticalpeers(b, p, preceding);
1189 : }
1190 : break;
1191 : }
1192 : default:
1193 0 : MT_UNREACHABLE();
1194 : }
1195 41 : if (is_lng_nil(limit) || limit < 0 || is_int_nil(int_limit) || int_limit < 0) {
1196 1 : goto invalid_bound;
1197 : }
1198 40 : r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT);
1199 40 : if (r == NULL)
1200 : return NULL;
1201 40 : oid *restrict rb = (oid *) Tloc(r, 0);
1202 40 : if (tp1 == TYPE_daytime || tp1 == TYPE_date || tp1 == TYPE_timestamp) {
1203 35 : if (tp2 == TYPE_int) {
1204 18 : if (preceding) {
1205 160 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_MTIME_MONTH_INTERVAL(_PRECEDING, SINGLE, int_limit);
1206 : } else {
1207 90 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_MTIME_MONTH_INTERVAL(_FOLLOWING, SINGLE, int_limit);
1208 : }
1209 : } else {
1210 17 : if (preceding) {
1211 135 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_MTIME_SEC_INTERVAL(_PRECEDING, SINGLE, limit);
1212 : } else {
1213 99 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_MTIME_SEC_INTERVAL(_FOLLOWING, SINGLE, limit);
1214 : }
1215 : }
1216 5 : } else if (preceding) {
1217 84 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_PRECEDING, SINGLE, limit, lng);
1218 : } else {
1219 71 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_FOLLOWING, SINGLE, limit, lng);
1220 : }
1221 : break;
1222 : }
1223 0 : case TYPE_flt:{
1224 0 : flt limit = (*(flt *) bound);
1225 0 : if (is_flt_nil(limit) || limit < 0) {
1226 0 : goto invalid_bound;
1227 0 : } else if (limit == GDK_flt_max) {
1228 0 : bat_iterator_end(&pi);
1229 0 : bat_iterator_end(&bi);
1230 0 : bat_iterator_end(&li);
1231 0 : return GDKanalyticalallbounds(b, p, preceding);
1232 0 : } else if (limit == 0) {
1233 0 : bat_iterator_end(&pi);
1234 0 : bat_iterator_end(&bi);
1235 0 : bat_iterator_end(&li);
1236 0 : return GDKanalyticalpeers(b, p, preceding);
1237 : }
1238 0 : r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT);
1239 0 : if (r == NULL)
1240 : return NULL;
1241 0 : oid *restrict rb = (oid *) Tloc(r, 0);
1242 0 : if (preceding) {
1243 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_FLT(_PRECEDING, SINGLE, limit);
1244 : } else {
1245 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_FLT(_FOLLOWING, SINGLE, limit);
1246 : }
1247 : break;
1248 : }
1249 0 : case TYPE_dbl:{
1250 0 : dbl limit = (*(dbl *) bound);
1251 0 : if (is_dbl_nil(limit) || limit < 0) {
1252 0 : goto invalid_bound;
1253 0 : } else if (limit == GDK_dbl_max) {
1254 0 : bat_iterator_end(&pi);
1255 0 : bat_iterator_end(&bi);
1256 0 : bat_iterator_end(&li);
1257 0 : return GDKanalyticalallbounds(b, p, preceding);
1258 0 : } else if (limit == 0) {
1259 0 : bat_iterator_end(&pi);
1260 0 : bat_iterator_end(&bi);
1261 0 : bat_iterator_end(&li);
1262 0 : return GDKanalyticalpeers(b, p, preceding);
1263 : }
1264 0 : r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT);
1265 0 : if (r == NULL)
1266 : return NULL;
1267 0 : oid *restrict rb = (oid *) Tloc(r, 0);
1268 0 : if (preceding) {
1269 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_DBL(_PRECEDING, SINGLE, limit);
1270 : } else {
1271 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_DBL(_FOLLOWING, SINGLE, limit);
1272 : }
1273 : break;
1274 : }
1275 : #ifdef HAVE_HGE
1276 0 : case TYPE_hge:{
1277 0 : hge limit = (*(hge *) bound);
1278 0 : if (is_hge_nil(limit) || limit < 0) {
1279 0 : goto invalid_bound;
1280 0 : } else if (limit == GDK_hge_max) {
1281 0 : bat_iterator_end(&pi);
1282 0 : bat_iterator_end(&bi);
1283 0 : bat_iterator_end(&li);
1284 0 : return GDKanalyticalallbounds(b, p, preceding);
1285 0 : } else if (limit == 0) {
1286 0 : bat_iterator_end(&pi);
1287 0 : bat_iterator_end(&bi);
1288 0 : bat_iterator_end(&li);
1289 0 : return GDKanalyticalpeers(b, p, preceding);
1290 : }
1291 0 : r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT);
1292 0 : if (r == NULL)
1293 : return NULL;
1294 0 : oid *restrict rb = (oid *) Tloc(r, 0);
1295 0 : if (preceding) {
1296 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_HGE(_PRECEDING, SINGLE, limit);
1297 : } else {
1298 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_HGE(_FOLLOWING, SINGLE, limit);
1299 : }
1300 : break;
1301 : }
1302 : #endif
1303 0 : default:
1304 0 : goto bound_not_supported;
1305 : }
1306 : }
1307 40 : bat_iterator_end(&pi);
1308 40 : bat_iterator_end(&bi);
1309 40 : bat_iterator_end(&li);
1310 40 : BATsetcount(r, cnt);
1311 40 : r->tnonil = (nils == 0);
1312 40 : r->tnil = (nils > 0);
1313 40 : return r;
1314 : bound_not_supported:
1315 0 : BBPreclaim(r);
1316 0 : bat_iterator_end(&pi);
1317 0 : bat_iterator_end(&bi);
1318 0 : bat_iterator_end(&li);
1319 0 : GDKerror("42000!range frame bound type %s not supported.\n", ATOMname(tp2));
1320 0 : return NULL;
1321 0 : type_not_supported:
1322 0 : BBPreclaim(r);
1323 0 : bat_iterator_end(&pi);
1324 0 : bat_iterator_end(&bi);
1325 0 : bat_iterator_end(&li);
1326 0 : GDKerror("42000!type %s not supported for %s frame bound type.\n", ATOMname(tp1), ATOMname(tp2));
1327 0 : return NULL;
1328 0 : calc_overflow:
1329 0 : BBPreclaim(r);
1330 0 : bat_iterator_end(&pi);
1331 0 : bat_iterator_end(&bi);
1332 0 : bat_iterator_end(&li);
1333 0 : GDKerror("22003!overflow in calculation.\n");
1334 0 : return NULL;
1335 1 : invalid_bound:
1336 1 : BBPreclaim(r);
1337 1 : bat_iterator_end(&pi);
1338 1 : bat_iterator_end(&bi);
1339 1 : bat_iterator_end(&li);
1340 1 : GDKerror("42000!range frame bound must be non negative and non null.\n");
1341 1 : return NULL;
1342 : }
1343 :
1344 : static BAT *
1345 68 : GDKanalyticalgroupsbounds(BAT *b, BAT *p, BAT *l, const void *restrict bound, int tp2, bool preceding)
1346 : {
1347 68 : oid cnt = BATcount(b), i = 0, k = 0, j = 0;
1348 68 : BATiter pi = bat_iterator(p);
1349 68 : BATiter bi = bat_iterator(b);
1350 68 : BATiter li = bat_iterator(l);
1351 68 : const bit *restrict np = pi.base, *restrict bp = bi.base;
1352 68 : bool last = false;
1353 68 : BAT *r = NULL;
1354 :
1355 68 : if (bi.type != TYPE_bit) {
1356 0 : bat_iterator_end(&pi);
1357 0 : bat_iterator_end(&bi);
1358 0 : bat_iterator_end(&li);
1359 0 : GDKerror("42000!groups frame bound type must be of type bit.\n");
1360 0 : return NULL;
1361 : }
1362 :
1363 68 : if (l) { /* dynamic bounds */
1364 0 : if (li.nil)
1365 0 : goto invalid_bound;
1366 0 : r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT);
1367 0 : if (r == NULL)
1368 : return NULL;
1369 0 : oid *restrict rb = (oid *) Tloc(r, 0);
1370 0 : switch (tp2) {
1371 0 : case TYPE_bte:{
1372 0 : const bte *restrict limit = (bte *) li.base;
1373 0 : if (preceding) {
1374 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, MULTI, bte, limit[k], (oid) olimit);
1375 : } else {
1376 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, MULTI, bte, limit[k], (oid) olimit);
1377 : }
1378 : break;
1379 : }
1380 0 : case TYPE_sht:{
1381 0 : const sht *restrict limit = (sht *) li.base;
1382 0 : if (preceding) {
1383 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, MULTI, sht, limit[k], (oid) olimit);
1384 : } else {
1385 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, MULTI, sht, limit[k], (oid) olimit);
1386 : }
1387 : break;
1388 : }
1389 0 : case TYPE_int:{
1390 0 : const int *restrict limit = (int *) li.base;
1391 0 : if (preceding) {
1392 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, MULTI, int, limit[k], (oid) olimit);
1393 : } else {
1394 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, MULTI, int, limit[k], (oid) olimit);
1395 : }
1396 : break;
1397 : }
1398 0 : case TYPE_lng:{
1399 0 : const lng *restrict limit = (lng *) li.base;
1400 0 : if (preceding) {
1401 : #if SIZEOF_OID == SIZEOF_INT
1402 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, MULTI, lng, limit[k], (olimit > (lng) GDK_oid_max) ? GDK_oid_max : (oid) olimit);
1403 : #else
1404 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, MULTI, lng, limit[k], (oid) olimit);
1405 : #endif
1406 : } else {
1407 : #if SIZEOF_OID == SIZEOF_INT
1408 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, MULTI, lng, limit[k], (olimit > (lng) GDK_oid_max) ? GDK_oid_max : (oid) olimit);
1409 : #else
1410 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, MULTI, lng, limit[k], (oid) olimit);
1411 : #endif
1412 : }
1413 : break;
1414 : }
1415 : #ifdef HAVE_HGE
1416 0 : case TYPE_hge:{
1417 0 : const hge *restrict limit = (hge *) li.base;
1418 0 : if (preceding) {
1419 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, MULTI, hge, limit[k], (olimit > (hge) GDK_oid_max) ? GDK_oid_max : (oid) olimit);
1420 : } else {
1421 0 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, MULTI, hge, limit[k], (olimit > (hge) GDK_oid_max) ? GDK_oid_max : (oid) olimit);
1422 : }
1423 : break;
1424 : }
1425 : #endif
1426 : default:
1427 0 : goto bound_not_supported;
1428 : }
1429 : } else { /* static bounds, all the limits are cast to the word size */
1430 68 : lng limit;
1431 68 : switch (tp2) {
1432 51 : case TYPE_bte:
1433 51 : limit = is_bte_nil(*(bte *) bound) ? lng_nil : (lng) *(bte *) bound;
1434 0 : break;
1435 0 : case TYPE_sht:
1436 0 : limit = is_sht_nil(*(sht *) bound) ? lng_nil : (lng) *(sht *) bound;
1437 0 : break;
1438 0 : case TYPE_int:
1439 0 : limit = is_int_nil(*(int *) bound) ? lng_nil : (lng) *(int *) bound;
1440 0 : break;
1441 17 : case TYPE_lng: {
1442 : #if SIZEOF_OID == SIZEOF_INT
1443 : lng nval = *(lng *) bound;
1444 : limit = is_lng_nil(nval) ? lng_nil : (nval > (lng) GDK_oid_max) ? GDK_lng_max : (lng) nval;
1445 : #else
1446 17 : limit = (lng) (*(lng *) bound);
1447 : #endif
1448 17 : break;
1449 : }
1450 : #ifdef HAVE_HGE
1451 0 : case TYPE_hge: {
1452 0 : hge nval = *(hge *) bound;
1453 0 : limit = is_hge_nil(nval) ? lng_nil : (nval > (hge) GDK_lng_max) ? GDK_lng_max : (lng) nval;
1454 : break;
1455 : }
1456 : #endif
1457 0 : default:
1458 0 : goto bound_not_supported;
1459 : }
1460 68 : if (limit == GDK_lng_max) {
1461 1 : bat_iterator_end(&pi);
1462 1 : bat_iterator_end(&bi);
1463 1 : bat_iterator_end(&li);
1464 1 : return GDKanalyticalallbounds(b, p, preceding);
1465 : }
1466 67 : if (is_lng_nil(limit) || limit < 0) { /* this check is needed if the input is empty */
1467 0 : goto invalid_bound;
1468 : }
1469 67 : r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT);
1470 67 : if (r == NULL)
1471 : return NULL;
1472 67 : oid *restrict rb = (oid *) Tloc(r, 0);
1473 67 : if (preceding) {
1474 1336 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, SINGLE, lng, limit, (oid) olimit);
1475 : } else {
1476 929 : ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, SINGLE, lng, limit, (oid) olimit);
1477 : }
1478 : }
1479 67 : bat_iterator_end(&pi);
1480 67 : bat_iterator_end(&bi);
1481 67 : bat_iterator_end(&li);
1482 67 : BATsetcount(r, cnt);
1483 67 : r->tnonil = true;
1484 67 : r->tnil = false;
1485 67 : return r;
1486 : bound_not_supported:
1487 0 : BBPreclaim(r);
1488 0 : bat_iterator_end(&pi);
1489 0 : bat_iterator_end(&bi);
1490 0 : bat_iterator_end(&li);
1491 0 : GDKerror("42000!groups frame bound type %s not supported.\n", ATOMname(tp2));
1492 0 : return NULL;
1493 0 : invalid_bound:
1494 0 : BBPreclaim(r);
1495 0 : bat_iterator_end(&pi);
1496 0 : bat_iterator_end(&bi);
1497 0 : bat_iterator_end(&li);
1498 0 : GDKerror("42000!groups frame bound must be non negative and non null.\n");
1499 0 : return NULL;
1500 : }
1501 :
1502 : BAT *
1503 765 : GDKanalyticalwindowbounds(BAT *b, BAT *p, BAT *l, const void *restrict bound, int tp1, int tp2, int unit, bool preceding, oid second_half)
1504 : {
1505 765 : assert((l && !bound) || (!l && bound));
1506 :
1507 765 : switch (unit) {
1508 423 : case 0:
1509 423 : return GDKanalyticalrowbounds(b, p, l, bound, tp2, preceding, second_half);
1510 274 : case 1:
1511 274 : return GDKanalyticalrangebounds(b, p, l, bound, tp1, tp2, preceding);
1512 68 : case 2:
1513 68 : return GDKanalyticalgroupsbounds(b, p, l, bound, tp2, preceding);
1514 : default:
1515 0 : MT_UNREACHABLE();
1516 : }
1517 : GDKerror("42000!unit type %d not supported (this is a bug).\n", unit);
1518 : return NULL;
1519 : }
|