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