LCOV - code coverage report
Current view: top level - gdk - gdk_analytic_bounds.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 326 609 53.5 %
Date: 2025-03-24 21:28:01 Functions: 7 7 100.0 %

          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        1918 : GDKanalyticaldiff(BAT *b, BAT *p, const bit *restrict npbit, int tpe)
      96             : {
      97        1918 :         BUN i = 0, cnt = BATcount(b);
      98        1918 :         BATiter pi = bat_iterator(p);
      99        1918 :         BATiter bi = bat_iterator(b);
     100        1918 :         BAT *r = COLnew(b->hseqbase, TYPE_bit, BATcount(b), TRANSIENT);
     101        1918 :         if (r == NULL)
     102             :                 return NULL;
     103        1918 :         bit *restrict rb = (bit *) Tloc(r, 0), npb = npbit ? *npbit : 0;
     104        1918 :         const bit *restrict np = (bit *) pi.base;
     105             : 
     106        3763 :         switch (ATOMbasetype(tpe)) {
     107         231 :         case TYPE_bte:
     108     1765228 :                 ANALYTICAL_DIFF_IMP(bte);
     109             :                 break;
     110         417 :         case TYPE_sht:
     111       13686 :                 ANALYTICAL_DIFF_IMP(sht);
     112             :                 break;
     113         938 :         case TYPE_int:
     114     7509506 :                 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        1918 :         bat_iterator_end(&bi);
     173        1918 :         bat_iterator_end(&pi);
     174        1918 :         BATsetcount(r, cnt);
     175        1918 :         r->tnonil = true;
     176        1918 :         r->tnil = false;
     177        1918 :         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         424 :         BATiter bi = bat_iterator(b);
     869         424 :         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          67 :                                 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         258 :                 case TYPE_bte:
     944         258 :                         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         151 :                 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         151 :                         limit = (lng) (*(lng *) bound);
     958             : #endif
     959         151 :                         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         352 :                 if (r == NULL)
     982             :                         return NULL;
     983         352 :                 oid *restrict rb = (oid *) Tloc(r, 0);
     984         352 :                 if (preceding) {
     985        9739 :                         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         360 :         bat_iterator_end(&pi);
     992         357 :         bat_iterator_end(&bi);
     993         359 :         bat_iterator_end(&li);
     994         359 :         BATsetcount(r, cnt);
     995         360 :         r->tnonil = (nils == 0);
     996         360 :         r->tnil = (nils > 0);
     997         360 :         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         273 :         const bit *restrict np = pi.base;
    1022         273 :         bool last = false;
    1023         273 :         BAT *r = NULL;
    1024             : 
    1025         273 :         if ((tp1 == TYPE_daytime || tp1 == TYPE_date || tp1 == TYPE_timestamp) && tp2 != TYPE_int && tp2 != TYPE_lng)
    1026           0 :                 goto bound_not_supported;
    1027             : 
    1028         273 :         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         273 :                 switch (tp2) {
    1118         273 :                 case TYPE_bte:
    1119             :                 case TYPE_sht:
    1120             :                 case TYPE_int:
    1121             :                 case TYPE_lng:{
    1122         273 :                         lng limit = 0;
    1123         273 :                         int int_limit = 0;
    1124         273 :                         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         160 :                         case TYPE_int:{
    1160         160 :                                 int_limit = (*(int *) bound);
    1161         160 :                                 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          86 :                                 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          22 :                                 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          40 :                         if (is_lng_nil(limit) || limit < 0 || is_int_nil(int_limit) || int_limit < 0) {
    1196           1 :                                 goto invalid_bound;
    1197             :                         }
    1198          39 :                         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         766 : GDKanalyticalwindowbounds(BAT *b, BAT *p, BAT *l, const void *restrict bound, int tp1, int tp2, int unit, bool preceding, oid second_half)
    1504             : {
    1505         766 :         assert((l && !bound) || (!l && bound));
    1506             : 
    1507         766 :         switch (unit) {
    1508         424 :         case 0:
    1509         424 :                 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             : }

Generated by: LCOV version 1.14