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

Generated by: LCOV version 1.14