LCOV - code coverage report
Current view: top level - gdk - gdk_analytic_bounds.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 277 532 52.1 %
Date: 2021-09-14 19:48:19 Functions: 7 7 100.0 %

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

Generated by: LCOV version 1.14