1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 *
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V.
7 */
8
9#include "monetdb_config.h"
10#include "gdk.h"
11#include "gdk_analytic.h"
12#include "gdk_calc_private.h"
13
14#define ANALYTICAL_WINDOW_BOUNDS_ROWS_PRECEDING(LIMIT) \
15 do { \
16 lng calc1, calc2; \
17 j = k; \
18 for (; k < i; k++, rb++) { \
19 lng rlimit = LIMIT; \
20 SUB_WITH_CHECK(k, rlimit, lng, calc1, GDK_lng_max, goto calc_overflow); \
21 ADD_WITH_CHECK(calc1, !first_half, lng, calc2, GDK_lng_max, goto calc_overflow); \
22 *rb = MAX(calc2, j); \
23 } \
24 } while (0)
25
26#define ANALYTICAL_WINDOW_BOUNDS_ROWS_FOLLOWING(LIMIT) \
27 do { \
28 lng calc1, calc2; \
29 for (; k < i; k++, rb++) { \
30 lng rlimit = LIMIT; \
31 ADD_WITH_CHECK(rlimit, k, lng, calc1, GDK_lng_max, goto calc_overflow); \
32 ADD_WITH_CHECK(calc1, !first_half, lng, calc2, GDK_lng_max, goto calc_overflow); \
33 *rb = MIN(calc2, i); \
34 } \
35 } while (0)
36
37#define ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE_PRECEDING(TPE1, LIMIT, TPE2) \
38 do { \
39 lng m = k - 1; \
40 TPE1 v, calc; \
41 TPE2 rlimit; \
42 if (b->tnonil) { \
43 for (; k < i; k++, rb++) { \
44 rlimit = (TPE2) LIMIT; \
45 v = bp[k]; \
46 for (j = k; ; j--) { \
47 if (j == m) \
48 break; \
49 SUB_WITH_CHECK(v, bp[j], TPE1, calc, GDK_##TPE1##_max, goto calc_overflow); \
50 if ((TPE2)(ABSOLUTE(calc)) > rlimit) \
51 break; \
52 } \
53 j++; \
54 *rb = j; \
55 } \
56 } else { \
57 for (; k < i; k++, rb++) { \
58 rlimit = (TPE2) LIMIT; \
59 v = bp[k]; \
60 if (is_##TPE1##_nil(v)) { \
61 for (j = k; ; j--) { \
62 if (j == m) \
63 break; \
64 if (!is_##TPE1##_nil(bp[j])) \
65 break; \
66 } \
67 } else { \
68 for (j = k; ; j--) { \
69 if (j == m) \
70 break; \
71 if (is_##TPE1##_nil(bp[j])) \
72 break; \
73 SUB_WITH_CHECK(v, bp[j], TPE1, calc, GDK_##TPE1##_max, goto calc_overflow); \
74 if ((TPE2)(ABSOLUTE(calc)) > rlimit) \
75 break; \
76 } \
77 } \
78 j++; \
79 *rb = j; \
80 } \
81 } \
82 } while (0)
83
84#define ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE_FOLLOWING(TPE1, LIMIT, TPE2) \
85 do { \
86 TPE1 v, calc; \
87 TPE2 rlimit; \
88 if (b->tnonil) { \
89 for (; k < i; k++, rb++) { \
90 rlimit = (TPE2) LIMIT; \
91 v = bp[k]; \
92 for (j = k + 1; j < i; j++) { \
93 SUB_WITH_CHECK(v, bp[j], TPE1, calc, GDK_##TPE1##_max, goto calc_overflow); \
94 if ((TPE2)(ABSOLUTE(calc)) > rlimit) \
95 break; \
96 } \
97 *rb = j; \
98 } \
99 } else { \
100 for (; k < i; k++, rb++) { \
101 rlimit = (TPE2) LIMIT; \
102 v = bp[k]; \
103 if (is_##TPE1##_nil(v)) { \
104 for (j =k + 1; j < i; j++) { \
105 if (!is_##TPE1##_nil(bp[j])) \
106 break; \
107 } \
108 } else { \
109 for (j = k + 1; j < i; j++) { \
110 if (is_##TPE1##_nil(bp[j])) \
111 break; \
112 SUB_WITH_CHECK(v, bp[j], TPE1, calc, GDK_##TPE1##_max, goto calc_overflow); \
113 if ((TPE2)(ABSOLUTE(calc)) > rlimit) \
114 break; \
115 } \
116 } \
117 *rb = j; \
118 } \
119 } \
120 } while (0)
121
122#define ANALYTICAL_WINDOW_BOUNDS_FIXED_GROUPS_PRECEDING(TPE1, LIMIT, TPE2) \
123 do { \
124 lng m = k - 1; \
125 if (b->tnonil) { \
126 for (; k < i; k++, rb++) { \
127 TPE2 rlimit = LIMIT; \
128 TPE1 v = bp[k]; \
129 for (j = k; ; j--) { \
130 if (j == m) \
131 break; \
132 if (v != bp[j]) { \
133 if (rlimit == 0) \
134 break; \
135 rlimit--; \
136 v = bp[j]; \
137 } \
138 } \
139 j++; \
140 *rb = j; \
141 } \
142 } else { \
143 for (; k < i; k++, rb++) { \
144 TPE2 rlimit = LIMIT; \
145 TPE1 v = bp[k]; \
146 if (is_##TPE1##_nil(v)) { \
147 for (j = k; ; j--) { \
148 if (j == m) \
149 break; \
150 if (!is_##TPE1##_nil(bp[j])) \
151 break; \
152 } \
153 } else { \
154 for (j = k; ; j--) { \
155 if (j == m) \
156 break; \
157 if (is_##TPE1##_nil(bp[j])) \
158 break; \
159 if (v != bp[j]) { \
160 if (rlimit == 0) \
161 break; \
162 rlimit--; \
163 v = bp[j]; \
164 } \
165 } \
166 } \
167 j++; \
168 *rb = j; \
169 } \
170 } \
171 } while (0)
172
173#define ANALYTICAL_WINDOW_BOUNDS_FIXED_GROUPS_FOLLOWING(TPE1, LIMIT, TPE2) \
174 do { \
175 if (b->tnonil) { \
176 for (; k < i; k++, rb++) { \
177 TPE2 rlimit = LIMIT; \
178 TPE1 v = bp[k]; \
179 for (j = k + 1; j < i; j++) { \
180 if (v != bp[j]) { \
181 if (rlimit == 0) \
182 break; \
183 rlimit--; \
184 v = bp[j]; \
185 } \
186 } \
187 *rb = j; \
188 } \
189 } else { \
190 for (; k < i; k++, rb++) { \
191 TPE2 rlimit = LIMIT; \
192 TPE1 v = bp[k]; \
193 if (is_##TPE1##_nil(v)) { \
194 for (j = k + 1; j < i; j++) { \
195 if (!is_##TPE1##_nil(bp[j])) \
196 break; \
197 } \
198 } else { \
199 for (j = k + 1; j < i; j++) { \
200 if (is_##TPE1##_nil(bp[j])) \
201 break; \
202 if (v != bp[j]) { \
203 if (rlimit == 0) \
204 break; \
205 rlimit--; \
206 v = bp[j]; \
207 } \
208 } \
209 } \
210 *rb = j; \
211 } \
212 } \
213 } while (0)
214
215#define ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(TPE1, IMP, LIMIT, TPE2) \
216 do { \
217 TPE1 *restrict bp = (TPE1*)Tloc(b, 0); \
218 if (np) { \
219 nend += cnt; \
220 for (; np < nend; np++) { \
221 if (*np) { \
222 i += (np - pnp); \
223 IMP(TPE1, LIMIT, TPE2); \
224 pnp = np; \
225 } \
226 } \
227 i += (np - pnp); \
228 IMP(TPE1, LIMIT, TPE2); \
229 } else { \
230 i += (lng) cnt; \
231 IMP(TPE1, LIMIT, TPE2); \
232 } \
233 } while (0)
234
235#define ANALYTICAL_WINDOW_BOUNDS_VARSIZED_RANGE_PRECEDING(LIMIT, TPE) \
236 do { \
237 lng m = k - 1; \
238 if (b->tnonil) { \
239 for (; k < i; k++, rb++) { \
240 void *v = BUNtail(bpi, (BUN) k); \
241 for (j = k; ; j--) { \
242 void *next; \
243 if (j == m) \
244 break; \
245 next = BUNtail(bpi, (BUN) j); \
246 if (ABSOLUTE((TPE) atomcmp(v, next)) > (TPE) LIMIT) \
247 break; \
248 } \
249 j++; \
250 *rb = j; \
251 } \
252 } else { \
253 for (; k < i; k++, rb++) { \
254 void *v = BUNtail(bpi, (BUN) k); \
255 if (atomcmp(v, nil) == 0) { \
256 for (j = k; ; j--) { \
257 if (j == m) \
258 break; \
259 if (atomcmp(BUNtail(bpi, (BUN) j), nil) != 0) \
260 break; \
261 } \
262 } else { \
263 for (j = k; ; j--) { \
264 void *next; \
265 if (j == m) \
266 break; \
267 next = BUNtail(bpi, (BUN) j); \
268 if (atomcmp(next, nil) == 0) \
269 break; \
270 if (ABSOLUTE((TPE) atomcmp(v, next)) > (TPE) LIMIT) \
271 break; \
272 } \
273 } \
274 j++; \
275 *rb = j; \
276 } \
277 } \
278 } while (0)
279
280#define ANALYTICAL_WINDOW_BOUNDS_VARSIZED_RANGE_FOLLOWING(LIMIT, TPE) \
281 do { \
282 if (b->tnonil) { \
283 for (; k < i; k++, rb++) { \
284 void *v = BUNtail(bpi, (BUN) k); \
285 for (j = k + 1; j < i; j++) { \
286 void *next = BUNtail(bpi, (BUN) j); \
287 if (ABSOLUTE((TPE) atomcmp(v, next)) > (TPE) LIMIT) \
288 break; \
289 } \
290 *rb = j; \
291 } \
292 } else { \
293 for (; k < i; k++, rb++) { \
294 void *v = BUNtail(bpi, (BUN) k); \
295 if (atomcmp(v, nil) == 0) { \
296 for (j = k + 1; j < i; j++) { \
297 if (atomcmp(BUNtail(bpi, (BUN) j), nil) != 0) \
298 break; \
299 } \
300 } else { \
301 for (j = k + 1; j < i; j++) { \
302 void *next = BUNtail(bpi, (BUN) j); \
303 if (atomcmp(next, nil) == 0) \
304 break; \
305 if (ABSOLUTE((TPE) atomcmp(v, next)) > (TPE) LIMIT) \
306 break; \
307 } \
308 } \
309 *rb = j; \
310 } \
311 } \
312 } while (0)
313
314#define ANALYTICAL_WINDOW_BOUNDS_VARSIZED_GROUPS_PRECEDING(LIMIT, TPE) \
315 do { \
316 lng m = k - 1; \
317 if (b->tnonil) { \
318 for (; k < i; k++, rb++) { \
319 TPE rlimit = LIMIT; \
320 void *v = BUNtail(bpi, (BUN) k); \
321 for (j = k; ; j--) { \
322 void *next; \
323 if (j == m) \
324 break; \
325 next = BUNtail(bpi, (BUN) j); \
326 if (atomcmp(v, next)) { \
327 if (rlimit == 0) \
328 break; \
329 rlimit--; \
330 v = next; \
331 } \
332 } \
333 j++; \
334 *rb = j; \
335 } \
336 } else { \
337 for (; k < i; k++, rb++) { \
338 TPE rlimit = LIMIT; \
339 void *v = BUNtail(bpi, (BUN) k); \
340 if (atomcmp(v, nil) == 0) { \
341 for (j = k; ; j--) { \
342 if (j == m) \
343 break; \
344 if (atomcmp(BUNtail(bpi, (BUN) j), nil) != 0) \
345 break; \
346 } \
347 } else { \
348 for (j = k; ; j--) { \
349 void *next; \
350 if (j == m) \
351 break; \
352 next = BUNtail(bpi, (BUN) j); \
353 if (atomcmp(next, nil) == 0) \
354 break; \
355 if (atomcmp(v, next)) { \
356 if (rlimit == 0) \
357 break; \
358 rlimit--; \
359 v = next; \
360 } \
361 } \
362 } \
363 j++; \
364 *rb = j; \
365 } \
366 } \
367 } while (0)
368
369#define ANALYTICAL_WINDOW_BOUNDS_VARSIZED_GROUPS_FOLLOWING(LIMIT, TPE) \
370 do { \
371 if (b->tnonil) { \
372 for (; k < i; k++, rb++) { \
373 TPE rlimit = LIMIT; \
374 void *v = BUNtail(bpi, (BUN) k); \
375 for (j = k + 1; j < i; j++) { \
376 void *next = BUNtail(bpi, (BUN) j); \
377 if (atomcmp(v, next)) { \
378 if (rlimit == 0) \
379 break; \
380 rlimit--; \
381 v = next; \
382 } \
383 } \
384 *rb = j; \
385 } \
386 } else { \
387 for (; k < i; k++, rb++) { \
388 TPE rlimit = LIMIT; \
389 void *v = BUNtail(bpi, (BUN) k); \
390 if (atomcmp(v, nil) == 0) { \
391 for (j = k + 1; j < i; j++) { \
392 if (atomcmp(BUNtail(bpi, (BUN) j), nil) != 0) \
393 break; \
394 } \
395 } else { \
396 for (j = k + 1; j < i; j++) { \
397 void *next = BUNtail(bpi, (BUN) j); \
398 if (atomcmp(next, nil) == 0) \
399 break; \
400 if (atomcmp(v, next)) { \
401 if (rlimit == 0) \
402 break; \
403 rlimit--; \
404 v = next; \
405 } \
406 } \
407 } \
408 *rb = j; \
409 } \
410 } \
411 } while (0)
412
413#define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(IMP, LIMIT) \
414 do { \
415 if (p) { \
416 pnp = np = (bit*)Tloc(p, 0); \
417 nend = np + cnt; \
418 for (; np < nend; np++) { \
419 if (*np) { \
420 i += (np - pnp); \
421 ANALYTICAL_WINDOW_BOUNDS_ROWS##IMP(LIMIT); \
422 pnp = np; \
423 } \
424 } \
425 i += (np - pnp); \
426 ANALYTICAL_WINDOW_BOUNDS_ROWS##IMP(LIMIT); \
427 } else { \
428 i += (lng) cnt; \
429 ANALYTICAL_WINDOW_BOUNDS_ROWS##IMP(LIMIT); \
430 } \
431 } while (0)
432
433#define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(IMP, LIMIT, CAST) \
434 do { \
435 switch (tp1) { \
436 case TYPE_bit: \
437 case TYPE_flt: \
438 case TYPE_dbl: \
439 goto type_not_supported; \
440 case TYPE_bte: \
441 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(bte, ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE##IMP, LIMIT, lng); \
442 break; \
443 case TYPE_sht: \
444 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(sht, ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE##IMP, LIMIT, lng); \
445 break; \
446 case TYPE_int: \
447 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(int, ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE##IMP, LIMIT, lng); \
448 break; \
449 case TYPE_lng: \
450 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(lng, ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE##IMP, LIMIT, lng); \
451 break; \
452 default: { \
453 if (p) { \
454 pnp = np = (bit*)Tloc(p, 0); \
455 nend = np + cnt; \
456 for (; np < nend; np++) { \
457 if (*np) { \
458 i += (np - pnp); \
459 ANALYTICAL_WINDOW_BOUNDS_VARSIZED_RANGE##IMP(LIMIT, CAST); \
460 pnp = np; \
461 } \
462 } \
463 i += (np - pnp); \
464 ANALYTICAL_WINDOW_BOUNDS_VARSIZED_RANGE##IMP(LIMIT, CAST); \
465 } else { \
466 i += (lng) cnt; \
467 ANALYTICAL_WINDOW_BOUNDS_VARSIZED_RANGE##IMP(LIMIT, CAST); \
468 } \
469 } \
470 } \
471 } while (0)
472
473#define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_FLT(IMP, LIMIT) \
474 do { \
475 switch (tp1) { \
476 case TYPE_flt: \
477 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(flt, ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE##IMP, LIMIT, flt); \
478 break; \
479 default: \
480 goto type_not_supported; \
481 } \
482 } while (0)
483
484#define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_DBL(IMP, LIMIT) \
485 do { \
486 switch (tp1) { \
487 case TYPE_dbl: \
488 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(dbl, ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE##IMP, LIMIT, dbl); \
489 break; \
490 default: \
491 goto type_not_supported; \
492 } \
493 } while (0)
494
495#ifdef HAVE_HGE
496#define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_HGE(IMP, LIMIT) \
497 do { \
498 switch (tp1) { \
499 case TYPE_bit: \
500 case TYPE_flt: \
501 case TYPE_dbl: \
502 goto type_not_supported; \
503 case TYPE_bte: \
504 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(bte, ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE##IMP, LIMIT, hge); \
505 break; \
506 case TYPE_sht: \
507 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(sht, ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE##IMP, LIMIT, hge); \
508 break; \
509 case TYPE_int: \
510 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(int, ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE##IMP, LIMIT, hge); \
511 break; \
512 case TYPE_lng: \
513 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(lng, ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE##IMP, LIMIT, hge); \
514 break; \
515 case TYPE_hge: \
516 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(hge, ANALYTICAL_WINDOW_BOUNDS_FIXED_RANGE##IMP, LIMIT, hge); \
517 break; \
518 default: { \
519 if (p) { \
520 pnp = np = (bit*)Tloc(p, 0); \
521 nend = np + cnt; \
522 for (; np < nend; np++) { \
523 if (*np) { \
524 i += (np - pnp); \
525 ANALYTICAL_WINDOW_BOUNDS_VARSIZED_RANGE##IMP(LIMIT, hge); \
526 pnp = np; \
527 } \
528 } \
529 i += (np - pnp); \
530 ANALYTICAL_WINDOW_BOUNDS_VARSIZED_RANGE##IMP(LIMIT, hge); \
531 } else { \
532 i += (lng) cnt; \
533 ANALYTICAL_WINDOW_BOUNDS_VARSIZED_RANGE##IMP(LIMIT, hge); \
534 } \
535 } \
536 } \
537 } while (0)
538#endif
539
540#ifdef HAVE_HGE
541#define ANALYTICAL_WINDOW_BOUNDS_GROUPS_HGE(IMP, LIMIT, TPE) \
542 case TYPE_hge: \
543 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(hge, ANALYTICAL_WINDOW_BOUNDS_FIXED_GROUPS##IMP, LIMIT, TPE); \
544 break;
545#else
546#define ANALYTICAL_WINDOW_BOUNDS_GROUPS_HGE(IMP, LIMIT, TPE)
547#endif
548
549#define ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(IMP, LIMIT, TPE) \
550 do { \
551 switch (tp1) { \
552 case TYPE_bit: \
553 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(bit, ANALYTICAL_WINDOW_BOUNDS_FIXED_GROUPS##IMP, LIMIT, TPE); \
554 break; \
555 case TYPE_bte: \
556 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(bte, ANALYTICAL_WINDOW_BOUNDS_FIXED_GROUPS##IMP, LIMIT, TPE); \
557 break; \
558 case TYPE_sht: \
559 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(sht, ANALYTICAL_WINDOW_BOUNDS_FIXED_GROUPS##IMP, LIMIT, TPE); \
560 break; \
561 case TYPE_int: \
562 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(int, ANALYTICAL_WINDOW_BOUNDS_FIXED_GROUPS##IMP, LIMIT, TPE); \
563 break; \
564 case TYPE_lng: \
565 ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(lng, ANALYTICAL_WINDOW_BOUNDS_FIXED_GROUPS##IMP, LIMIT, TPE); \
566 break; \
567 ANALYTICAL_WINDOW_BOUNDS_GROUPS_HGE(IMP, LIMIT, TPE); \
568 default: { \
569 if (p) { \
570 pnp = np = (bit*)Tloc(p, 0); \
571 nend = np + cnt; \
572 for (; np < nend; np++) { \
573 if (*np) { \
574 i += (np - pnp); \
575 ANALYTICAL_WINDOW_BOUNDS_VARSIZED_GROUPS##IMP(LIMIT, TPE); \
576 pnp = np; \
577 } \
578 } \
579 i += (np - pnp); \
580 ANALYTICAL_WINDOW_BOUNDS_VARSIZED_GROUPS##IMP(LIMIT, TPE); \
581 } else { \
582 i += (lng) cnt; \
583 ANALYTICAL_WINDOW_BOUNDS_VARSIZED_GROUPS##IMP(LIMIT, TPE); \
584 } \
585 } \
586 } \
587 } while (0)
588
589static gdk_return
590GDKanalyticalallbounds(BAT *r, BAT *b, BAT *p, bool preceding)
591{
592 BUN cnt = BATcount(b);
593 lng *restrict rb = (lng *) Tloc(r, 0), i = 0, k = 0, j = 0;
594 bit *np = p ? (bit *) Tloc(p, 0) : NULL, *pnp = np, *nend = np;
595
596 if (preceding) {
597 if (np) {
598 nend += cnt;
599 for (; np < nend; np++) {
600 if (*np) {
601 i += (np - pnp);
602 j = k;
603 for (; k < i; k++)
604 rb[k] = j;
605 pnp = np;
606 }
607 }
608 i += (np - pnp);
609 j = k;
610 for (; k < i; k++)
611 rb[k] = j;
612 } else {
613 i += (lng) cnt;
614 j = k;
615 for (; k < i; k++)
616 rb[k] = j;
617 }
618 } else if (np) { /* following */
619 nend += cnt;
620 for (; np < nend; np++) {
621 if (*np) {
622 i += (np - pnp);
623 for (; k < i; k++)
624 rb[k] = i;
625 pnp = np;
626 }
627 }
628 i += (np - pnp);
629 for (; k < i; k++)
630 rb[k] = i;
631 } else {
632 i += (lng) cnt;
633 for (; k < i; k++)
634 rb[k] = i;
635 }
636
637 BATsetcount(r, cnt);
638 r->tnonil = false;
639 r->tnil = false;
640 return GDK_SUCCEED;
641}
642
643static gdk_return
644GDKanalyticalrowbounds(BAT *r, BAT *b, BAT *p, BAT *l, const void *restrict bound, int tp2, bool preceding, lng first_half)
645{
646 BUN cnt = BATcount(b), nils = 0;
647 lng *restrict rb = (lng *) Tloc(r, 0), i = 0, k = 0, j = 0;
648 bit *np, *pnp, *nend;
649 int abort_on_error = 1;
650
651 if (l) { /* dynamic bounds */
652 switch (tp2) {
653 case TYPE_bte:{
654 bte *restrict limit = (bte *) Tloc(l, 0);
655 if (preceding) {
656 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, (lng) limit[k]);
657 } else {
658 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, (lng) limit[k]);
659 }
660 break;
661 }
662 case TYPE_sht:{
663 sht *restrict limit = (sht *) Tloc(l, 0);
664 if (preceding) {
665 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, (lng) limit[k]);
666 } else {
667 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, (lng) limit[k]);
668 }
669 break;
670 }
671 case TYPE_int:{
672 int *restrict limit = (int *) Tloc(l, 0);
673 if (preceding) {
674 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, (lng) limit[k]);
675 } else {
676 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, (lng) limit[k]);
677 }
678 break;
679 }
680 case TYPE_lng:{
681 lng *restrict limit = (lng *) Tloc(l, 0);
682 if (preceding) {
683 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, (lng) limit[k]);
684 } else {
685 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, (lng) limit[k]);
686 }
687 break;
688 }
689#ifdef HAVE_HGE
690 case TYPE_hge:{
691 hge *restrict limit = (hge *) Tloc(l, 0);
692 if (preceding) {
693 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, (limit[k] > (hge) GDK_lng_max) ? GDK_lng_max : (lng) limit[k]);
694 } else {
695 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, (limit[k] > (hge) GDK_lng_max) ? GDK_lng_max : (lng) limit[k]);
696 }
697 break;
698 }
699#endif
700 default:
701 goto bound_not_supported;
702 }
703 } else { /* static bounds, all the limits are cast to lng */
704 lng limit;
705 switch (tp2) {
706 case TYPE_bte:
707 limit = is_bte_nil(*(bte *) bound) ? lng_nil : (lng) *(bte *) bound;
708 break;
709 case TYPE_sht:
710 limit = is_sht_nil(*(sht *) bound) ? lng_nil : (lng) *(sht *) bound;
711 break;
712 case TYPE_int:
713 limit = is_int_nil(*(int *) bound) ? lng_nil : (lng) *(int *) bound;
714 break;
715 case TYPE_lng:
716 limit = (lng) (*(lng *) bound);
717 break;
718#ifdef HAVE_HGE
719 case TYPE_hge: {
720 hge nval = *(hge *) bound;
721 limit = is_hge_nil(nval) ? lng_nil : (nval > (hge) GDK_lng_max) ? GDK_lng_max : (lng) nval;
722 break;
723 }
724#endif
725 default:
726 goto bound_not_supported;
727 }
728 if (is_lng_nil(limit)) {
729 return GDKanalyticalallbounds(r, b, p, preceding);
730 } else if (preceding) {
731 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_PRECEDING, limit);
732 } else {
733 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_ROWS(_FOLLOWING, limit);
734 }
735 }
736
737 BATsetcount(r, cnt);
738 r->tnonil = (nils == 0);
739 r->tnil = (nils > 0);
740 return GDK_SUCCEED;
741 bound_not_supported:
742 GDKerror("GDKanalyticalrowbounds: rows frame bound type %s not supported.\n", ATOMname(tp2));
743 return GDK_FAIL;
744 calc_overflow:
745 GDKerror("22003!overflow in calculation.\n");
746 return GDK_FAIL;
747}
748
749static gdk_return
750GDKanalyticalrangebounds(BAT *r, BAT *b, BAT *p, BAT *l, const void *restrict bound, int tp1, int tp2, bool preceding)
751{
752 BUN cnt = BATcount(b), nils = 0;
753 lng *restrict rb = (lng *) Tloc(r, 0), i = 0, k = 0, j = 0;
754 bit *np = p ? (bit *) Tloc(p, 0) : NULL, *pnp = np, *nend = np;
755 BATiter bpi = bat_iterator(b);
756 int (*atomcmp) (const void *, const void *) = ATOMcompare(tp1);
757 const void *restrict nil = ATOMnilptr(tp1);
758 int abort_on_error = 1;
759
760 if (l) { /* dynamic bounds */
761 switch (tp2) {
762 case TYPE_bte:{
763 bte *restrict limit = (bte *) Tloc(l, 0);
764 if (preceding) {
765 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_PRECEDING, limit[k], int);
766 } else {
767 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_FOLLOWING, limit[k], int);
768 }
769 break;
770 }
771 case TYPE_sht:{
772 sht *restrict limit = (sht *) Tloc(l, 0);
773 if (preceding) {
774 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_PRECEDING, limit[k], int);
775 } else {
776 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_FOLLOWING, limit[k], int);
777 }
778 break;
779 }
780 case TYPE_int:{
781 int *restrict limit = (int *) Tloc(l, 0);
782 if (preceding) {
783 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_PRECEDING, limit[k], int);
784 } else {
785 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_FOLLOWING, limit[k], int);
786 }
787 break;
788 }
789 case TYPE_lng:{
790 lng *restrict limit = (lng *) Tloc(l, 0);
791 if (preceding) {
792 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_PRECEDING, limit[k], lng);
793 } else {
794 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_FOLLOWING, limit[k], lng);
795 }
796 break;
797 }
798 case TYPE_flt:{
799 flt *restrict limit = (flt *) Tloc(l, 0);
800 if (preceding) {
801 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_FLT(_PRECEDING, limit[k]);
802 } else {
803 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_FLT(_FOLLOWING, limit[k]);
804 }
805 break;
806 }
807 case TYPE_dbl:{
808 dbl *restrict limit = (dbl *) Tloc(l, 0);
809 if (preceding) {
810 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_DBL(_PRECEDING, limit[k]);
811 } else {
812 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_DBL(_FOLLOWING, limit[k]);
813 }
814 break;
815 }
816#ifdef HAVE_HGE
817 case TYPE_hge:{
818 hge *restrict limit = (hge *) Tloc(l, 0);
819 if (preceding) {
820 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_HGE(_PRECEDING, limit[k]);
821 } else {
822 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_HGE(_FOLLOWING, limit[k]);
823 }
824 break;
825 }
826#endif
827 default:
828 goto bound_not_supported;
829 }
830 } else { /* static bounds */
831 switch (tp2) {
832 case TYPE_bte:
833 case TYPE_sht:
834 case TYPE_int:
835 case TYPE_lng:{
836 lng limit = 0;
837 switch (tp2) {
838 case TYPE_bte:{
839 bte ll = (*(bte *) bound);
840 if (is_bte_nil(ll)) /* UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING cases, avoid overflow */
841 return GDKanalyticalallbounds(r, b, p, preceding);
842 else
843 limit = (lng) ll;
844 break;
845 }
846 case TYPE_sht:{
847 sht ll = (*(sht *) bound);
848 if (is_sht_nil(ll))
849 return GDKanalyticalallbounds(r, b, p, preceding);
850 else
851 limit = (lng) ll;
852 break;
853 }
854 case TYPE_int:{
855 int ll = (*(int *) bound);
856 if (is_int_nil(ll))
857 return GDKanalyticalallbounds(r, b, p, preceding);
858 else
859 limit = (lng) ll;
860 break;
861 }
862 case TYPE_lng:{
863 lng ll = (*(lng *) bound);
864 if (is_lng_nil(ll))
865 return GDKanalyticalallbounds(r, b, p, preceding);
866 else
867 limit = (lng) ll;
868 break;
869 }
870 default:
871 assert(0);
872 }
873 if (preceding) {
874 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_PRECEDING, limit, lng);
875 } else {
876 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_NUM(_FOLLOWING, limit, lng);
877 }
878 break;
879 }
880 case TYPE_flt:{
881 flt limit = (*(flt *) bound);
882 if (is_flt_nil(limit)) {
883 return GDKanalyticalallbounds(r, b, p, preceding);
884 } else if (preceding) {
885 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_FLT(_PRECEDING, limit);
886 } else {
887 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_FLT(_FOLLOWING, limit);
888 }
889 break;
890 }
891 case TYPE_dbl:{
892 dbl limit = (*(dbl *) bound);
893 if (is_dbl_nil(limit)) {
894 return GDKanalyticalallbounds(r, b, p, preceding);
895 } else if (preceding) {
896 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_DBL(_PRECEDING, limit);
897 } else {
898 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_DBL(_FOLLOWING, limit);
899 }
900 break;
901 }
902#ifdef HAVE_HGE
903 case TYPE_hge:{
904 hge limit = (*(hge *) bound);
905 if (is_hge_nil(limit)) {
906 return GDKanalyticalallbounds(r, b, p, preceding);
907 } else if (preceding) {
908 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_HGE(_PRECEDING, limit);
909 } else {
910 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_RANGE_HGE(_FOLLOWING, limit);
911 }
912 break;
913 }
914#endif
915 default:
916 goto bound_not_supported;
917 }
918 }
919 BATsetcount(r, cnt);
920 r->tnonil = (nils == 0);
921 r->tnil = (nils > 0);
922 return GDK_SUCCEED;
923 bound_not_supported:
924 GDKerror("GDKanalyticalrangebounds: range frame bound type %s not supported.\n", ATOMname(tp2));
925 return GDK_FAIL;
926 type_not_supported:
927 GDKerror("GDKanalyticalrangebounds: type %s not supported for %s frame bound type.\n", ATOMname(tp1), ATOMname(tp2));
928 return GDK_FAIL;
929 calc_overflow:
930 GDKerror("22003!overflow in calculation.\n");
931 return GDK_FAIL;
932}
933
934static gdk_return
935GDKanalyticalgroupsbounds(BAT *r, BAT *b, BAT *p, BAT *l, const void *restrict bound, int tp1, int tp2, bool preceding)
936{
937 BUN cnt = BATcount(b), nils = 0;
938 lng *restrict rb = (lng *) Tloc(r, 0), i = 0, k = 0, j = 0;
939 bit *np = p ? (bit *) Tloc(p, 0) : NULL, *pnp = np, *nend = np;
940 BATiter bpi = bat_iterator(b);
941 int (*atomcmp) (const void *, const void *) = ATOMcompare(tp1);
942 const void *restrict nil = ATOMnilptr(tp1);
943
944 if (l) { /* dynamic bounds */
945 switch (tp2) {
946 case TYPE_bte:{
947 bte *restrict limit = (bte *) Tloc(l, 0);
948 if (preceding) {
949 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, limit[k], bte);
950 } else {
951 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, limit[k], bte);
952 }
953 break;
954 }
955 case TYPE_sht:{
956 sht *restrict limit = (sht *) Tloc(l, 0);
957 if (preceding) {
958 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, limit[k], sht);
959 } else {
960 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, limit[k], sht);
961 }
962 break;
963 }
964 case TYPE_int:{
965 int *restrict limit = (int *) Tloc(l, 0);
966 if (preceding) {
967 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, limit[k], int);
968 } else {
969 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, limit[k], int);
970 }
971 break;
972 }
973 case TYPE_lng:{
974 lng *restrict limit = (lng *) Tloc(l, 0);
975 if (preceding) {
976 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, limit[k], lng);
977 } else {
978 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, limit[k], lng);
979 }
980 break;
981 }
982#ifdef HAVE_HGE
983 case TYPE_hge:{
984 hge *restrict limit = (hge *) Tloc(l, 0);
985 if (preceding) {
986 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, limit[k], hge);
987 } else {
988 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, limit[k], hge);
989 }
990 break;
991 }
992#endif
993 default:
994 goto bound_not_supported;
995 }
996 } else { /* static bounds, all the limits are cast to lng */
997 lng limit;
998 switch (tp2) {
999 case TYPE_bte:
1000 limit = is_bte_nil(*(bte *) bound) ? lng_nil : (lng) *(bte *) bound;
1001 break;
1002 case TYPE_sht:
1003 limit = is_sht_nil(*(sht *) bound) ? lng_nil : (lng) *(sht *) bound;
1004 break;
1005 case TYPE_int:
1006 limit = is_int_nil(*(int *) bound) ? lng_nil : (lng) *(int *) bound;
1007 break;
1008 case TYPE_lng:
1009 limit = (lng) (*(lng *) bound);
1010 break;
1011#ifdef HAVE_HGE
1012 case TYPE_hge: {
1013 hge nval = *(hge *) bound;
1014 limit = is_hge_nil(nval) ? lng_nil : (nval > (hge) GDK_lng_max) ? GDK_lng_max : (lng) nval;
1015 break;
1016 }
1017#endif
1018 default:
1019 goto bound_not_supported;
1020 }
1021 if (is_lng_nil(limit)) {
1022 return GDKanalyticalallbounds(r, b, p, preceding);
1023 } else if (preceding) {
1024 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_PRECEDING, limit, lng);
1025 } else {
1026 ANALYTICAL_WINDOW_BOUNDS_BRANCHES_GROUPS(_FOLLOWING, limit, lng);
1027 }
1028 }
1029 BATsetcount(r, cnt);
1030 r->tnonil = (nils == 0);
1031 r->tnil = (nils > 0);
1032 return GDK_SUCCEED;
1033 bound_not_supported:
1034 GDKerror("GDKanalyticalgroupsbounds: groups frame bound type %s not supported.\n", ATOMname(tp2));
1035 return GDK_FAIL;
1036}
1037
1038gdk_return
1039GDKanalyticalwindowbounds(BAT *r, BAT *b, BAT *p, BAT *l, const void *restrict bound, int tp1, int tp2, int unit, bool preceding, lng first_half)
1040{
1041 assert((l && !bound) || (!l && bound));
1042
1043 switch (unit) {
1044 case 0:
1045 return GDKanalyticalrowbounds(r, b, p, l, bound, tp2, preceding, first_half);
1046 case 1:
1047 return GDKanalyticalrangebounds(r, b, p, l, bound, tp1, tp2, preceding);
1048 case 2:
1049 return GDKanalyticalgroupsbounds(r, b, p, l, bound, tp1, tp2, preceding);
1050 case 3:
1051 return GDKanalyticalallbounds(r, b, p, preceding);
1052 default:
1053 assert(0);
1054 }
1055 GDKerror("GDKanalyticalwindowbounds: unit type %d not supported (this is a bug).\n", unit);
1056 return GDK_FAIL;
1057}
1058