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

Generated by: LCOV version 1.14