LCOV - code coverage report
Current view: top level - gdk - gdk_analytic_func.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 411 619 66.4 %
Date: 2021-09-14 19:48:19 Functions: 21 21 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_calc_private.h"
      13             : 
      14             : gdk_return
      15       39550 : GDKrebuild_segment_tree(oid ncount, oid data_size, void **segment_tree, oid *tree_capacity, oid **levels_offset, oid *nlevels)
      16             : {
      17             :         oid total_size, next_tree_size = ncount, counter = ncount, next_levels = 1; /* there will be at least one level */
      18             :         void *new_segment_tree;
      19             : 
      20       39550 :         assert(ncount > 0);
      21             :         do { /* compute the next number of levels */
      22       69793 :                 counter = (oid) ceil((dbl)counter / SEGMENT_TREE_FANOUT);
      23       69793 :                 next_tree_size += counter;
      24       69793 :                 next_levels++;
      25       69793 :         } while (counter > 1);
      26             : 
      27       39550 :         *nlevels = next_levels; /* set the logical size of levels before the physical one */
      28       39550 :         next_tree_size *= data_size;
      29       39550 :         total_size = next_tree_size + next_levels * sizeof(oid);
      30             : 
      31       39550 :         if (total_size > *tree_capacity) {
      32         219 :                 total_size = (((total_size) + 1023) & ~1023); /* align to a multiple of 1024 bytes */
      33         219 :                 if (!(new_segment_tree = GDKmalloc(total_size)))
      34             :                         return GDK_FAIL;
      35         219 :                 GDKfree(*segment_tree);
      36         219 :                 *tree_capacity = total_size;
      37         219 :                 *segment_tree = new_segment_tree;
      38         219 :                 *levels_offset = (oid*)((uint8_t*)new_segment_tree + next_tree_size); /* levels offset will be next to the segment tree */
      39             :         } else {
      40       39331 :                 *levels_offset = (oid*)(*(uint8_t**)segment_tree + next_tree_size); /* no reallocation, just update location of levels offset */
      41             :         }
      42             :         return GDK_SUCCEED;
      43             : }
      44             : 
      45             : #define NTILE_CALC(TPE, NEXT_VALUE, LNG_HGE, UPCAST, VALIDATION)        \
      46             :         do {                                                            \
      47             :                 UPCAST j = 0, ncnt = (UPCAST) (i - k);                  \
      48             :                 for (; k < i; k++, j++) {                            \
      49             :                         TPE val = NEXT_VALUE;                           \
      50             :                         if (is_##TPE##_nil(val)) {                      \
      51             :                                 has_nils = true;                        \
      52             :                                 rb[k] = TPE##_nil;                      \
      53             :                         } else {                                        \
      54             :                                 UPCAST nval = (UPCAST) LNG_HGE;         \
      55             :                                 VALIDATION /* validation must come after null check */ \
      56             :                                 if (nval >= ncnt) {                  \
      57             :                                         rb[k] = (TPE)(j + 1);           \
      58             :                                 } else {                                \
      59             :                                         UPCAST bsize = ncnt / nval;     \
      60             :                                         UPCAST top = ncnt - nval * bsize; \
      61             :                                         UPCAST small = top * (bsize + 1); \
      62             :                                         if ((UPCAST) j < small)              \
      63             :                                                 rb[k] = (TPE)(1 + j / (bsize + 1)); \
      64             :                                         else                            \
      65             :                                                 rb[k] = (TPE)(1 + top + (j - small) / bsize); \
      66             :                                 }                                       \
      67             :                         }                                               \
      68             :                 }                                                       \
      69             :         } while (0)
      70             : 
      71             : #define ANALYTICAL_NTILE(IMP, TPE, NEXT_VALUE, LNG_HGE, UPCAST, VALIDATION) \
      72             :         do {                                                            \
      73             :                 TPE *rb = (TPE*)Tloc(r, 0);                             \
      74             :                 if (p) {                                                \
      75             :                         while (i < cnt) {                            \
      76             :                                 if (np[i])      {                       \
      77             : ntile##IMP##TPE:                                                        \
      78             :                                         NTILE_CALC(TPE, NEXT_VALUE, LNG_HGE, UPCAST, VALIDATION); \
      79             :                                 }                                       \
      80             :                                 if (!last)                              \
      81             :                                         i++;                            \
      82             :                         }                                               \
      83             :                 }                                                       \
      84             :                 if (!last) {                                            \
      85             :                         last = true;                                    \
      86             :                         i = cnt;                                        \
      87             :                         goto ntile##IMP##TPE;                           \
      88             :                 }                                                       \
      89             :         } while (0)
      90             : 
      91             : #define ANALYTICAL_NTILE_SINGLE_IMP(TPE, LNG_HGE, UPCAST)               \
      92             :         do {                                                            \
      93             :                 TPE ntl = *(TPE*) ntile;                                \
      94             :                 if (!is_##TPE##_nil(ntl) && ntl <= 0) goto invalidntile; \
      95             :                 ANALYTICAL_NTILE(SINGLE, TPE, ntl, LNG_HGE, UPCAST, ;); \
      96             :         } while (0)
      97             : 
      98             : #define ANALYTICAL_NTILE_MULTI_IMP(TPE, LNG_HGE, UPCAST)                \
      99             :         do {                                                            \
     100             :                 const TPE *restrict nn = (TPE*)ni.base;                 \
     101             :                 ANALYTICAL_NTILE(MULTI, TPE, nn[k], LNG_HGE, UPCAST, if (val <= 0) goto invalidntile;); \
     102             :         } while (0)
     103             : 
     104             : gdk_return
     105          61 : GDKanalyticalntile(BAT *r, BAT *b, BAT *p, BAT *n, int tpe, const void *restrict ntile)
     106             : {
     107          61 :         BATiter bi = bat_iterator(b);
     108          61 :         BATiter pi = bat_iterator(p);
     109          61 :         BATiter ni = bat_iterator(n);
     110          61 :         lng i = 0, k = 0, cnt = (lng) BATcount(b);
     111          61 :         const bit *restrict np = pi.base;
     112             :         bool has_nils = false, last = false;
     113             : 
     114          61 :         assert((n && !ntile) || (!n && ntile));
     115             : 
     116          61 :         if (ntile) {
     117          34 :                 switch (tpe) {
     118          33 :                 case TYPE_bte:
     119         674 :                         ANALYTICAL_NTILE_SINGLE_IMP(bte, val, BUN);
     120             :                         break;
     121           0 :                 case TYPE_sht:
     122           0 :                         ANALYTICAL_NTILE_SINGLE_IMP(sht, val, BUN);
     123             :                         break;
     124           0 :                 case TYPE_int:
     125           0 :                         ANALYTICAL_NTILE_SINGLE_IMP(int, val, BUN);
     126             :                         break;
     127           1 :                 case TYPE_lng:
     128             : #if SIZEOF_OID == SIZEOF_INT
     129             :                         ANALYTICAL_NTILE_SINGLE_IMP(lng, val, lng);
     130             : #else
     131         162 :                         ANALYTICAL_NTILE_SINGLE_IMP(lng, val, BUN);
     132             : #endif
     133             :                         break;
     134             : #ifdef HAVE_HGE
     135           0 :                 case TYPE_hge:
     136             : #if SIZEOF_OID == SIZEOF_INT
     137             :                         ANALYTICAL_NTILE_SINGLE_IMP(hge, (val > (hge) GDK_int_max) ? GDK_int_max : (lng) val, lng);
     138             : #else
     139           0 :                         ANALYTICAL_NTILE_SINGLE_IMP(hge, (val > (hge) GDK_lng_max) ? GDK_lng_max : (lng) val, BUN);
     140             : #endif
     141             : #endif
     142             :                 default:
     143           0 :                         goto nosupport;
     144             :                 }
     145             :         } else {
     146          27 :                 switch (tpe) {
     147           1 :                 case TYPE_bte:
     148          12 :                         ANALYTICAL_NTILE_MULTI_IMP(bte, val, BUN);
     149             :                         break;
     150           0 :                 case TYPE_sht:
     151           0 :                         ANALYTICAL_NTILE_MULTI_IMP(sht, val, BUN);
     152             :                         break;
     153          26 :                 case TYPE_int:
     154         420 :                         ANALYTICAL_NTILE_MULTI_IMP(int, val, BUN);
     155             :                         break;
     156           0 :                 case TYPE_lng:
     157             : #if SIZEOF_OID == SIZEOF_INT
     158             :                         ANALYTICAL_NTILE_MULTI_IMP(lng, val, lng);
     159             : #else
     160           0 :                         ANALYTICAL_NTILE_MULTI_IMP(lng, val, BUN);
     161             : #endif
     162             :                         break;
     163             : #ifdef HAVE_HGE
     164           0 :                 case TYPE_hge:
     165             : #if SIZEOF_OID == SIZEOF_INT
     166             :                         ANALYTICAL_NTILE_MULTI_IMP(hge, (val > (hge) GDK_int_max) ? GDK_int_max : (lng) val, lng);
     167             : #else
     168           0 :                         ANALYTICAL_NTILE_MULTI_IMP(hge, (val > (hge) GDK_lng_max) ? GDK_lng_max : (lng) val, BUN);
     169             : #endif
     170             :                 break;
     171             : #endif
     172           0 :                 default:
     173           0 :                         goto nosupport;
     174             :                 }
     175             :         }
     176          61 :         bat_iterator_end(&bi);
     177          61 :         bat_iterator_end(&pi);
     178          61 :         bat_iterator_end(&ni);
     179          61 :         BATsetcount(r, BATcount(b));
     180          61 :         r->tnonil = !has_nils;
     181          61 :         r->tnil = has_nils;
     182          61 :         return GDK_SUCCEED;
     183           0 : nosupport:
     184           0 :         bat_iterator_end(&bi);
     185           0 :         bat_iterator_end(&pi);
     186           0 :         bat_iterator_end(&ni);
     187           0 :         GDKerror("42000!type %s not supported for the ntile type.\n", ATOMname(tpe));
     188           0 :         return GDK_FAIL;
     189           0 : invalidntile:
     190           0 :         bat_iterator_end(&bi);
     191           0 :         bat_iterator_end(&pi);
     192           0 :         bat_iterator_end(&ni);
     193           0 :         GDKerror("42000!ntile must be greater than zero.\n");
     194           0 :         return GDK_FAIL;
     195             : }
     196             : 
     197             : #define ANALYTICAL_FIRST_FIXED(TPE)                                     \
     198             :         do {                                                            \
     199             :                 const TPE *bp = (TPE*)bi.base;                          \
     200             :                 TPE *rb = (TPE*)Tloc(r, 0);                             \
     201             :                 for (; k < cnt; k++) {                                       \
     202             :                         const TPE *bs = bp + start[k], *be = bp + end[k]; \
     203             :                         TPE curval = (be > bs) ? *bs : TPE##_nil;    \
     204             :                         rb[k] = curval;                                 \
     205             :                         has_nils |= is_##TPE##_nil(curval);             \
     206             :                 }                                                       \
     207             :         } while (0)
     208             : 
     209             : gdk_return
     210          32 : GDKanalyticalfirst(BAT *r, BAT *b, BAT *s, BAT *e, int tpe)
     211             : {
     212          32 :         BATiter bi = bat_iterator(b);
     213          32 :         BATiter si = bat_iterator(s);
     214          32 :         BATiter ei = bat_iterator(e);
     215             :         bool has_nils = false;
     216          32 :         oid k = 0, cnt = BATcount(b);
     217          32 :         const oid *restrict start = si.base, *restrict end = ei.base;
     218          32 :         const void *nil = ATOMnilptr(tpe);
     219          32 :         int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe);
     220             : 
     221          32 :         switch (ATOMbasetype(tpe)) {
     222           1 :         case TYPE_bte:
     223          11 :                 ANALYTICAL_FIRST_FIXED(bte);
     224             :                 break;
     225           0 :         case TYPE_sht:
     226           0 :                 ANALYTICAL_FIRST_FIXED(sht);
     227             :                 break;
     228          23 :         case TYPE_int:
     229         244 :                 ANALYTICAL_FIRST_FIXED(int);
     230             :                 break;
     231           1 :         case TYPE_lng:
     232          12 :                 ANALYTICAL_FIRST_FIXED(lng);
     233             :                 break;
     234             : #ifdef HAVE_HGE
     235           0 :         case TYPE_hge:
     236           0 :                 ANALYTICAL_FIRST_FIXED(hge);
     237             :                 break;
     238             : #endif
     239           0 :         case TYPE_flt:
     240           0 :                 ANALYTICAL_FIRST_FIXED(flt);
     241             :                 break;
     242           2 :         case TYPE_dbl:
     243          14 :                 ANALYTICAL_FIRST_FIXED(dbl);
     244             :                 break;
     245           5 :         default:{
     246           5 :                 if (ATOMvarsized(tpe)) {
     247          50 :                         for (; k < cnt; k++) {
     248          45 :                                 const void *curval = (end[k] > start[k]) ? BUNtvar(bi, start[k]) : nil;
     249          45 :                                 if (tfastins_nocheckVAR(r, k, curval) != GDK_SUCCEED) {
     250           0 :                                         bat_iterator_end(&bi);
     251           0 :                                         bat_iterator_end(&si);
     252           0 :                                         bat_iterator_end(&ei);
     253           0 :                                         return GDK_FAIL;
     254             :                                 }
     255          45 :                                 has_nils |= atomcmp(curval, nil) == 0;
     256             :                         }
     257             :                 } else {
     258           0 :                         uint16_t width = r->twidth;
     259           0 :                         uint8_t *restrict rcast = (uint8_t *) Tloc(r, 0);
     260           0 :                         for (; k < cnt; k++) {
     261           0 :                                 const void *curval = (end[k] > start[k]) ? BUNtloc(bi, start[k]) : nil;
     262           0 :                                 memcpy(rcast, curval, width);
     263           0 :                                 rcast += width;
     264           0 :                                 has_nils |= atomcmp(curval, nil) == 0;
     265             :                         }
     266             :                 }
     267             :         }
     268             :         }
     269          32 :         bat_iterator_end(&bi);
     270          32 :         bat_iterator_end(&si);
     271          32 :         bat_iterator_end(&ei);
     272             : 
     273          32 :         BATsetcount(r, cnt);
     274          32 :         r->tnonil = !has_nils;
     275          32 :         r->tnil = has_nils;
     276          32 :         return GDK_SUCCEED;
     277             : }
     278             : 
     279             : #define ANALYTICAL_LAST_FIXED(TPE)                                      \
     280             :         do {                                                            \
     281             :                 const TPE *bp = (TPE*)bi.base;                          \
     282             :                 TPE *rb = (TPE*)Tloc(r, 0);                             \
     283             :                 for (; k < cnt; k++) {                                       \
     284             :                         const TPE *bs = bp + start[k], *be = bp + end[k]; \
     285             :                         TPE curval = (be > bs) ? *(be - 1) : TPE##_nil;      \
     286             :                         rb[k] = curval;                                 \
     287             :                         has_nils |= is_##TPE##_nil(curval);             \
     288             :                 }                                                       \
     289             :         } while (0)
     290             : 
     291             : gdk_return
     292          31 : GDKanalyticallast(BAT *r, BAT *b, BAT *s, BAT *e, int tpe)
     293             : {
     294          31 :         BATiter bi = bat_iterator(b);
     295          31 :         BATiter si = bat_iterator(s);
     296          31 :         BATiter ei = bat_iterator(e);
     297             :         bool has_nils = false;
     298          31 :         oid k = 0, cnt = BATcount(b);
     299          31 :         const oid *restrict start = si.base, *restrict end = ei.base;
     300          31 :         const void *nil = ATOMnilptr(tpe);
     301          31 :         int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe);
     302             : 
     303          31 :         switch (ATOMbasetype(tpe)) {
     304           1 :         case TYPE_bte:
     305          11 :                 ANALYTICAL_LAST_FIXED(bte);
     306             :                 break;
     307           0 :         case TYPE_sht:
     308           0 :                 ANALYTICAL_LAST_FIXED(sht);
     309             :                 break;
     310          22 :         case TYPE_int:
     311         339 :                 ANALYTICAL_LAST_FIXED(int);
     312             :                 break;
     313           1 :         case TYPE_lng:
     314          12 :                 ANALYTICAL_LAST_FIXED(lng);
     315             :                 break;
     316             : #ifdef HAVE_HGE
     317           0 :         case TYPE_hge:
     318           0 :                 ANALYTICAL_LAST_FIXED(hge);
     319             :                 break;
     320             : #endif
     321           0 :         case TYPE_flt:
     322           0 :                 ANALYTICAL_LAST_FIXED(flt);
     323             :                 break;
     324           2 :         case TYPE_dbl:
     325          14 :                 ANALYTICAL_LAST_FIXED(dbl);
     326             :                 break;
     327           5 :         default:{
     328           5 :                 if (ATOMvarsized(tpe)) {
     329          50 :                         for (; k < cnt; k++) {
     330          45 :                                 const void *curval = (end[k] > start[k]) ? BUNtvar(bi, end[k] - 1) : nil;
     331          45 :                                 if (tfastins_nocheckVAR(r, k, curval) != GDK_SUCCEED) {
     332           0 :                                         bat_iterator_end(&bi);
     333           0 :                                         bat_iterator_end(&si);
     334           0 :                                         bat_iterator_end(&ei);
     335           0 :                                         return GDK_FAIL;
     336             :                                 }
     337          45 :                                 has_nils |= atomcmp(curval, nil) == 0;
     338             :                         }
     339             :                 } else {
     340           0 :                         uint16_t width = r->twidth;
     341           0 :                         uint8_t *restrict rcast = (uint8_t *) Tloc(r, 0);
     342           0 :                         for (; k < cnt; k++) {
     343           0 :                                 const void *curval = (end[k] > start[k]) ? BUNtloc(bi, end[k] - 1) : nil;
     344           0 :                                 memcpy(rcast, curval, width);
     345           0 :                                 rcast += width;
     346           0 :                                 has_nils |= atomcmp(curval, nil) == 0;
     347             :                         }
     348             :                 }
     349             :         }
     350             :         }
     351          31 :         bat_iterator_end(&bi);
     352          31 :         bat_iterator_end(&si);
     353          31 :         bat_iterator_end(&ei);
     354          31 :         BATsetcount(r, cnt);
     355          31 :         r->tnonil = !has_nils;
     356          31 :         r->tnil = has_nils;
     357          31 :         return GDK_SUCCEED;
     358             : }
     359             : 
     360             : #define ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(TPE)                       \
     361             :         do {                                                            \
     362             :                 const TPE *bp = (TPE*)bi.base;                          \
     363             :                 TPE *rb = (TPE*)Tloc(r, 0);                             \
     364             :                 if (is_lng_nil(nth)) {                                  \
     365             :                         has_nils = true;                                \
     366             :                         for (; k < cnt; k++)                         \
     367             :                                 rb[k] = TPE##_nil;                      \
     368             :                 } else {                                                \
     369             :                         nth--;                                          \
     370             :                         for (; k < cnt; k++) {                               \
     371             :                                 const TPE *bs = bp + start[k];          \
     372             :                                 const TPE *be = bp + end[k];            \
     373             :                                 TPE curval = (be > bs && nth < (lng)(end[k] - start[k])) ? *(bs + nth) : TPE##_nil; \
     374             :                                 rb[k] = curval;                         \
     375             :                                 has_nils |= is_##TPE##_nil(curval);     \
     376             :                         }                                               \
     377             :                 }                                                       \
     378             :         } while (0)
     379             : 
     380             : #define ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE)                        \
     381             :         do {                                                            \
     382             :                 const TPE *bp = (TPE*)bi.base;                          \
     383             :                 TPE curval, *rb = (TPE*)Tloc(r, 0);                     \
     384             :                 for (; k < cnt; k++) {                                       \
     385             :                         lng lnth = tp[k];                               \
     386             :                         const TPE *bs = bp + start[k];                  \
     387             :                         const TPE *be = bp + end[k];                    \
     388             :                         if (!is_lng_nil(lnth) && lnth <= 0) goto invalidnth; \
     389             :                         if (is_lng_nil(lnth) || be <= bs || lnth - 1 > (lng)(end[k] - start[k])) { \
     390             :                                 curval = TPE##_nil;                     \
     391             :                                 has_nils = true;                        \
     392             :                         } else {                                        \
     393             :                                 curval = *(bs + lnth - 1);              \
     394             :                                 has_nils |= is_##TPE##_nil(curval);     \
     395             :                         }                                               \
     396             :                         rb[k] = curval;                                 \
     397             :                 }                                                       \
     398             :         } while (0)
     399             : 
     400             : gdk_return
     401          40 : GDKanalyticalnthvalue(BAT *r, BAT *b, BAT *s, BAT *e, BAT *t, lng *pnth, int tpe)
     402             : {
     403          40 :         BATiter bi = bat_iterator(b);
     404          40 :         BATiter si = bat_iterator(s);
     405          40 :         BATiter ei = bat_iterator(e);
     406          40 :         BATiter ti = bat_iterator(t);
     407             :         bool has_nils = false;
     408          40 :         oid k = 0, cnt = bi.count;
     409          40 :         const oid *restrict start = si.base, *restrict end = ei.base;
     410          40 :         lng nth = pnth ? *pnth : 0;
     411          40 :         const lng *restrict tp = ti.base;
     412          40 :         const void *nil = ATOMnilptr(tpe);
     413          40 :         int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe);
     414             : 
     415          40 :         if (t && t->ttype != TYPE_lng)
     416           0 :                 goto nosupport;
     417             : 
     418          40 :         if (t) {
     419           5 :                 switch (ATOMbasetype(tpe)) {
     420           3 :                 case TYPE_bte:
     421          33 :                         ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(bte);
     422             :                         break;
     423           0 :                 case TYPE_sht:
     424           0 :                         ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(sht);
     425             :                         break;
     426           2 :                 case TYPE_int:
     427          22 :                         ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(int);
     428             :                         break;
     429           0 :                 case TYPE_lng:
     430           0 :                         ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(lng);
     431             :                         break;
     432             : #ifdef HAVE_HGE
     433           0 :                 case TYPE_hge:
     434           0 :                         ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(hge);
     435             :                         break;
     436             : #endif
     437           0 :                 case TYPE_flt:
     438           0 :                         ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(flt);
     439             :                         break;
     440           0 :                 case TYPE_dbl:
     441           0 :                         ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(dbl);
     442             :                         break;
     443           0 :                 default:{
     444             :                         const void *curval = nil;
     445           0 :                         if (ATOMvarsized(tpe)) {
     446           0 :                                 for (; k < cnt; k++) {
     447           0 :                                         lng lnth = tp[k];
     448           0 :                                         if (!is_lng_nil(nth) && nth <= 0) goto invalidnth;
     449           0 :                                         if (is_lng_nil(lnth) || end[k] <= start[k] || lnth - 1 > (lng)(end[k] - start[k])) {
     450             :                                                 curval = (void *) nil;
     451             :                                                 has_nils = true;
     452             :                                         } else {
     453           0 :                                                 curval = BUNtvar(bi, start[k] + (oid)(lnth - 1));
     454           0 :                                                 has_nils |= atomcmp(curval, nil) == 0;
     455             :                                         }
     456           0 :                                         if (tfastins_nocheckVAR(r, k, curval) != GDK_SUCCEED) {
     457           0 :                                                 bat_iterator_end(&bi);
     458           0 :                                                 bat_iterator_end(&si);
     459           0 :                                                 bat_iterator_end(&ei);
     460           0 :                                                 bat_iterator_end(&ti);
     461           0 :                                                 return GDK_FAIL;
     462             :                                         }
     463             :                                 }
     464             :                         } else {
     465           0 :                                 uint8_t *restrict rcast = (uint8_t *) Tloc(r, 0);
     466           0 :                                 uint16_t width = r->twidth;
     467           0 :                                 for (; k < cnt; k++) {
     468           0 :                                         lng lnth = tp[k];
     469           0 :                                         if (!is_lng_nil(nth) && nth <= 0) goto invalidnth;
     470           0 :                                         if (is_lng_nil(lnth) || end[k] <= start[k] || lnth - 1 > (lng)(end[k] - start[k])) {
     471             :                                                 curval = (void *) nil;
     472             :                                                 has_nils = true;
     473             :                                         } else {
     474           0 :                                                 curval = BUNtloc(bi, start[k] + (oid)(lnth - 1));
     475           0 :                                                 has_nils |= atomcmp(curval, nil) == 0;
     476             :                                         }
     477           0 :                                         memcpy(rcast, curval, width);
     478           0 :                                         rcast += width;
     479             :                                 }
     480             :                         }
     481             :                 }
     482             :                 }
     483             :         } else {
     484          35 :                 if (!is_lng_nil(nth) && nth <= 0) {
     485           0 :                         goto invalidnth;
     486             :                 }
     487          35 :                 switch (ATOMbasetype(tpe)) {
     488           1 :                 case TYPE_bte:
     489          11 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(bte);
     490             :                         break;
     491           0 :                 case TYPE_sht:
     492           0 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(sht);
     493             :                         break;
     494          23 :                 case TYPE_int:
     495         243 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(int);
     496             :                         break;
     497           0 :                 case TYPE_lng:
     498           0 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(lng);
     499             :                         break;
     500             : #ifdef HAVE_HGE
     501           0 :                 case TYPE_hge:
     502           0 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(hge);
     503             :                         break;
     504             : #endif
     505           0 :                 case TYPE_flt:
     506           0 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(flt);
     507             :                         break;
     508           0 :                 case TYPE_dbl:
     509           0 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(dbl);
     510             :                         break;
     511          11 :                 default:{
     512          11 :                         if (ATOMvarsized(tpe)) {
     513          11 :                                 if (is_lng_nil(nth)) {
     514             :                                         has_nils = true;
     515           0 :                                         for (; k < cnt; k++)
     516           0 :                                                 if (tfastins_nocheckVAR(r, k, nil) != GDK_SUCCEED) {
     517           0 :                                                         bat_iterator_end(&bi);
     518           0 :                                                         bat_iterator_end(&si);
     519           0 :                                                         bat_iterator_end(&ei);
     520           0 :                                                         bat_iterator_end(&ti);
     521           0 :                                                         return GDK_FAIL;
     522             :                                                 }
     523             :                                 } else {
     524          11 :                                         nth--;
     525         112 :                                         for (; k < cnt; k++) {
     526         101 :                                                 const void *curval = (end[k] > start[k] && nth < (lng)(end[k] - start[k])) ? BUNtvar(bi, start[k] + (oid) nth) : nil;
     527         101 :                                                 if (tfastins_nocheckVAR(r, k, curval) != GDK_SUCCEED) {
     528           0 :                                                         bat_iterator_end(&bi);
     529           0 :                                                         bat_iterator_end(&si);
     530           0 :                                                         bat_iterator_end(&ei);
     531           0 :                                                         bat_iterator_end(&ti);
     532           0 :                                                         return GDK_FAIL;
     533             :                                                 }
     534         101 :                                                 has_nils |= atomcmp(curval, nil) == 0;
     535             :                                         }
     536             :                                 }
     537             :                         } else {
     538           0 :                                 uint16_t width = r->twidth;
     539           0 :                                 uint8_t *restrict rcast = (uint8_t *) Tloc(r, 0);
     540           0 :                                 if (is_lng_nil(nth)) {
     541             :                                         has_nils = true;
     542           0 :                                         for (; k < cnt; k++) {
     543           0 :                                                 memcpy(rcast, nil, width);
     544           0 :                                                 rcast += width;
     545             :                                         }
     546             :                                 } else {
     547           0 :                                         nth--;
     548           0 :                                         for (; k < cnt; k++) {
     549           0 :                                                 const void *curval = (end[k] > start[k] && nth < (lng)(end[k] - start[k])) ? BUNtloc(bi, start[k] + (oid) nth) : nil;
     550           0 :                                                 memcpy(rcast, curval, width);
     551           0 :                                                 rcast += width;
     552           0 :                                                 has_nils |= atomcmp(curval, nil) == 0;
     553             :                                         }
     554             :                                 }
     555             :                         }
     556             :                 }
     557             :                 }
     558             :         }
     559          40 :         bat_iterator_end(&bi);
     560          40 :         bat_iterator_end(&si);
     561          40 :         bat_iterator_end(&ei);
     562          40 :         bat_iterator_end(&ti);
     563             : 
     564          40 :         BATsetcount(r, cnt);
     565          40 :         r->tnonil = !has_nils;
     566          40 :         r->tnil = has_nils;
     567          40 :         return GDK_SUCCEED;
     568             : nosupport:
     569           0 :         bat_iterator_end(&bi);
     570           0 :         bat_iterator_end(&si);
     571           0 :         bat_iterator_end(&ei);
     572           0 :         bat_iterator_end(&ti);
     573           0 :         GDKerror("42000!type %s not supported for the nth_value.\n", ATOMname(t->ttype));
     574           0 :         return GDK_FAIL;
     575           0 : invalidnth:
     576           0 :         bat_iterator_end(&bi);
     577           0 :         bat_iterator_end(&si);
     578           0 :         bat_iterator_end(&ei);
     579           0 :         bat_iterator_end(&ti);
     580           0 :         GDKerror("42000!nth_value must be greater than zero.\n");
     581           0 :         return GDK_FAIL;
     582             : }
     583             : 
     584             : #define ANALYTICAL_LAG_CALC(TPE)                                \
     585             :         do {                                                    \
     586             :                 for (i = 0; i < lag && rb < rp; i++, rb++)        \
     587             :                         *rb = def;                              \
     588             :                 has_nils |= (lag > 0 && is_##TPE##_nil(def));        \
     589             :                 for (; rb < rp; rb++, bp++) {                        \
     590             :                         next = *bp;                             \
     591             :                         *rb = next;                             \
     592             :                         has_nils |= is_##TPE##_nil(next);       \
     593             :                 }                                               \
     594             :         } while (0)
     595             : 
     596             : #define ANALYTICAL_LAG_IMP(TPE)                                         \
     597             :         do {                                                            \
     598             :                 TPE *rp, *rb, *rend,                                    \
     599             :                         def = *((TPE *) default_value), next;           \
     600             :                 const TPE *bp, *nbp;                                    \
     601             :                 bp = (TPE*)bi.base;                                     \
     602             :                 rb = rp = (TPE*)Tloc(r, 0);                             \
     603             :                 rend = rb + cnt;                                        \
     604             :                 if (lag == BUN_NONE) {                                  \
     605             :                         has_nils = true;                                \
     606             :                         for (; rb < rend; rb++)                              \
     607             :                                 *rb = TPE##_nil;                        \
     608             :                 } else if (p) {                                         \
     609             :                         pnp = np = (bit*)pi.base;                       \
     610             :                         end = np + cnt;                                 \
     611             :                         for (; np < end; np++) {                     \
     612             :                                 if (*np) {                              \
     613             :                                         ncnt = (np - pnp);              \
     614             :                                         rp += ncnt;                     \
     615             :                                         nbp = bp + ncnt;                \
     616             :                                         ANALYTICAL_LAG_CALC(TPE);       \
     617             :                                         bp = nbp;                       \
     618             :                                         pnp = np;                       \
     619             :                                 }                                       \
     620             :                         }                                               \
     621             :                         rp += (np - pnp);                               \
     622             :                         ANALYTICAL_LAG_CALC(TPE);                       \
     623             :                 } else {                                                \
     624             :                         rp += cnt;                                      \
     625             :                         ANALYTICAL_LAG_CALC(TPE);                       \
     626             :                 }                                                       \
     627             :         } while (0)
     628             : 
     629             : #define ANALYTICAL_LAG_OTHERS                                           \
     630             :         do {                                                            \
     631             :                 for (i = 0; i < lag && k < j; i++, k++) {         \
     632             :                         if (BUNappend(r, default_value, false) != GDK_SUCCEED) { \
     633             :                                 bat_iterator_end(&bi);                      \
     634             :                                 bat_iterator_end(&pi);                      \
     635             :                                 return GDK_FAIL;                        \
     636             :                         }                                               \
     637             :                 }                                                       \
     638             :                 has_nils |= (lag > 0 && atomcmp(default_value, nil) == 0); \
     639             :                 for (l = k - lag; k < j; k++, l++) {                 \
     640             :                         curval = BUNtail(bi, l);                        \
     641             :                         if (BUNappend(r, curval, false) != GDK_SUCCEED) { \
     642             :                                 bat_iterator_end(&bi);                      \
     643             :                                 bat_iterator_end(&pi);                      \
     644             :                                 return GDK_FAIL;                        \
     645             :                         }                                               \
     646             :                         has_nils |= atomcmp(curval, nil) == 0;          \
     647             :                 }                                                       \
     648             :         } while (0)
     649             : 
     650             : gdk_return
     651          30 : GDKanalyticallag(BAT *r, BAT *b, BAT *p, BUN lag, const void *restrict default_value, int tpe)
     652             : {
     653          30 :         BATiter bi = bat_iterator(b);
     654          30 :         BATiter pi = bat_iterator(p);
     655             :         int (*atomcmp) (const void *, const void *);
     656             :         const void *restrict nil;
     657          30 :         BUN i = 0, j = 0, k = 0, l = 0, ncnt, cnt = BATcount(b);
     658             :         bit *np, *pnp, *end;
     659             :         bool has_nils = false;
     660             : 
     661          30 :         assert(default_value);
     662             : 
     663          30 :         switch (ATOMbasetype(tpe)) {
     664           3 :         case TYPE_bte:
     665          33 :                 ANALYTICAL_LAG_IMP(bte);
     666             :                 break;
     667           0 :         case TYPE_sht:
     668           0 :                 ANALYTICAL_LAG_IMP(sht);
     669             :                 break;
     670          21 :         case TYPE_int:
     671         337 :                 ANALYTICAL_LAG_IMP(int);
     672             :                 break;
     673           1 :         case TYPE_lng:
     674          23 :                 ANALYTICAL_LAG_IMP(lng);
     675             :                 break;
     676             : #ifdef HAVE_HGE
     677           0 :         case TYPE_hge:
     678           0 :                 ANALYTICAL_LAG_IMP(hge);
     679             :                 break;
     680             : #endif
     681           0 :         case TYPE_flt:
     682           0 :                 ANALYTICAL_LAG_IMP(flt);
     683             :                 break;
     684           0 :         case TYPE_dbl:
     685           0 :                 ANALYTICAL_LAG_IMP(dbl);
     686             :                 break;
     687           5 :         default:{
     688             :                 const void *restrict curval;
     689           5 :                 nil = ATOMnilptr(tpe);
     690           5 :                 atomcmp = ATOMcompare(tpe);
     691           5 :                 if (lag == BUN_NONE) {
     692             :                         has_nils = true;
     693           0 :                         for (j = 0; j < cnt; j++) {
     694           0 :                                 if (BUNappend(r, nil, false) != GDK_SUCCEED) {
     695           0 :                                         bat_iterator_end(&bi);
     696           0 :                                         bat_iterator_end(&pi);
     697           0 :                                         return GDK_FAIL;
     698             :                                 }
     699             :                         }
     700           5 :                 } else if (p) {
     701           3 :                         pnp = np = (bit *) pi.base;
     702           3 :                         end = np + cnt;
     703          30 :                         for (; np < end; np++) {
     704          27 :                                 if (*np) {
     705           9 :                                         j += (np - pnp);
     706          31 :                                         ANALYTICAL_LAG_OTHERS;
     707             :                                         pnp = np;
     708             :                                 }
     709             :                         }
     710           3 :                         j += (np - pnp);
     711           8 :                         ANALYTICAL_LAG_OTHERS;
     712             :                 } else {
     713             :                         j += cnt;
     714          20 :                         ANALYTICAL_LAG_OTHERS;
     715             :                 }
     716             :         }
     717             :         }
     718          30 :         bat_iterator_end(&bi);
     719          30 :         bat_iterator_end(&pi);
     720          30 :         BATsetcount(r, cnt);
     721          30 :         r->tnonil = !has_nils;
     722          30 :         r->tnil = has_nils;
     723          30 :         return GDK_SUCCEED;
     724             : }
     725             : 
     726             : #define LEAD_CALC(TPE)                                                  \
     727             :         do {                                                            \
     728             :                 if (lead < ncnt) {                                   \
     729             :                         bp += lead;                                     \
     730             :                         l = ncnt - lead;                                \
     731             :                         for (i = 0; i < l; i++, rb++, bp++) {                \
     732             :                                 next = *bp;                             \
     733             :                                 *rb = next;                             \
     734             :                                 has_nils |= is_##TPE##_nil(next);       \
     735             :                         }                                               \
     736             :                 } else {                                                \
     737             :                         bp += ncnt;                                     \
     738             :                 }                                                       \
     739             :                 for (;rb < rp; rb++)                                 \
     740             :                         *rb = def;                                      \
     741             :                 has_nils |= (lead > 0 && is_##TPE##_nil(def));               \
     742             :         } while (0)
     743             : 
     744             : #define ANALYTICAL_LEAD_IMP(TPE)                                \
     745             :         do {                                                    \
     746             :                 TPE *rp, *rb, *bp, *rend,                       \
     747             :                         def = *((TPE *) default_value), next;   \
     748             :                 bp = (TPE*)bi.base;                             \
     749             :                 rb = rp = (TPE*)Tloc(r, 0);                     \
     750             :                 rend = rb + cnt;                                \
     751             :                 if (lead == BUN_NONE) {                         \
     752             :                         has_nils = true;                        \
     753             :                         for (; rb < rend; rb++)                      \
     754             :                                 *rb = TPE##_nil;                \
     755             :                 } else if (p) {                                 \
     756             :                         pnp = np = (bit*)pi.base;               \
     757             :                         end = np + cnt;                         \
     758             :                         for (; np < end; np++) {             \
     759             :                                 if (*np) {                      \
     760             :                                         ncnt = (np - pnp);      \
     761             :                                         rp += ncnt;             \
     762             :                                         LEAD_CALC(TPE);         \
     763             :                                         pnp = np;               \
     764             :                                 }                               \
     765             :                         }                                       \
     766             :                         ncnt = (np - pnp);                      \
     767             :                         rp += ncnt;                             \
     768             :                         LEAD_CALC(TPE);                         \
     769             :                 } else {                                        \
     770             :                         ncnt = cnt;                             \
     771             :                         rp += ncnt;                             \
     772             :                         LEAD_CALC(TPE);                         \
     773             :                 }                                               \
     774             :         } while (0)
     775             : 
     776             : #define ANALYTICAL_LEAD_OTHERS                                          \
     777             :         do {                                                            \
     778             :                 j += ncnt;                                              \
     779             :                 if (lead < ncnt) {                                   \
     780             :                         m = ncnt - lead;                                \
     781             :                         for (i = 0,n = k + lead; i < m; i++, n++) {  \
     782             :                                 curval = BUNtail(bi, n);                \
     783             :                                 if (BUNappend(r, curval, false) != GDK_SUCCEED) { \
     784             :                                         bat_iterator_end(&bi);              \
     785             :                                         bat_iterator_end(&pi);              \
     786             :                                         return GDK_FAIL;                \
     787             :                                 }                                       \
     788             :                                 has_nils |= atomcmp(curval, nil) == 0;  \
     789             :                         }                                               \
     790             :                         k += i;                                         \
     791             :                 }                                                       \
     792             :                 for (; k < j; k++) {                                 \
     793             :                         if (BUNappend(r, default_value, false) != GDK_SUCCEED) { \
     794             :                                 bat_iterator_end(&bi);                      \
     795             :                                 bat_iterator_end(&pi);                      \
     796             :                                 return GDK_FAIL;                        \
     797             :                         }                                               \
     798             :                 }                                                       \
     799             :                 has_nils |= (lead > 0 && atomcmp(default_value, nil) == 0); \
     800             :         } while (0)
     801             : 
     802             : gdk_return
     803          29 : GDKanalyticallead(BAT *r, BAT *b, BAT *p, BUN lead, const void *restrict default_value, int tpe)
     804             : {
     805          29 :         BATiter bi = bat_iterator(b);
     806          29 :         BATiter pi = bat_iterator(p);
     807             :         int (*atomcmp) (const void *, const void *);
     808             :         const void *restrict nil;
     809          29 :         BUN i = 0, j = 0, k = 0, l = 0, ncnt, cnt = BATcount(b);
     810             :         bit *np, *pnp, *end;
     811             :         bool has_nils = false;
     812             : 
     813          29 :         assert(default_value);
     814             : 
     815          29 :         switch (ATOMbasetype(tpe)) {
     816           4 :         case TYPE_bte:
     817          37 :                 ANALYTICAL_LEAD_IMP(bte);
     818             :                 break;
     819           0 :         case TYPE_sht:
     820           0 :                 ANALYTICAL_LEAD_IMP(sht);
     821             :                 break;
     822          18 :         case TYPE_int:
     823         314 :                 ANALYTICAL_LEAD_IMP(int);
     824             :                 break;
     825           1 :         case TYPE_lng:
     826          24 :                 ANALYTICAL_LEAD_IMP(lng);
     827             :                 break;
     828             : #ifdef HAVE_HGE
     829           0 :         case TYPE_hge:
     830           0 :                 ANALYTICAL_LEAD_IMP(hge);
     831             :                 break;
     832             : #endif
     833           0 :         case TYPE_flt:
     834           0 :                 ANALYTICAL_LEAD_IMP(flt);
     835             :                 break;
     836           0 :         case TYPE_dbl:
     837           0 :                 ANALYTICAL_LEAD_IMP(dbl);
     838             :                 break;
     839           6 :         default:{
     840             :                 BUN m = 0, n = 0;
     841             :                 const void *restrict curval;
     842           6 :                 nil = ATOMnilptr(tpe);
     843           6 :                 atomcmp = ATOMcompare(tpe);
     844           6 :                 if (lead == BUN_NONE) {
     845             :                         has_nils = true;
     846           0 :                         for (j = 0; j < cnt; j++) {
     847           0 :                                 if (BUNappend(r, nil, false) != GDK_SUCCEED) {
     848           0 :                                         bat_iterator_end(&bi);
     849           0 :                                         bat_iterator_end(&pi);
     850           0 :                                         return GDK_FAIL;
     851             :                                 }
     852             :                         }
     853           6 :                 } else if (p) {
     854           4 :                         pnp = np = (bit *) pi.base;
     855           4 :                         end = np + cnt;
     856          42 :                         for (; np < end; np++) {
     857          38 :                                 if (*np) {
     858          12 :                                         ncnt = (np - pnp);
     859          56 :                                         ANALYTICAL_LEAD_OTHERS;
     860             :                                         pnp = np;
     861             :                                 }
     862             :                         }
     863           4 :                         ncnt = (np - pnp);
     864          14 :                         ANALYTICAL_LEAD_OTHERS;
     865             :                 } else {
     866             :                         ncnt = cnt;
     867          22 :                         ANALYTICAL_LEAD_OTHERS;
     868             :                 }
     869             :         }
     870             :         }
     871          29 :         bat_iterator_end(&bi);
     872          29 :         bat_iterator_end(&pi);
     873          29 :         BATsetcount(r, cnt);
     874          29 :         r->tnonil = !has_nils;
     875          29 :         r->tnil = has_nils;
     876          29 :         return GDK_SUCCEED;
     877             : }
     878             : 
     879             : #define ANALYTICAL_MIN_MAX_CALC_FIXED_UNBOUNDED_TILL_CURRENT_ROW(TPE, MIN_MAX) \
     880             :         do {                                                            \
     881             :                 TPE curval = TPE##_nil;                                 \
     882             :                 for (; k < i;) {                                     \
     883             :                         j = k;                                          \
     884             :                         do {                                            \
     885             :                                 if (!is_##TPE##_nil(bp[k])) {           \
     886             :                                         if (is_##TPE##_nil(curval))     \
     887             :                                                 curval = bp[k];         \
     888             :                                         else                            \
     889             :                                                 curval = MIN_MAX(bp[k], curval); \
     890             :                                 }                                       \
     891             :                                 k++;                                    \
     892             :                         } while (k < i && !op[k]);                   \
     893             :                         for (; j < k; j++)                           \
     894             :                                 rb[j] = curval;                         \
     895             :                         has_nils |= is_##TPE##_nil(curval);             \
     896             :                 }                                                       \
     897             :         } while (0)
     898             : 
     899             : #define ANALYTICAL_MIN_MAX_CALC_FIXED_CURRENT_ROW_TILL_UNBOUNDED(TPE, MIN_MAX) \
     900             :         do {                                                            \
     901             :                 TPE curval = TPE##_nil;                                 \
     902             :                 l = i - 1;                                              \
     903             :                 for (j = l; ; j--) {                                    \
     904             :                         if (!is_##TPE##_nil(bp[j])) {                   \
     905             :                                 if (is_##TPE##_nil(curval))             \
     906             :                                         curval = bp[j];                 \
     907             :                                 else                                    \
     908             :                                         curval = MIN_MAX(bp[j], curval); \
     909             :                         }                                               \
     910             :                         if (op[j] || j == k) {                          \
     911             :                                 for (; ; l--) {                         \
     912             :                                         rb[l] = curval;                 \
     913             :                                         if (l == j)                     \
     914             :                                                 break;                  \
     915             :                                 }                                       \
     916             :                                 has_nils |= is_##TPE##_nil(curval);     \
     917             :                                 if (j == k)                             \
     918             :                                         break;                          \
     919             :                                 l = j - 1;                              \
     920             :                         }                                               \
     921             :                 }                                                       \
     922             :                 k = i;                                                  \
     923             :         } while (0)
     924             : 
     925             : #define ANALYTICAL_MIN_MAX_CALC_FIXED_ALL_ROWS(TPE, MIN_MAX)            \
     926             :         do {                                                            \
     927             :                 TPE curval = TPE##_nil;                                 \
     928             :                 for (j = k; j < i; j++) {                            \
     929             :                         TPE v = bp[j];                                  \
     930             :                         if (!is_##TPE##_nil(v)) {                       \
     931             :                                 if (is_##TPE##_nil(curval))             \
     932             :                                         curval = v;                     \
     933             :                                 else                                    \
     934             :                                         curval = MIN_MAX(v, curval);    \
     935             :                         }                                               \
     936             :                 }                                                       \
     937             :                 for (; k < i; k++)                                   \
     938             :                         rb[k] = curval;                                 \
     939             :                 has_nils |= is_##TPE##_nil(curval);                     \
     940             :         } while (0)
     941             : 
     942             : #define ANALYTICAL_MIN_MAX_CALC_FIXED_CURRENT_ROW(TPE, MIN_MAX) \
     943             :         do {                                                    \
     944             :                 for (; k < i; k++) {                         \
     945             :                         TPE v = bp[k];                          \
     946             :                         rb[k] = v;                              \
     947             :                         has_nils |= is_##TPE##_nil(v);          \
     948             :                 }                                               \
     949             :         } while (0)
     950             : 
     951             : #define INIT_AGGREGATE_MIN_MAX_FIXED(TPE, MIN_MAX, NOTHING)     \
     952             :         do {                                                    \
     953             :                 computed = TPE##_nil;                           \
     954             :         } while (0)
     955             : #define COMPUTE_LEVEL0_MIN_MAX_FIXED(X, TPE, MIN_MAX, NOTHING)  \
     956             :         do {                                                    \
     957             :                 computed = bp[j + X];                           \
     958             :         } while (0)
     959             : #define COMPUTE_LEVELN_MIN_MAX_FIXED(VAL, TPE, MIN_MAX, NOTHING)        \
     960             :         do {                                                            \
     961             :                 if (!is_##TPE##_nil(VAL)) {                             \
     962             :                         if (is_##TPE##_nil(computed))                   \
     963             :                                 computed = VAL;                         \
     964             :                         else                                            \
     965             :                                 computed = MIN_MAX(computed, VAL);      \
     966             :                 }                                                       \
     967             :         } while (0)
     968             : #define FINALIZE_AGGREGATE_MIN_MAX_FIXED(TPE, MIN_MAX, NOTHING) \
     969             :         do {                                                    \
     970             :                 rb[k] = computed;                               \
     971             :                 has_nils |= is_##TPE##_nil(computed);           \
     972             :         } while (0)
     973             : #define ANALYTICAL_MIN_MAX_CALC_FIXED_OTHERS(TPE, MIN_MAX)              \
     974             :         do {                                                            \
     975             :                 oid ncount = i - k;                                     \
     976             :                 if ((res = GDKrebuild_segment_tree(ncount, sizeof(TPE), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
     977             :                         goto cleanup;                                   \
     978             :                 populate_segment_tree(TPE, ncount, INIT_AGGREGATE_MIN_MAX_FIXED, COMPUTE_LEVEL0_MIN_MAX_FIXED, COMPUTE_LEVELN_MIN_MAX_FIXED, TPE, MIN_MAX, NOTHING); \
     979             :                 for (; k < i; k++)                                   \
     980             :                         compute_on_segment_tree(TPE, start[k] - j, end[k] - j, INIT_AGGREGATE_MIN_MAX_FIXED, COMPUTE_LEVELN_MIN_MAX_FIXED, FINALIZE_AGGREGATE_MIN_MAX_FIXED, TPE, MIN_MAX, NOTHING); \
     981             :                 j = k;                                                  \
     982             :         } while (0)
     983             : 
     984             : #define ANALYTICAL_MIN_MAX_CALC_OTHERS_UNBOUNDED_TILL_CURRENT_ROW(GT_LT) \
     985             :         do {                                                            \
     986             :                 const void *curval = nil;                               \
     987             :                 if (ATOMvarsized(tpe)) {                                \
     988             :                         for (; k < i;) {                             \
     989             :                                 j = k;                                  \
     990             :                                 do {                                    \
     991             :                                         void *next = BUNtvar(bi, k);    \
     992             :                                         if (atomcmp(next, nil) != 0) {  \
     993             :                                                 if (atomcmp(curval, nil) == 0) \
     994             :                                                         curval = next;  \
     995             :                                                 else                    \
     996             :                                                         curval = atomcmp(next, curval) GT_LT 0 ? curval : next; \
     997             :                                         }                               \
     998             :                                         k++;                            \
     999             :                                 } while (k < i && !op[k]);           \
    1000             :                                 for (; j < k; j++)                   \
    1001             :                                         if ((res = tfastins_nocheckVAR(r, j, curval)) != GDK_SUCCEED) \
    1002             :                                                 goto cleanup;           \
    1003             :                                 has_nils |= atomcmp(curval, nil) == 0;  \
    1004             :                         }                                               \
    1005             :                 } else {                                                \
    1006             :                         for (; k < i;) {                             \
    1007             :                                 j = k;                                  \
    1008             :                                 do {                                    \
    1009             :                                         void *next = BUNtloc(bi, k);    \
    1010             :                                         if (atomcmp(next, nil) != 0) {  \
    1011             :                                                 if (atomcmp(curval, nil) == 0) \
    1012             :                                                         curval = next;  \
    1013             :                                                 else                    \
    1014             :                                                         curval = atomcmp(next, curval) GT_LT 0 ? curval : next; \
    1015             :                                         }                               \
    1016             :                                         k++;                            \
    1017             :                                 } while (k < i && !op[k]);           \
    1018             :                                 for (; j < k; j++) {                 \
    1019             :                                         memcpy(rcast, curval, width);   \
    1020             :                                         rcast += width;                 \
    1021             :                                 }                                       \
    1022             :                                 has_nils |= atomcmp(curval, nil) == 0;  \
    1023             :                         }                                               \
    1024             :                 }                                                       \
    1025             :         } while (0)
    1026             : 
    1027             : #define ANALYTICAL_MIN_MAX_CALC_OTHERS_CURRENT_ROW_TILL_UNBOUNDED(GT_LT) \
    1028             :         do {                                                            \
    1029             :                 const void *curval = nil;                               \
    1030             :                 l = i - 1;                                              \
    1031             :                 if (ATOMvarsized(tpe)) {                                \
    1032             :                         for (j = l; ; j--) {                            \
    1033             :                                 void *next = BUNtvar(bi, j);            \
    1034             :                                 if (atomcmp(next, nil) != 0) {          \
    1035             :                                         if (atomcmp(curval, nil) == 0)  \
    1036             :                                                 curval = next;          \
    1037             :                                         else                            \
    1038             :                                                 curval = atomcmp(next, curval) GT_LT 0 ? curval : next; \
    1039             :                                 }                                       \
    1040             :                                 if (op[j] || j == k) {                  \
    1041             :                                         for (; ; l--) {                 \
    1042             :                                                 if ((res = tfastins_nocheckVAR(r, l, curval)) != GDK_SUCCEED) \
    1043             :                                                         goto cleanup;   \
    1044             :                                                 if (l == j)             \
    1045             :                                                         break;          \
    1046             :                                         }                               \
    1047             :                                         has_nils |= atomcmp(curval, nil) == 0; \
    1048             :                                         if (j == k)                     \
    1049             :                                                 break;                  \
    1050             :                                         l = j - 1;                      \
    1051             :                                 }                                       \
    1052             :                         }                                               \
    1053             :                 } else {                                                \
    1054             :                         for (j = l; ; j--) {                            \
    1055             :                                 void *next = BUNtloc(bi, j);            \
    1056             :                                 if (atomcmp(next, nil) != 0) {          \
    1057             :                                         if (atomcmp(curval, nil) == 0)  \
    1058             :                                                 curval = next;          \
    1059             :                                         else                            \
    1060             :                                                 curval = atomcmp(next, curval) GT_LT 0 ? curval : next; \
    1061             :                                 }                                       \
    1062             :                                 if (op[j] || j == k) {                  \
    1063             :                                         BUN x = l * width;              \
    1064             :                                         for (; ; l--) {                 \
    1065             :                                                 memcpy(rcast + x, curval, width); \
    1066             :                                                 x -= width;             \
    1067             :                                                 if (l == j)             \
    1068             :                                                         break;          \
    1069             :                                         }                               \
    1070             :                                         has_nils |= atomcmp(curval, nil) == 0; \
    1071             :                                         if (j == k)                     \
    1072             :                                                 break;                  \
    1073             :                                         l = j - 1;                      \
    1074             :                                 }                                       \
    1075             :                         }                                               \
    1076             :                 }                                                       \
    1077             :                 k = i;                                                  \
    1078             :         } while (0)
    1079             : 
    1080             : #define ANALYTICAL_MIN_MAX_CALC_OTHERS_ALL_ROWS(GT_LT)                  \
    1081             :         do {                                                            \
    1082             :                 void *curval = (void*) nil;                             \
    1083             :                 if (ATOMvarsized(tpe)) {                                \
    1084             :                         for (j = k; j < i; j++) {                    \
    1085             :                                 void *next = BUNtvar(bi, j);            \
    1086             :                                 if (atomcmp(next, nil) != 0) {          \
    1087             :                                         if (atomcmp(curval, nil) == 0)  \
    1088             :                                                 curval = next;          \
    1089             :                                         else                            \
    1090             :                                                 curval = atomcmp(next, curval) GT_LT 0 ? curval : next; \
    1091             :                                 }                                       \
    1092             :                         }                                               \
    1093             :                         for (; k < i; k++)                           \
    1094             :                                 if ((res = tfastins_nocheckVAR(r, k, curval)) != GDK_SUCCEED) \
    1095             :                                         goto cleanup;                   \
    1096             :                 } else {                                                \
    1097             :                         for (j = k; j < i; j++) {                    \
    1098             :                                 void *next = BUNtloc(bi, j);            \
    1099             :                                 if (atomcmp(next, nil) != 0) {          \
    1100             :                                         if (atomcmp(curval, nil) == 0)  \
    1101             :                                                 curval = next;          \
    1102             :                                         else                            \
    1103             :                                                 curval = atomcmp(next, curval) GT_LT 0 ? curval : next; \
    1104             :                                 }                                       \
    1105             :                         }                                               \
    1106             :                         for (; k < i; k++) {                         \
    1107             :                                 memcpy(rcast, curval, width);           \
    1108             :                                 rcast += width;                         \
    1109             :                         }                                               \
    1110             :                 }                                                       \
    1111             :                 has_nils |= atomcmp(curval, nil) == 0;                  \
    1112             :         } while (0)
    1113             : 
    1114             : #define ANALYTICAL_MIN_MAX_CALC_OTHERS_CURRENT_ROW(GT_LT)               \
    1115             :         do {                                                            \
    1116             :                 if (ATOMvarsized(tpe)) {                                \
    1117             :                         for (; k < i; k++) {                         \
    1118             :                                 void *next = BUNtvar(bi, k);            \
    1119             :                                 if ((res = tfastins_nocheckVAR(r, k, next)) != GDK_SUCCEED) \
    1120             :                                         goto cleanup;                   \
    1121             :                                 has_nils |= atomcmp(next, nil) == 0;    \
    1122             :                         }                                               \
    1123             :                 } else {                                                \
    1124             :                         for (; k < i; k++) {                         \
    1125             :                                 void *next = BUNtloc(bi, k);            \
    1126             :                                 memcpy(rcast, next, width);             \
    1127             :                                 rcast += width;                         \
    1128             :                                 has_nils |= atomcmp(next, nil) == 0;    \
    1129             :                         }                                               \
    1130             :                 }                                                       \
    1131             :         } while (0)
    1132             : 
    1133             : #define INIT_AGGREGATE_MIN_MAX_OTHERS(GT_LT, NOTHING1, NOTHING2)        \
    1134             :         do {                                                            \
    1135             :                 computed = (void*) nil;                                 \
    1136             :         } while (0)
    1137             : #define COMPUTE_LEVEL0_MIN_MAX_OTHERS(X, GT_LT, NOTHING1, NOTHING2)     \
    1138             :         do {                                                            \
    1139             :                 computed = BUNtail(bi, j + X);                          \
    1140             :         } while (0)
    1141             : #define COMPUTE_LEVELN_MIN_MAX_OTHERS(VAL, GT_LT, NOTHING1, NOTHING2)   \
    1142             :         do {                                                            \
    1143             :                 if (atomcmp(VAL, nil) != 0) {                           \
    1144             :                         if (atomcmp(computed, nil) == 0)                \
    1145             :                                 computed = VAL;                         \
    1146             :                         else                                            \
    1147             :                                 computed = atomcmp(VAL, computed) GT_LT 0 ? computed : VAL; \
    1148             :                 }                                                       \
    1149             :         } while (0)
    1150             : #define FINALIZE_AGGREGATE_MIN_MAX_OTHERS(GT_LT, NOTHING1, NOTHING2)    \
    1151             :         do {                                                            \
    1152             :                 if (ATOMvarsized(tpe)) {                                \
    1153             :                         if ((res = tfastins_nocheckVAR(r, k, computed)) != GDK_SUCCEED) \
    1154             :                                 goto cleanup;                           \
    1155             :                 } else {                                                \
    1156             :                         memcpy(rcast, computed, width);                 \
    1157             :                         rcast += width;                                 \
    1158             :                 }                                                       \
    1159             :                 has_nils |= atomcmp(computed, nil) == 0;                \
    1160             :         } while (0)
    1161             : #define ANALYTICAL_MIN_MAX_CALC_OTHERS_OTHERS(GT_LT)                    \
    1162             :         do {                                                            \
    1163             :                 oid ncount = i - k;                                     \
    1164             :                 if ((res = GDKrebuild_segment_tree(ncount, sizeof(void*), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    1165             :                         goto cleanup;                                   \
    1166             :                 populate_segment_tree(void*, ncount, INIT_AGGREGATE_MIN_MAX_OTHERS, COMPUTE_LEVEL0_MIN_MAX_OTHERS, COMPUTE_LEVELN_MIN_MAX_OTHERS, GT_LT, NOTHING, NOTHING); \
    1167             :                 for (; k < i; k++)                                   \
    1168             :                         compute_on_segment_tree(void*, start[k] - j, end[k] - j, INIT_AGGREGATE_MIN_MAX_OTHERS, COMPUTE_LEVELN_MIN_MAX_OTHERS, FINALIZE_AGGREGATE_MIN_MAX_OTHERS, GT_LT, NOTHING, NOTHING); \
    1169             :                 j = k;                                                  \
    1170             :         } while (0)
    1171             : 
    1172             : #define ANALYTICAL_MIN_MAX_PARTITIONS(TPE, MIN_MAX, IMP)                \
    1173             :         do {                                                            \
    1174             :                 TPE *restrict bp = (TPE*)bi.base, *rb = (TPE*)Tloc(r, 0); \
    1175             :                 if (p) {                                                \
    1176             :                         while (i < cnt) {                            \
    1177             :                                 if (np[i])      {                       \
    1178             : minmaxfixed##TPE##IMP:                                                  \
    1179             :                                         ANALYTICAL_MIN_MAX_CALC_FIXED_##IMP(TPE, MIN_MAX); \
    1180             :                                 }                                       \
    1181             :                                 if (!last)                              \
    1182             :                                         i++;                            \
    1183             :                         }                                               \
    1184             :                 }                                                       \
    1185             :                 if (!last) { /* hack to reduce code explosion, there's no need to duplicate the code to iterate each partition */ \
    1186             :                         last = true;                                    \
    1187             :                         i = cnt;                                        \
    1188             :                         goto minmaxfixed##TPE##IMP;                     \
    1189             :                 }                                                       \
    1190             :         } while (0)
    1191             : 
    1192             : #ifdef HAVE_HGE
    1193             : #define ANALYTICAL_MIN_MAX_LIMIT(MIN_MAX, IMP)                          \
    1194             :         case TYPE_hge:                                                  \
    1195             :                 ANALYTICAL_MIN_MAX_PARTITIONS(hge, MIN_MAX, IMP);       \
    1196             :         break;
    1197             : #else
    1198             : #define ANALYTICAL_MIN_MAX_LIMIT(MIN_MAX, IMP)
    1199             : #endif
    1200             : 
    1201             : #define ANALYTICAL_MIN_MAX_BRANCHES(MIN_MAX, GT_LT, IMP)                \
    1202             :         do {                                                            \
    1203             :                 switch (ATOMbasetype(tpe)) {                            \
    1204             :                 case TYPE_bte:                                          \
    1205             :                         ANALYTICAL_MIN_MAX_PARTITIONS(bte, MIN_MAX, IMP); \
    1206             :                         break;                                          \
    1207             :                 case TYPE_sht:                                          \
    1208             :                         ANALYTICAL_MIN_MAX_PARTITIONS(sht, MIN_MAX, IMP); \
    1209             :                         break;                                          \
    1210             :                 case TYPE_int:                                          \
    1211             :                         ANALYTICAL_MIN_MAX_PARTITIONS(int, MIN_MAX, IMP); \
    1212             :                         break;                                          \
    1213             :                 case TYPE_lng:                                          \
    1214             :                         ANALYTICAL_MIN_MAX_PARTITIONS(lng, MIN_MAX, IMP); \
    1215             :                         break;                                          \
    1216             :                         ANALYTICAL_MIN_MAX_LIMIT(MIN_MAX, IMP)          \
    1217             :                 case TYPE_flt:                                          \
    1218             :                         ANALYTICAL_MIN_MAX_PARTITIONS(flt, MIN_MAX, IMP); \
    1219             :                         break;                                          \
    1220             :                 case TYPE_dbl:                                          \
    1221             :                         ANALYTICAL_MIN_MAX_PARTITIONS(dbl, MIN_MAX, IMP); \
    1222             :                         break;                                          \
    1223             :                 default: {                                              \
    1224             :                         if (p) {                                        \
    1225             :                                 while (i < cnt) {                    \
    1226             :                                         if (np[i])      {               \
    1227             : minmaxvarsized##IMP:                                                    \
    1228             :                                                 ANALYTICAL_MIN_MAX_CALC_OTHERS_##IMP(GT_LT); \
    1229             :                                         }                               \
    1230             :                                         if (!last)                      \
    1231             :                                                 i++;                    \
    1232             :                                 }                                       \
    1233             :                         }                                               \
    1234             :                         if (!last) {                                    \
    1235             :                                 last = true;                            \
    1236             :                                 i = cnt;                                \
    1237             :                                 goto minmaxvarsized##IMP;               \
    1238             :                         }                                               \
    1239             :                 }                                                       \
    1240             :                 }                                                       \
    1241             :         } while (0)
    1242             : 
    1243             : #define ANALYTICAL_MIN_MAX(OP, MIN_MAX, GT_LT)                          \
    1244             : gdk_return                                                              \
    1245             : GDKanalytical##OP(BAT *r, BAT *p, BAT *o, BAT *b, BAT *s, BAT *e, int tpe, int frame_type) \
    1246             : {                                                                       \
    1247             :         BATiter pi = bat_iterator(p);                                   \
    1248             :         BATiter oi = bat_iterator(o);                                   \
    1249             :         BATiter bi = bat_iterator(b);                                   \
    1250             :         BATiter si = bat_iterator(s);                                   \
    1251             :         BATiter ei = bat_iterator(e);                                   \
    1252             :         bool has_nils = false, last = false;                            \
    1253             :         oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b), *restrict start = si.base, *restrict end = ei.base, \
    1254             :                 *levels_offset = NULL, tree_capacity = 0, nlevels = 0;  \
    1255             :         bit *np = pi.base, *op = oi.base;                               \
    1256             :         const void *nil = ATOMnilptr(tpe);                              \
    1257             :         int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe);  \
    1258             :         void *segment_tree = NULL;                                      \
    1259             :         gdk_return res = GDK_SUCCEED;                                   \
    1260             :         uint16_t width = r->twidth;                                  \
    1261             :         uint8_t *restrict rcast = (uint8_t *) Tloc(r, 0);               \
    1262             :                                                                         \
    1263             :         if (cnt > 0) {                                                       \
    1264             :                 switch (frame_type) {                                   \
    1265             :                 case 3: /* unbounded until current row */       {       \
    1266             :                         ANALYTICAL_MIN_MAX_BRANCHES(MIN_MAX, GT_LT, UNBOUNDED_TILL_CURRENT_ROW); \
    1267             :                 } break;                                                \
    1268             :                 case 4: /* current row until unbounded */       {       \
    1269             :                         ANALYTICAL_MIN_MAX_BRANCHES(MIN_MAX, GT_LT, CURRENT_ROW_TILL_UNBOUNDED); \
    1270             :                 } break;                                                \
    1271             :                 case 5: /* all rows */  {                               \
    1272             :                         ANALYTICAL_MIN_MAX_BRANCHES(MIN_MAX, GT_LT, ALL_ROWS); \
    1273             :                 } break;                                                \
    1274             :                 case 6: /* current row */ {                             \
    1275             :                         ANALYTICAL_MIN_MAX_BRANCHES(MIN_MAX, GT_LT, CURRENT_ROW); \
    1276             :                 } break;                                                \
    1277             :                 default: {                                              \
    1278             :                         ANALYTICAL_MIN_MAX_BRANCHES(MIN_MAX, GT_LT, OTHERS); \
    1279             :                 }                                                       \
    1280             :                 }                                                       \
    1281             :         }                                                               \
    1282             :                                                                         \
    1283             :         BATsetcount(r, cnt);                                            \
    1284             :         r->tnonil = !has_nils;                                               \
    1285             :         r->tnil = has_nils;                                          \
    1286             : cleanup:                                                                \
    1287             :         bat_iterator_end(&pi);                                              \
    1288             :         bat_iterator_end(&oi);                                              \
    1289             :         bat_iterator_end(&bi);                                              \
    1290             :         bat_iterator_end(&si);                                              \
    1291             :         bat_iterator_end(&ei);                                              \
    1292             :         GDKfree(segment_tree);                                          \
    1293             :         return res;                                                     \
    1294             : }
    1295             : 
    1296        3243 : ANALYTICAL_MIN_MAX(min, MIN, >)
    1297    17140846 : ANALYTICAL_MIN_MAX(max, MAX, <)
    1298             : 
    1299             : /* Counting no nils for fixed sizes */
    1300             : #define ANALYTICAL_COUNT_FIXED_UNBOUNDED_TILL_CURRENT_ROW(TPE)          \
    1301             :         do {                                                            \
    1302             :                 curval = 0;                                             \
    1303             :                 if (count_all) {                                        \
    1304             :                         for (; k < i;) {                             \
    1305             :                                 j = k;                                  \
    1306             :                                 do {                                    \
    1307             :                                         k++;                            \
    1308             :                                 } while (k < i && !op[k]);           \
    1309             :                                 curval += k - j;                        \
    1310             :                                 for (; j < k; j++)                   \
    1311             :                                         rb[j] = curval;                 \
    1312             :                         }                                               \
    1313             :                 } else {                                                \
    1314             :                         for (; k < i;) {                             \
    1315             :                                 j = k;                                  \
    1316             :                                 do {                                    \
    1317             :                                         curval += !is_##TPE##_nil(bp[k]); \
    1318             :                                         k++;                            \
    1319             :                                 } while (k < i && !op[k]);           \
    1320             :                                 for (; j < k; j++)                   \
    1321             :                                         rb[j] = curval;                 \
    1322             :                         }                                               \
    1323             :                 }                                                       \
    1324             :         } while (0)
    1325             : 
    1326             : #define ANALYTICAL_COUNT_FIXED_CURRENT_ROW_TILL_UNBOUNDED(TPE)          \
    1327             :         do {                                                            \
    1328             :                 curval = 0;                                             \
    1329             :                 l = i - 1;                                              \
    1330             :                 if (count_all) {                                        \
    1331             :                         for (j = l; ; j--) {                            \
    1332             :                                 if (op[j] || j == k) {                  \
    1333             :                                         curval += l - j + 1;            \
    1334             :                                         for (; ; l--) {                 \
    1335             :                                                 rb[l] = curval;         \
    1336             :                                                 if (l == j)             \
    1337             :                                                         break;          \
    1338             :                                         }                               \
    1339             :                                         if (j == k)                     \
    1340             :                                                 break;                  \
    1341             :                                         l = j - 1;                      \
    1342             :                                 }                                       \
    1343             :                         }                                               \
    1344             :                 } else {                                                \
    1345             :                         for (j = l; ; j--) {                            \
    1346             :                                 curval += !is_##TPE##_nil(bp[j]);       \
    1347             :                                 if (op[j] || j == k) {                  \
    1348             :                                         for (; ; l--) {                 \
    1349             :                                                 rb[l] = curval;         \
    1350             :                                                 if (l == j)             \
    1351             :                                                         break;          \
    1352             :                                         }                               \
    1353             :                                         if (j == k)                     \
    1354             :                                                 break;                  \
    1355             :                                         l = j - 1;                      \
    1356             :                                 }                                       \
    1357             :                         }                                               \
    1358             :                 }                                                       \
    1359             :                 k = i;                                                  \
    1360             :         } while (0)
    1361             : 
    1362             : #define ANALYTICAL_COUNT_FIXED_ALL_ROWS(TPE)                            \
    1363             :         do {                                                            \
    1364             :                 if (count_all) {                                        \
    1365             :                         curval = (lng)(i - k);                          \
    1366             :                         for (; k < i; k++)                           \
    1367             :                                 rb[k] = curval;                         \
    1368             :                 } else {                                                \
    1369             :                         curval = 0;                                     \
    1370             :                         for (; j < i; j++)                           \
    1371             :                                 curval += !is_##TPE##_nil(bp[j]);       \
    1372             :                         for (; k < i; k++)                           \
    1373             :                                 rb[k] = curval;                         \
    1374             :                 }                                                       \
    1375             :         } while (0)
    1376             : 
    1377             : #define ANALYTICAL_COUNT_FIXED_CURRENT_ROW(TPE)                 \
    1378             :         do {                                                    \
    1379             :                 if (count_all) {                                \
    1380             :                         for (; k < i; k++)                   \
    1381             :                                 rb[k] = 1;                      \
    1382             :                 } else {                                        \
    1383             :                         for (; k < i; k++)                   \
    1384             :                                 rb[k] = !is_##TPE##_nil(bp[k]); \
    1385             :                 }                                               \
    1386             :         } while (0)
    1387             : 
    1388             : #define INIT_AGGREGATE_COUNT(TPE, NOTHING1, NOTHING2)   \
    1389             :         do {                                            \
    1390             :                 computed = 0;                           \
    1391             :         } while (0)
    1392             : #define COMPUTE_LEVEL0_COUNT_FIXED(X, TPE, NOTHING1, NOTHING2)  \
    1393             :         do {                                                    \
    1394             :                 computed = !is_##TPE##_nil(bp[j + X]);          \
    1395             :         } while (0)
    1396             : #define COMPUTE_LEVELN_COUNT(VAL, NOTHING1, NOTHING2, NOTHING3) \
    1397             :         do {                                                    \
    1398             :                 computed += VAL;                                \
    1399             :         } while (0)
    1400             : #define FINALIZE_AGGREGATE_COUNT(NOTHING1, NOTHING2, NOTHING3)  \
    1401             :         do {                                                    \
    1402             :                 rb[k] = computed;                               \
    1403             :         } while (0)
    1404             : #define ANALYTICAL_COUNT_FIXED_OTHERS(TPE)                              \
    1405             :         do {                                                            \
    1406             :                 if (count_all) { /* no segment tree required for the global case (it scales in O(n)) */ \
    1407             :                         for (; k < i; k++)                           \
    1408             :                                 rb[k] = (end[k] > start[k]) ? (lng)(end[k] - start[k]) : 0; \
    1409             :                 } else {                                                \
    1410             :                         oid ncount = i - k;                             \
    1411             :                         if ((res = GDKrebuild_segment_tree(ncount, sizeof(lng), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    1412             :                                 goto cleanup;                           \
    1413             :                         populate_segment_tree(lng, ncount, INIT_AGGREGATE_COUNT, COMPUTE_LEVEL0_COUNT_FIXED, COMPUTE_LEVELN_COUNT, TPE, NOTHING, NOTHING); \
    1414             :                         for (; k < i; k++)                           \
    1415             :                                 compute_on_segment_tree(lng, start[k] - j, end[k] - j, INIT_AGGREGATE_COUNT, COMPUTE_LEVELN_COUNT, FINALIZE_AGGREGATE_COUNT, TPE, NOTHING, NOTHING); \
    1416             :                         j = k;                                          \
    1417             :                 }                                                       \
    1418             :         } while (0)
    1419             : 
    1420             : /* Counting no nils for other types */
    1421             : #define ANALYTICAL_COUNT_OTHERS_UNBOUNDED_TILL_CURRENT_ROW              \
    1422             :         do {                                                            \
    1423             :                 curval = 0;                                             \
    1424             :                 if (count_all) {                                        \
    1425             :                         for (; k < i;) {                             \
    1426             :                                 j = k;                                  \
    1427             :                                 do {                                    \
    1428             :                                         k++;                            \
    1429             :                                 } while (k < i && !op[k]);           \
    1430             :                                 curval += k - j;                        \
    1431             :                                 for (; j < k; j++)                   \
    1432             :                                         rb[j] = curval;                 \
    1433             :                         }                                               \
    1434             :                 } else {                                                \
    1435             :                         for (; k < i; ) {                            \
    1436             :                                 j = k;                                  \
    1437             :                                 do {                                    \
    1438             :                                         curval += cmp(BUNtail(bi, k), nil) != 0; \
    1439             :                                         k++;                            \
    1440             :                                 } while (k < i && !op[k]);           \
    1441             :                                 for (; j < k; j++)                   \
    1442             :                                         rb[j] = curval;                 \
    1443             :                         }                                               \
    1444             :                 }                                                       \
    1445             :         } while (0)
    1446             : 
    1447             : #define ANALYTICAL_COUNT_OTHERS_CURRENT_ROW_TILL_UNBOUNDED              \
    1448             :         do {                                                            \
    1449             :                 curval = 0;                                             \
    1450             :                 l = i - 1;                                              \
    1451             :                 if (count_all) {                                        \
    1452             :                         for (j = l; ; j--) {                            \
    1453             :                                 if (op[j] || j == k) {                  \
    1454             :                                         curval += l - j + 1;            \
    1455             :                                         for (; ; l--) {                 \
    1456             :                                                 rb[l] = curval;         \
    1457             :                                                 if (l == j)             \
    1458             :                                                         break;          \
    1459             :                                         }                               \
    1460             :                                         if (j == k)                     \
    1461             :                                                 break;                  \
    1462             :                                         l = j - 1;                      \
    1463             :                                 }                                       \
    1464             :                         }                                               \
    1465             :                 } else {                                                \
    1466             :                         for (j = l; ; j--) {                            \
    1467             :                                 curval += cmp(BUNtail(bi, j), nil) != 0; \
    1468             :                                 if (op[j] || j == k) {                  \
    1469             :                                         for (; ; l--) {                 \
    1470             :                                                 rb[l] = curval;         \
    1471             :                                                 if (l == j)             \
    1472             :                                                         break;          \
    1473             :                                         }                               \
    1474             :                                         if (j == k)                     \
    1475             :                                                 break;                  \
    1476             :                                         l = j - 1;                      \
    1477             :                                 }                                       \
    1478             :                         }                                               \
    1479             :                 }                                                       \
    1480             :                 k = i;                                                  \
    1481             :         } while (0)
    1482             : 
    1483             : #define ANALYTICAL_COUNT_OTHERS_ALL_ROWS                                \
    1484             :         do {                                                            \
    1485             :                 curval = 0;                                             \
    1486             :                 if (count_all) {                                        \
    1487             :                         curval = (lng)(i - k);                          \
    1488             :                 } else {                                                \
    1489             :                         for (; j < i; j++)                           \
    1490             :                                 curval += cmp(BUNtail(bi, j), nil) != 0; \
    1491             :                 }                                                       \
    1492             :                 for (; k < i; k++)                                   \
    1493             :                         rb[k] = curval;                                 \
    1494             :         } while (0)
    1495             : 
    1496             : #define ANALYTICAL_COUNT_OTHERS_CURRENT_ROW                             \
    1497             :         do {                                                            \
    1498             :                 if (count_all) {                                        \
    1499             :                         for (; k < i; k++)                           \
    1500             :                                 rb[k] = 1;                              \
    1501             :                 } else {                                                \
    1502             :                         for (; k < i; k++)                           \
    1503             :                                 rb[k] = cmp(BUNtail(bi, k), nil) != 0;  \
    1504             :                 }                                                       \
    1505             :         } while (0)
    1506             : 
    1507             : #define COMPUTE_LEVEL0_COUNT_OTHERS(X, NOTHING1, NOTHING2, NOTHING3)    \
    1508             :         do {                                                            \
    1509             :                 computed = cmp(BUNtail(bi, j + X), nil) != 0;           \
    1510             :         } while (0)
    1511             : #define ANALYTICAL_COUNT_OTHERS_OTHERS                                  \
    1512             :         do {                                                            \
    1513             :                 if (count_all) { /* no segment tree required for the global case (it scales in O(n)) */ \
    1514             :                         for (; k < i; k++)                           \
    1515             :                                 rb[k] = (end[k] > start[k]) ? (lng)(end[k] - start[k]) : 0; \
    1516             :                 } else {                                                \
    1517             :                         oid ncount = i - k;                             \
    1518             :                         if ((res = GDKrebuild_segment_tree(ncount, sizeof(lng), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    1519             :                                 goto cleanup;                           \
    1520             :                         populate_segment_tree(lng, ncount, INIT_AGGREGATE_COUNT, COMPUTE_LEVEL0_COUNT_OTHERS, COMPUTE_LEVELN_COUNT, NOTHING, NOTHING, NOTHING); \
    1521             :                         for (; k < i; k++)                           \
    1522             :                                 compute_on_segment_tree(lng, start[k] - j, end[k] - j, INIT_AGGREGATE_COUNT, COMPUTE_LEVELN_COUNT, FINALIZE_AGGREGATE_COUNT, NOTHING, NOTHING, NOTHING); \
    1523             :                         j = k;                                          \
    1524             :                 }                                                       \
    1525             :         } while (0)
    1526             : 
    1527             : /* Now do the count analytic function branches */
    1528             : #define ANALYTICAL_COUNT_FIXED_PARTITIONS(TPE, IMP)                     \
    1529             :         do {                                                            \
    1530             :                 TPE *restrict bp = (TPE*) bheap;                        \
    1531             :                 if (p) {                                                \
    1532             :                         while (i < cnt) {                            \
    1533             :                                 if (np[i])      {                       \
    1534             : count##TPE##IMP:                                                        \
    1535             :                                         ANALYTICAL_COUNT_FIXED_##IMP(TPE); \
    1536             :                                 }                                       \
    1537             :                                 if (!last)                              \
    1538             :                                         i++;                            \
    1539             :                         }                                               \
    1540             :                 }                                                       \
    1541             :                 if (!last) {                                            \
    1542             :                         last = true;                                    \
    1543             :                         i = cnt;                                        \
    1544             :                         goto count##TPE##IMP;                           \
    1545             :                 }                                                       \
    1546             :         } while (0)
    1547             : 
    1548             : #ifdef HAVE_HGE
    1549             : #define ANALYTICAL_COUNT_LIMIT(IMP)                             \
    1550             :         case TYPE_hge:                                          \
    1551             :                 ANALYTICAL_COUNT_FIXED_PARTITIONS(hge, IMP);    \
    1552             :         break;
    1553             : #else
    1554             : #define ANALYTICAL_COUNT_LIMIT(IMP)
    1555             : #endif
    1556             : 
    1557             : #define ANALYTICAL_COUNT_BRANCHES(IMP)                                  \
    1558             :         do {                                                            \
    1559             :                 switch (ATOMbasetype(tpe)) {                            \
    1560             :                 case TYPE_bte:                                          \
    1561             :                         ANALYTICAL_COUNT_FIXED_PARTITIONS(bte, IMP);    \
    1562             :                         break;                                          \
    1563             :                 case TYPE_sht:                                          \
    1564             :                         ANALYTICAL_COUNT_FIXED_PARTITIONS(sht, IMP);    \
    1565             :                         break;                                          \
    1566             :                 case TYPE_int:                                          \
    1567             :                         ANALYTICAL_COUNT_FIXED_PARTITIONS(int, IMP);    \
    1568             :                         break;                                          \
    1569             :                 case TYPE_lng:                                          \
    1570             :                         ANALYTICAL_COUNT_FIXED_PARTITIONS(lng, IMP);    \
    1571             :                         break;                                          \
    1572             :                         ANALYTICAL_COUNT_LIMIT(IMP)                     \
    1573             :                 case TYPE_flt:                                          \
    1574             :                         ANALYTICAL_COUNT_FIXED_PARTITIONS(flt, IMP);    \
    1575             :                         break;                                          \
    1576             :                 case TYPE_dbl:                                          \
    1577             :                         ANALYTICAL_COUNT_FIXED_PARTITIONS(dbl, IMP);    \
    1578             :                         break;                                          \
    1579             :                 default: {                                              \
    1580             :                         if (p) {                                        \
    1581             :                                 while (i < cnt) {                    \
    1582             :                                         if (np[i])      {               \
    1583             : countothers##IMP:                                                       \
    1584             :                                                 ANALYTICAL_COUNT_OTHERS_##IMP; \
    1585             :                                         }                               \
    1586             :                                         if (!last)                      \
    1587             :                                                 i++;                    \
    1588             :                                 }                                       \
    1589             :                         }                                               \
    1590             :                         if (!last) {                                    \
    1591             :                                 last = true;                            \
    1592             :                                 i = cnt;                                \
    1593             :                                 goto countothers##IMP;                  \
    1594             :                         }                                               \
    1595             :                 }                                                       \
    1596             :                 }                                                       \
    1597             :         } while (0)
    1598             : 
    1599             : gdk_return
    1600         159 : GDKanalyticalcount(BAT *r, BAT *p, BAT *o, BAT *b, BAT *s, BAT *e, bit ignore_nils, int tpe, int frame_type)
    1601             : {
    1602         159 :         BATiter pi = bat_iterator(p);
    1603         159 :         BATiter oi = bat_iterator(o);
    1604         159 :         BATiter bi = bat_iterator(b);
    1605         159 :         BATiter si = bat_iterator(s);
    1606         159 :         BATiter ei = bat_iterator(e);
    1607         159 :         oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b), *restrict start = si.base, *restrict end = ei.base,
    1608         159 :                 *levels_offset = NULL, tree_capacity = 0, nlevels = 0;
    1609         159 :         lng curval = 0, *rb = (lng *) Tloc(r, 0);
    1610         159 :         bit *np = pi.base, *op = oi.base;
    1611         159 :         const void *restrict nil = ATOMnilptr(tpe);
    1612         159 :         int (*cmp) (const void *, const void *) = ATOMcompare(tpe);
    1613         159 :         const void *restrict bheap = bi.base;
    1614         159 :         bool count_all = !ignore_nils || b->tnonil, last = false;
    1615         159 :         void *segment_tree = NULL;
    1616             :         gdk_return res = GDK_SUCCEED;
    1617             : 
    1618         159 :         if (cnt > 0) {
    1619         159 :                 switch (frame_type) {
    1620          38 :                 case 3: /* unbounded until current row */       {
    1621         988 :                         ANALYTICAL_COUNT_BRANCHES(UNBOUNDED_TILL_CURRENT_ROW);
    1622             :                 } break;
    1623           3 :                 case 4: /* current row until unbounded */       {
    1624          41 :                         ANALYTICAL_COUNT_BRANCHES(CURRENT_ROW_TILL_UNBOUNDED);
    1625             :                 } break;
    1626          32 :                 case 5: /* all rows */  {
    1627         681 :                         ANALYTICAL_COUNT_BRANCHES(ALL_ROWS);
    1628             :                 } break;
    1629           8 :                 case 6: /* current row */ {
    1630          96 :                         ANALYTICAL_COUNT_BRANCHES(CURRENT_ROW);
    1631             :                 } break;
    1632          78 :                 default: {
    1633        2948 :                         ANALYTICAL_COUNT_BRANCHES(OTHERS);
    1634             :                 }
    1635             :                 }
    1636             :         }
    1637             : 
    1638         159 :         BATsetcount(r, cnt);
    1639         159 :         r->tnonil = true;
    1640         159 :         r->tnil = false;
    1641         159 : cleanup:
    1642         159 :         bat_iterator_end(&pi);
    1643         159 :         bat_iterator_end(&oi);
    1644         159 :         bat_iterator_end(&bi);
    1645         159 :         bat_iterator_end(&si);
    1646         159 :         bat_iterator_end(&ei);
    1647         159 :         GDKfree(segment_tree);
    1648         159 :         return res;
    1649             : }
    1650             : 
    1651             : /* sum on fixed size integers */
    1652             : #define ANALYTICAL_SUM_IMP_NUM_UNBOUNDED_TILL_CURRENT_ROW(TPE1, TPE2)   \
    1653             :         do {                                                            \
    1654             :                 TPE2 curval = TPE2##_nil;                               \
    1655             :                 for (; k < i;) {                                     \
    1656             :                         j = k;                                          \
    1657             :                         do {                                            \
    1658             :                                 if (!is_##TPE1##_nil(bp[k])) {          \
    1659             :                                         if (is_##TPE2##_nil(curval))    \
    1660             :                                                 curval = (TPE2) bp[k];  \
    1661             :                                         else                            \
    1662             :                                                 ADD_WITH_CHECK(bp[k], curval, TPE2, curval, GDK_##TPE2##_max, goto calc_overflow); \
    1663             :                                 }                                       \
    1664             :                                 k++;                                    \
    1665             :                         } while (k < i && !op[k]);                   \
    1666             :                         for (; j < k; j++)                           \
    1667             :                                 rb[j] = curval;                         \
    1668             :                         has_nils |= is_##TPE2##_nil(curval);            \
    1669             :                 }                                                       \
    1670             :         } while (0)
    1671             : 
    1672             : #define ANALYTICAL_SUM_IMP_NUM_CURRENT_ROW_TILL_UNBOUNDED(TPE1, TPE2)   \
    1673             :         do {                                                            \
    1674             :                 TPE2 curval = TPE2##_nil;                               \
    1675             :                 l = i - 1;                                              \
    1676             :                 for (j = l; ; j--) {                                    \
    1677             :                         if (!is_##TPE1##_nil(bp[j])) {                  \
    1678             :                                 if (is_##TPE2##_nil(curval))            \
    1679             :                                         curval = (TPE2) bp[j];          \
    1680             :                                 else                                    \
    1681             :                                         ADD_WITH_CHECK(bp[j], curval, TPE2, curval, GDK_##TPE2##_max, goto calc_overflow); \
    1682             :                         }                                               \
    1683             :                         if (op[j] || j == k) {                          \
    1684             :                                 for (; ; l--) {                         \
    1685             :                                         rb[l] = curval;                 \
    1686             :                                         if (l == j)                     \
    1687             :                                                 break;                  \
    1688             :                                 }                                       \
    1689             :                                 has_nils |= is_##TPE2##_nil(curval);    \
    1690             :                                 if (j == k)                             \
    1691             :                                         break;                          \
    1692             :                                 l = j - 1;                              \
    1693             :                         }                                               \
    1694             :                 }                                                       \
    1695             :                 k = i;                                                  \
    1696             :         } while (0)
    1697             : 
    1698             : #define ANALYTICAL_SUM_IMP_NUM_ALL_ROWS(TPE1, TPE2)                     \
    1699             :         do {                                                            \
    1700             :                 TPE2 curval = TPE2##_nil;                               \
    1701             :                 for (; j < i; j++) {                                 \
    1702             :                         TPE1 v = bp[j];                                 \
    1703             :                         if (!is_##TPE1##_nil(v)) {                      \
    1704             :                                 if (is_##TPE2##_nil(curval))            \
    1705             :                                         curval = (TPE2) v;              \
    1706             :                                 else                                    \
    1707             :                                         ADD_WITH_CHECK(v, curval, TPE2, curval, GDK_##TPE2##_max, goto calc_overflow); \
    1708             :                         }                                               \
    1709             :                 }                                                       \
    1710             :                 for (; k < i; k++)                                   \
    1711             :                         rb[k] = curval;                                 \
    1712             :                 has_nils |= is_##TPE2##_nil(curval);                    \
    1713             :         } while (0)
    1714             : 
    1715             : #define ANALYTICAL_SUM_IMP_NUM_CURRENT_ROW(TPE1, TPE2)  \
    1716             :         do {                                            \
    1717             :                 for (; k < i; k++) {                 \
    1718             :                         TPE1 v = bp[k];                 \
    1719             :                         if (is_##TPE1##_nil(v)) {       \
    1720             :                                 rb[k] = TPE2##_nil;     \
    1721             :                                 has_nils = true;        \
    1722             :                         } else  {                       \
    1723             :                                 rb[k] = (TPE2) v;       \
    1724             :                         }                               \
    1725             :                 }                                       \
    1726             :         } while (0)
    1727             : 
    1728             : #define INIT_AGGREGATE_SUM(NOTHING1, TPE2, NOTHING2)    \
    1729             :         do {                                            \
    1730             :                 computed = TPE2##_nil;                  \
    1731             :         } while (0)
    1732             : #define COMPUTE_LEVEL0_SUM(X, TPE1, TPE2, NOTHING)                      \
    1733             :         do {                                                            \
    1734             :                 TPE1 v = bp[j + X];                                     \
    1735             :                 computed = is_##TPE1##_nil(v) ? TPE2##_nil : (TPE2) v;  \
    1736             :         } while (0)
    1737             : #define COMPUTE_LEVELN_SUM_NUM(VAL, NOTHING1, TPE2, NOTHING2)           \
    1738             :         do {                                                            \
    1739             :                 if (!is_##TPE2##_nil(VAL)) {                            \
    1740             :                         if (is_##TPE2##_nil(computed))                  \
    1741             :                                 computed = VAL;                         \
    1742             :                         else                                            \
    1743             :                                 ADD_WITH_CHECK(VAL, computed, TPE2, computed, GDK_##TPE2##_max, goto calc_overflow); \
    1744             :                 }                                                       \
    1745             :         } while (0)
    1746             : #define FINALIZE_AGGREGATE_SUM(NOTHING1, TPE2, NOTHING2)        \
    1747             :         do {                                                    \
    1748             :                 rb[k] = computed;                               \
    1749             :                 has_nils |= is_##TPE2##_nil(computed);          \
    1750             :         } while (0)
    1751             : #define ANALYTICAL_SUM_IMP_NUM_OTHERS(TPE1, TPE2)                       \
    1752             :         do {                                                            \
    1753             :                 oid ncount = i - k;                                     \
    1754             :                 if ((res = GDKrebuild_segment_tree(ncount, sizeof(TPE2), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    1755             :                         goto cleanup;                                   \
    1756             :                 populate_segment_tree(TPE2, ncount, INIT_AGGREGATE_SUM, COMPUTE_LEVEL0_SUM, COMPUTE_LEVELN_SUM_NUM, TPE1, TPE2, NOTHING); \
    1757             :                 for (; k < i; k++)                                   \
    1758             :                         compute_on_segment_tree(TPE2, start[k] - j, end[k] - j, INIT_AGGREGATE_SUM, COMPUTE_LEVELN_SUM_NUM, FINALIZE_AGGREGATE_SUM, TPE1, TPE2, NOTHING); \
    1759             :                 j = k;                                                  \
    1760             :         } while (0)
    1761             : 
    1762             : /* sum on floating-points */
    1763             : /* TODO go through a version of dofsum which returns the current partials for all the cases */
    1764             : #define ANALYTICAL_SUM_IMP_FP_UNBOUNDED_TILL_CURRENT_ROW(TPE1, TPE2) ANALYTICAL_SUM_IMP_NUM_UNBOUNDED_TILL_CURRENT_ROW(TPE1, TPE2)
    1765             : #define ANALYTICAL_SUM_IMP_FP_CURRENT_ROW_TILL_UNBOUNDED(TPE1, TPE2) ANALYTICAL_SUM_IMP_NUM_CURRENT_ROW_TILL_UNBOUNDED(TPE1, TPE2)
    1766             : 
    1767             : #define ANALYTICAL_SUM_IMP_FP_ALL_ROWS(TPE1, TPE2)                      \
    1768             :         do {                                                            \
    1769             :                 TPE1 *bs = bp + k;                                      \
    1770             :                 BUN parcel = i - k;                                     \
    1771             :                 TPE2 curval = TPE2##_nil;                               \
    1772             :                 if (dofsum(bs, 0,                                       \
    1773             :                                 &(struct canditer){.tpe = cand_dense, .ncand = parcel,}, \
    1774             :                                 parcel, &curval, 1, TYPE_##TPE1,    \
    1775             :                                 TYPE_##TPE2, NULL, 0, 0, true,          \
    1776             :                                 false, true) == BUN_NONE) {             \
    1777             :                         goto bailout;                                   \
    1778             :                 }                                                       \
    1779             :                 for (; k < i; k++)                                   \
    1780             :                         rb[k] = curval;                                 \
    1781             :                 has_nils |= is_##TPE2##_nil(curval);                    \
    1782             :         } while (0)
    1783             : 
    1784             : #define ANALYTICAL_SUM_IMP_FP_CURRENT_ROW(TPE1, TPE2) ANALYTICAL_SUM_IMP_NUM_CURRENT_ROW(TPE1, TPE2)
    1785             : #define ANALYTICAL_SUM_IMP_FP_OTHERS(TPE1, TPE2) ANALYTICAL_SUM_IMP_NUM_OTHERS(TPE1, TPE2)
    1786             : 
    1787             : #define ANALYTICAL_SUM_CALC(TPE1, TPE2, IMP)                    \
    1788             :         do {                                                    \
    1789             :                 TPE1 *restrict bp = (TPE1*)bi.base;             \
    1790             :                 TPE2 *rb = (TPE2*)Tloc(r, 0);                   \
    1791             :                 if (p) {                                        \
    1792             :                         while (i < cnt) {                    \
    1793             :                                 if (np[i])      {               \
    1794             : sum##TPE1##TPE2##IMP:                                           \
    1795             :                                         IMP(TPE1, TPE2);        \
    1796             :                                 }                               \
    1797             :                                 if (!last)                      \
    1798             :                                         i++;                    \
    1799             :                         }                                       \
    1800             :                 }                                               \
    1801             :                 if (!last) {                                    \
    1802             :                         last = true;                            \
    1803             :                         i = cnt;                                \
    1804             :                         goto sum##TPE1##TPE2##IMP;              \
    1805             :                 }                                               \
    1806             :         } while (0)
    1807             : 
    1808             : #ifdef HAVE_HGE
    1809             : #define ANALYTICAL_SUM_LIMIT(IMP)                                       \
    1810             :         case TYPE_hge:{                                                 \
    1811             :                 switch (tp1) {                                          \
    1812             :                 case TYPE_bte:                                          \
    1813             :                         ANALYTICAL_SUM_CALC(bte, hge, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1814             :                         break;                                          \
    1815             :                 case TYPE_sht:                                          \
    1816             :                         ANALYTICAL_SUM_CALC(sht, hge, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1817             :                         break;                                          \
    1818             :                 case TYPE_int:                                          \
    1819             :                         ANALYTICAL_SUM_CALC(int, hge, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1820             :                         break;                                          \
    1821             :                 case TYPE_lng:                                          \
    1822             :                         ANALYTICAL_SUM_CALC(lng, hge, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1823             :                         break;                                          \
    1824             :                 case TYPE_hge:                                          \
    1825             :                         ANALYTICAL_SUM_CALC(hge, hge, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1826             :                         break;                                          \
    1827             :                 default:                                                \
    1828             :                         goto nosupport;                                 \
    1829             :                 }                                                       \
    1830             :                 break;                                                  \
    1831             :         }
    1832             : #else
    1833             : #define ANALYTICAL_SUM_LIMIT(IMP)
    1834             : #endif
    1835             : 
    1836             : #define ANALYTICAL_SUM_BRANCHES(IMP)                                    \
    1837             :         do {                                                            \
    1838             :                 switch (tp2) {                                          \
    1839             :                 case TYPE_bte:{                                         \
    1840             :                         switch (tp1) {                                  \
    1841             :                         case TYPE_bte:                                  \
    1842             :                                 ANALYTICAL_SUM_CALC(bte, bte, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1843             :                                 break;                                  \
    1844             :                         default:                                        \
    1845             :                                 goto nosupport;                         \
    1846             :                         }                                               \
    1847             :                         break;                                          \
    1848             :                 }                                                       \
    1849             :                 case TYPE_sht:{                                         \
    1850             :                         switch (tp1) {                                  \
    1851             :                         case TYPE_bte:                                  \
    1852             :                                 ANALYTICAL_SUM_CALC(bte, sht, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1853             :                                 break;                                  \
    1854             :                         case TYPE_sht:                                  \
    1855             :                                 ANALYTICAL_SUM_CALC(sht, sht, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1856             :                                 break;                                  \
    1857             :                         default:                                        \
    1858             :                                 goto nosupport;                         \
    1859             :                         }                                               \
    1860             :                         break;                                          \
    1861             :                 }                                                       \
    1862             :                 case TYPE_int:{                                         \
    1863             :                         switch (tp1) {                                  \
    1864             :                         case TYPE_bte:                                  \
    1865             :                                 ANALYTICAL_SUM_CALC(bte, int, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1866             :                                 break;                                  \
    1867             :                         case TYPE_sht:                                  \
    1868             :                                 ANALYTICAL_SUM_CALC(sht, int, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1869             :                                 break;                                  \
    1870             :                         case TYPE_int:                                  \
    1871             :                                 ANALYTICAL_SUM_CALC(int, int, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1872             :                                 break;                                  \
    1873             :                         default:                                        \
    1874             :                                 goto nosupport;                         \
    1875             :                         }                                               \
    1876             :                         break;                                          \
    1877             :                 }                                                       \
    1878             :                 case TYPE_lng:{                                         \
    1879             :                         switch (tp1) {                                  \
    1880             :                         case TYPE_bte:                                  \
    1881             :                                 ANALYTICAL_SUM_CALC(bte, lng, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1882             :                                 break;                                  \
    1883             :                         case TYPE_sht:                                  \
    1884             :                                 ANALYTICAL_SUM_CALC(sht, lng, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1885             :                                 break;                                  \
    1886             :                         case TYPE_int:                                  \
    1887             :                                 ANALYTICAL_SUM_CALC(int, lng, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1888             :                                 break;                                  \
    1889             :                         case TYPE_lng:                                  \
    1890             :                                 ANALYTICAL_SUM_CALC(lng, lng, ANALYTICAL_SUM_IMP_NUM_##IMP); \
    1891             :                                 break;                                  \
    1892             :                         default:                                        \
    1893             :                                 goto nosupport;                         \
    1894             :                         }                                               \
    1895             :                         break;                                          \
    1896             :                 }                                                       \
    1897             :                 ANALYTICAL_SUM_LIMIT(IMP)                               \
    1898             :                 case TYPE_flt:{                                         \
    1899             :                         switch (tp1) {                                  \
    1900             :                         case TYPE_flt:                                  \
    1901             :                                 ANALYTICAL_SUM_CALC(flt, flt, ANALYTICAL_SUM_IMP_FP_##IMP); \
    1902             :                                 break;                                  \
    1903             :                         default:                                        \
    1904             :                                 goto nosupport;                         \
    1905             :                         }                                               \
    1906             :                         break;                                          \
    1907             :                 }                                                       \
    1908             :                 case TYPE_dbl:{                                         \
    1909             :                         switch (tp1) {                                  \
    1910             :                         case TYPE_flt:                                  \
    1911             :                                 ANALYTICAL_SUM_CALC(flt, dbl, ANALYTICAL_SUM_IMP_FP_##IMP); \
    1912             :                                 break;                                  \
    1913             :                         case TYPE_dbl:                                  \
    1914             :                                 ANALYTICAL_SUM_CALC(dbl, dbl, ANALYTICAL_SUM_IMP_FP_##IMP); \
    1915             :                                 break;                                  \
    1916             :                         default:                                        \
    1917             :                                 goto nosupport;                         \
    1918             :                         }                                               \
    1919             :                         break;                                          \
    1920             :                 }                                                       \
    1921             :                 default:                                                \
    1922             :                         goto nosupport;                                 \
    1923             :                 }                                                       \
    1924             :         } while (0)
    1925             : 
    1926             : gdk_return
    1927         115 : GDKanalyticalsum(BAT *r, BAT *p, BAT *o, BAT *b, BAT *s, BAT *e, int tp1, int tp2, int frame_type)
    1928             : {
    1929         115 :         BATiter pi = bat_iterator(p);
    1930         114 :         BATiter oi = bat_iterator(o);
    1931         114 :         BATiter bi = bat_iterator(b);
    1932         115 :         BATiter si = bat_iterator(s);
    1933         115 :         BATiter ei = bat_iterator(e);
    1934             :         bool has_nils = false, last = false;
    1935         115 :         oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b), *restrict start = si.base, *restrict end = ei.base,
    1936         115 :                 *levels_offset = NULL, tree_capacity = 0, nlevels = 0;
    1937         115 :         bit *np = pi.base, *op = oi.base;
    1938             :         int abort_on_error = 1;
    1939             :         BUN nils = 0;
    1940         115 :         void *segment_tree = NULL;
    1941             :         gdk_return res = GDK_SUCCEED;
    1942             : 
    1943         115 :         if (cnt > 0) {
    1944         115 :                 switch (frame_type) {
    1945          39 :                 case 3: /* unbounded until current row */       {
    1946        1028 :                         ANALYTICAL_SUM_BRANCHES(UNBOUNDED_TILL_CURRENT_ROW);
    1947             :                 } break;
    1948           0 :                 case 4: /* current row until unbounded */       {
    1949           0 :                         ANALYTICAL_SUM_BRANCHES(CURRENT_ROW_TILL_UNBOUNDED);
    1950             :                 } break;
    1951          28 :                 case 5: /* all rows */  {
    1952       18539 :                         ANALYTICAL_SUM_BRANCHES(ALL_ROWS);
    1953             :                 } break;
    1954           2 :                 case 6: /* current row */ {
    1955          34 :                         ANALYTICAL_SUM_BRANCHES(CURRENT_ROW);
    1956             :                 } break;
    1957          46 :                 default: {
    1958     8374161 :                         ANALYTICAL_SUM_BRANCHES(OTHERS);
    1959             :                 }
    1960             :                 }
    1961             :         }
    1962             : 
    1963         115 :         BATsetcount(r, cnt);
    1964         115 :         r->tnonil = !has_nils;
    1965         115 :         r->tnil = has_nils;
    1966         115 :         goto cleanup; /* all these gotos seem confusing but it cleans up the ending of the operator */
    1967           0 : bailout:
    1968           0 :         GDKerror("42000!error while calculating floating-point sum\n");
    1969             :         res = GDK_FAIL;
    1970           0 :         goto cleanup;
    1971           0 : calc_overflow:
    1972           0 :         GDKerror("22003!overflow in calculation.\n");
    1973             :         res = GDK_FAIL;
    1974         115 : cleanup:
    1975         115 :         bat_iterator_end(&pi);
    1976         115 :         bat_iterator_end(&oi);
    1977         115 :         bat_iterator_end(&bi);
    1978         115 :         bat_iterator_end(&si);
    1979         115 :         bat_iterator_end(&ei);
    1980         115 :         GDKfree(segment_tree);
    1981         115 :         return res;
    1982           0 : nosupport:
    1983           0 :         GDKerror("42000!type combination (sum(%s)->%s) not supported.\n", ATOMname(tp1), ATOMname(tp2));
    1984             :         res = GDK_FAIL;
    1985           0 :         goto cleanup;
    1986             : }
    1987             : 
    1988             : /* product on integers */
    1989             : #define PROD_NUM(TPE1, TPE2, TPE3, ARG)                                 \
    1990             :         do {                                                            \
    1991             :                 if (!is_##TPE1##_nil(ARG)) {                            \
    1992             :                         if (is_##TPE2##_nil(curval))                    \
    1993             :                                 curval = (TPE2) ARG;                    \
    1994             :                         else                                            \
    1995             :                                 MUL4_WITH_CHECK(ARG, curval, TPE2, curval, GDK_##TPE2##_max, TPE3, goto calc_overflow); \
    1996             :                 }                                                       \
    1997             :         } while(0)
    1998             : 
    1999             : #define ANALYTICAL_PROD_CALC_NUM_UNBOUNDED_TILL_CURRENT_ROW(TPE1, TPE2, TPE3) \
    2000             :         do {                                                            \
    2001             :                 TPE2 curval = TPE2##_nil;                               \
    2002             :                 for (; k < i;) {                                     \
    2003             :                         j = k;                                          \
    2004             :                         do {                                            \
    2005             :                                 PROD_NUM(TPE1, TPE2, TPE3, bp[k]);      \
    2006             :                                 k++;                                    \
    2007             :                         } while (k < i && !op[k]);                   \
    2008             :                         for (; j < k; j++)                           \
    2009             :                                 rb[j] = curval;                         \
    2010             :                         has_nils |= is_##TPE2##_nil(curval);            \
    2011             :                 }                                                       \
    2012             :         } while (0)
    2013             : 
    2014             : #define ANALYTICAL_PROD_CALC_NUM_CURRENT_ROW_TILL_UNBOUNDED(TPE1, TPE2, TPE3) \
    2015             :         do {                                                            \
    2016             :                 TPE2 curval = TPE2##_nil;                               \
    2017             :                 l = i - 1;                                              \
    2018             :                 for (j = l; ; j--) {                                    \
    2019             :                         PROD_NUM(TPE1, TPE2, TPE3, bp[j]);              \
    2020             :                         if (op[j] || j == k) {                          \
    2021             :                                 for (; ; l--) {                         \
    2022             :                                         rb[l] = curval;                 \
    2023             :                                         if (l == j)                     \
    2024             :                                                 break;                  \
    2025             :                                 }                                       \
    2026             :                                 has_nils |= is_##TPE2##_nil(curval);    \
    2027             :                                 if (j == k)                             \
    2028             :                                         break;                          \
    2029             :                                 l = j - 1;                              \
    2030             :                         }                                               \
    2031             :                 }                                                       \
    2032             :                 k = i;                                                  \
    2033             :         } while (0)
    2034             : 
    2035             : #define ANALYTICAL_PROD_CALC_NUM_ALL_ROWS(TPE1, TPE2, TPE3)     \
    2036             :         do {                                                    \
    2037             :                 TPE2 curval = TPE2##_nil;                       \
    2038             :                 for (; j < i; j++) {                         \
    2039             :                         TPE1 v = bp[j];                         \
    2040             :                         PROD_NUM(TPE1, TPE2, TPE3, v);          \
    2041             :                 }                                               \
    2042             :                 for (; k < i; k++)                           \
    2043             :                         rb[k] = curval;                         \
    2044             :                 has_nils |= is_##TPE2##_nil(curval);            \
    2045             :         } while (0)
    2046             : 
    2047             : #define ANALYTICAL_PROD_CALC_NUM_CURRENT_ROW(TPE1, TPE2, TPE3)  \
    2048             :         do {                                                    \
    2049             :                 for (; k < i; k++) {                         \
    2050             :                         TPE1 v = bp[k];                         \
    2051             :                         if (is_##TPE1##_nil(v)) {               \
    2052             :                                 rb[k] = TPE2##_nil;             \
    2053             :                                 has_nils = true;                \
    2054             :                         } else  {                               \
    2055             :                                 rb[k] = (TPE2) v;               \
    2056             :                         }                                       \
    2057             :                 }                                               \
    2058             :         } while (0)
    2059             : 
    2060             : #define INIT_AGGREGATE_PROD(NOTHING1, TPE2, NOTHING2)   \
    2061             :         do {                                            \
    2062             :                 computed = TPE2##_nil;                  \
    2063             :         } while (0)
    2064             : #define COMPUTE_LEVEL0_PROD(X, TPE1, TPE2, NOTHING)                     \
    2065             :         do {                                                            \
    2066             :                 TPE1 v = bp[j + X];                                     \
    2067             :                 computed = is_##TPE1##_nil(v) ? TPE2##_nil : (TPE2) v;  \
    2068             :         } while (0)
    2069             : #define COMPUTE_LEVELN_PROD_NUM(VAL, NOTHING, TPE2, TPE3)               \
    2070             :         do {                                                            \
    2071             :                 if (!is_##TPE2##_nil(VAL)) {                            \
    2072             :                         if (is_##TPE2##_nil(computed))                  \
    2073             :                                 computed = VAL;                         \
    2074             :                         else                                            \
    2075             :                                 MUL4_WITH_CHECK(VAL, computed, TPE2, computed, GDK_##TPE2##_max, TPE3, goto calc_overflow); \
    2076             :                 }                                                       \
    2077             :         } while (0)
    2078             : #define FINALIZE_AGGREGATE_PROD(NOTHING1, TPE2, NOTHING2)       \
    2079             :         do {                                                    \
    2080             :                 rb[k] = computed;                               \
    2081             :                 has_nils |= is_##TPE2##_nil(computed);          \
    2082             :         } while (0)
    2083             : #define ANALYTICAL_PROD_CALC_NUM_OTHERS(TPE1, TPE2, TPE3)               \
    2084             :         do {                                                            \
    2085             :                 oid ncount = i - k;                                     \
    2086             :                 if ((res = GDKrebuild_segment_tree(ncount, sizeof(TPE2), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    2087             :                         goto cleanup;                                   \
    2088             :                 populate_segment_tree(TPE2, ncount, INIT_AGGREGATE_PROD, COMPUTE_LEVEL0_PROD, COMPUTE_LEVELN_PROD_NUM, TPE1, TPE2, TPE3); \
    2089             :                 for (; k < i; k++)                                   \
    2090             :                         compute_on_segment_tree(TPE2, start[k] - j, end[k] - j, INIT_AGGREGATE_PROD, COMPUTE_LEVELN_PROD_NUM, FINALIZE_AGGREGATE_PROD, TPE1, TPE2, TPE3); \
    2091             :                 j = k;                                                  \
    2092             :         } while (0)
    2093             : 
    2094             : /* product on integers while checking for overflows on the output  */
    2095             : #define PROD_NUM_LIMIT(TPE1, TPE2, REAL_IMP, ARG)                       \
    2096             :         do {                                                            \
    2097             :                 if (!is_##TPE1##_nil(ARG)) {                            \
    2098             :                         if (is_##TPE2##_nil(curval))                    \
    2099             :                                 curval = (TPE2) ARG;                    \
    2100             :                         else                                            \
    2101             :                                 REAL_IMP(ARG, curval, curval, GDK_##TPE2##_max, goto calc_overflow); \
    2102             :                 }                                                       \
    2103             :         } while(0)
    2104             : 
    2105             : #define ANALYTICAL_PROD_CALC_NUM_LIMIT_UNBOUNDED_TILL_CURRENT_ROW(TPE1, TPE2, REAL_IMP) \
    2106             :         do {                                                            \
    2107             :                 TPE2 curval = TPE2##_nil;                               \
    2108             :                 for (; k < i;) {                                     \
    2109             :                         j = k;                                          \
    2110             :                         do {                                            \
    2111             :                                 PROD_NUM_LIMIT(TPE1, TPE2, REAL_IMP, bp[k]); \
    2112             :                                 k++;                                    \
    2113             :                         } while (k < i && !op[k]);                   \
    2114             :                         for (; j < k; j++)                           \
    2115             :                                 rb[j] = curval;                         \
    2116             :                         has_nils |= is_##TPE2##_nil(curval);            \
    2117             :                 }                                                       \
    2118             :         } while (0)
    2119             : 
    2120             : #define ANALYTICAL_PROD_CALC_NUM_LIMIT_CURRENT_ROW_TILL_UNBOUNDED(TPE1, TPE2, REAL_IMP) \
    2121             :         do {                                                            \
    2122             :                 TPE2 curval = TPE2##_nil;                               \
    2123             :                 l = i - 1;                                              \
    2124             :                 for (j = l; ; j--) {                                    \
    2125             :                         PROD_NUM_LIMIT(TPE1, TPE2, REAL_IMP, bp[j]);    \
    2126             :                         if (op[j] || j == k) {                          \
    2127             :                                 for (; ; l--) {                         \
    2128             :                                         rb[l] = curval;                 \
    2129             :                                         if (l == j)                     \
    2130             :                                                 break;                  \
    2131             :                                 }                                       \
    2132             :                                 has_nils |= is_##TPE2##_nil(curval);    \
    2133             :                                 if (j == k)                             \
    2134             :                                         break;                          \
    2135             :                                 l = j - 1;                              \
    2136             :                         }                                               \
    2137             :                 }                                                       \
    2138             :                 k = i;                                                  \
    2139             :         } while (0)
    2140             : 
    2141             : #define ANALYTICAL_PROD_CALC_NUM_LIMIT_ALL_ROWS(TPE1, TPE2, REAL_IMP)   \
    2142             :         do {                                                            \
    2143             :                 TPE2 curval = TPE2##_nil;                               \
    2144             :                 for (; j < i; j++) {                                 \
    2145             :                         TPE1 v = bp[j];                                 \
    2146             :                         PROD_NUM_LIMIT(TPE1, TPE2, REAL_IMP, v);        \
    2147             :                 }                                                       \
    2148             :                 for (; k < i; k++)                                   \
    2149             :                         rb[k] = curval;                                 \
    2150             :                 has_nils |= is_##TPE2##_nil(curval);                    \
    2151             :         } while (0)
    2152             : 
    2153             : #define ANALYTICAL_PROD_CALC_NUM_LIMIT_CURRENT_ROW(TPE1, TPE2, REAL_IMP) \
    2154             :         do {                                                            \
    2155             :                 for (; k < i; k++) {                                 \
    2156             :                         TPE1 v = bp[k];                                 \
    2157             :                         if (is_##TPE1##_nil(v)) {                       \
    2158             :                                 rb[k] = TPE2##_nil;                     \
    2159             :                                 has_nils = true;                        \
    2160             :                         } else  {                                       \
    2161             :                                 rb[k] = (TPE2) v;                       \
    2162             :                         }                                               \
    2163             :                 }                                                       \
    2164             :         } while (0)
    2165             : 
    2166             : #define COMPUTE_LEVELN_PROD_NUM_LIMIT(VAL, NOTHING, TPE2, REAL_IMP)     \
    2167             :         do {                                                            \
    2168             :                 if (!is_##TPE2##_nil(VAL)) {                            \
    2169             :                         if (is_##TPE2##_nil(computed))                  \
    2170             :                                 computed = VAL;                         \
    2171             :                         else                                            \
    2172             :                                 REAL_IMP(VAL, computed, computed, GDK_##TPE2##_max, goto calc_overflow); \
    2173             :                 }                                                       \
    2174             :         } while (0)
    2175             : #define ANALYTICAL_PROD_CALC_NUM_LIMIT_OTHERS(TPE1, TPE2, REAL_IMP)     \
    2176             :         do {                                                            \
    2177             :                 oid ncount = i - k;                                     \
    2178             :                 if ((res = GDKrebuild_segment_tree(ncount, sizeof(TPE2), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    2179             :                         goto cleanup;                                   \
    2180             :                 populate_segment_tree(TPE2, ncount, INIT_AGGREGATE_PROD, COMPUTE_LEVEL0_PROD, COMPUTE_LEVELN_PROD_NUM_LIMIT, TPE1, TPE2, REAL_IMP); \
    2181             :                 for (; k < i; k++)                                   \
    2182             :                         compute_on_segment_tree(TPE2, start[k] - j, end[k] - j, INIT_AGGREGATE_PROD, COMPUTE_LEVELN_PROD_NUM_LIMIT, FINALIZE_AGGREGATE_PROD, TPE1, TPE2, REAL_IMP); \
    2183             :                 j = k;                                                  \
    2184             :         } while (0)
    2185             : 
    2186             : /* product on floating-points */
    2187             : #define PROD_FP(TPE1, TPE2, ARG)                                        \
    2188             :         do {                                                            \
    2189             :                 if (!is_##TPE1##_nil(ARG)) {                            \
    2190             :                         if (is_##TPE2##_nil(curval)) {                  \
    2191             :                                 curval = (TPE2) ARG;                    \
    2192             :                         } else if (ABSOLUTE(curval) > 1 && GDK_##TPE2##_max / ABSOLUTE(ARG) < ABSOLUTE(curval)) { \
    2193             :                                 if (abort_on_error)                     \
    2194             :                                         goto calc_overflow;             \
    2195             :                                 curval = TPE2##_nil;                    \
    2196             :                                 nils++;                                 \
    2197             :                         } else {                                        \
    2198             :                                 curval *= ARG;                          \
    2199             :                         }                                               \
    2200             :                 }                                                       \
    2201             :         } while(0)
    2202             : 
    2203             : #define ANALYTICAL_PROD_CALC_FP_UNBOUNDED_TILL_CURRENT_ROW(TPE1, TPE2, ARG3)    /* ARG3 is ignored here */ \
    2204             :         do {                                                            \
    2205             :                 TPE2 curval = TPE2##_nil;                               \
    2206             :                 for (; k < i;) {                                     \
    2207             :                         j = k;                                          \
    2208             :                         do {                                            \
    2209             :                                 PROD_FP(TPE1, TPE2, bp[k]);             \
    2210             :                                 k++;                                    \
    2211             :                         } while (k < i && !op[k]);                   \
    2212             :                         for (; j < k; j++)                           \
    2213             :                                 rb[j] = curval;                         \
    2214             :                         has_nils |= is_##TPE2##_nil(curval);            \
    2215             :                 }                                                       \
    2216             :         } while (0)
    2217             : 
    2218             : #define ANALYTICAL_PROD_CALC_FP_CURRENT_ROW_TILL_UNBOUNDED(TPE1, TPE2, ARG3)    /* ARG3 is ignored here */ \
    2219             :         do {                                                            \
    2220             :                 TPE2 curval = TPE2##_nil;                               \
    2221             :                 l = i - 1;                                              \
    2222             :                 for (j = l; ; j--) {                                    \
    2223             :                         PROD_FP(TPE1, TPE2, bp[j]);                     \
    2224             :                         if (op[j] || j == k) {                          \
    2225             :                                 for (; ; l--) {                         \
    2226             :                                         rb[l] = curval;                 \
    2227             :                                         if (l == j)                     \
    2228             :                                                 break;                  \
    2229             :                                 }                                       \
    2230             :                                 has_nils |= is_##TPE2##_nil(curval);    \
    2231             :                                 if (j == k)                             \
    2232             :                                         break;                          \
    2233             :                                 l = j - 1;                              \
    2234             :                         }                                               \
    2235             :                 }                                                       \
    2236             :                 k = i;                                                  \
    2237             :         } while (0)
    2238             : 
    2239             : #define ANALYTICAL_PROD_CALC_FP_ALL_ROWS(TPE1, TPE2, ARG3)      /* ARG3 is ignored here */ \
    2240             :         do {                                                            \
    2241             :                 TPE2 curval = TPE2##_nil;                               \
    2242             :                 for (; j < i; j++) {                                 \
    2243             :                         TPE1 v = bp[j];                                 \
    2244             :                         PROD_FP(TPE1, TPE2, v);                         \
    2245             :                 }                                                       \
    2246             :                 for (; k < i; k++)                                   \
    2247             :                         rb[k] = curval;                                 \
    2248             :                 has_nils |= is_##TPE2##_nil(curval);                    \
    2249             :         } while (0)
    2250             : 
    2251             : #define ANALYTICAL_PROD_CALC_FP_CURRENT_ROW(TPE1, TPE2, ARG3)   /* ARG3 is ignored here */ \
    2252             :         do {                                                            \
    2253             :                 for (; k < i; k++) {                                 \
    2254             :                         TPE1 v = bp[k];                                 \
    2255             :                         if (is_##TPE1##_nil(v)) {                       \
    2256             :                                 rb[k] = TPE2##_nil;                     \
    2257             :                                 has_nils = true;                        \
    2258             :                         } else  {                                       \
    2259             :                                 rb[k] = (TPE2) v;                       \
    2260             :                         }                                               \
    2261             :                 }                                                       \
    2262             :         } while (0)
    2263             : 
    2264             : #define COMPUTE_LEVELN_PROD_FP(VAL, NOTHING1, TPE2, NOTHING2)           \
    2265             :         do {                                                            \
    2266             :                 if (!is_##TPE2##_nil(VAL)) {                            \
    2267             :                         if (is_##TPE2##_nil(computed)) {                \
    2268             :                                 computed = VAL;                         \
    2269             :                         } else if (ABSOLUTE(computed) > 1 && GDK_##TPE2##_max / ABSOLUTE(VAL) < ABSOLUTE(computed)) { \
    2270             :                                 if (abort_on_error)                     \
    2271             :                                         goto calc_overflow;             \
    2272             :                                 computed = TPE2##_nil;                  \
    2273             :                                 nils++;                                 \
    2274             :                         } else {                                        \
    2275             :                                 computed *= VAL;                        \
    2276             :                         }                                               \
    2277             :                 }                                                       \
    2278             :         } while (0)
    2279             : #define ANALYTICAL_PROD_CALC_FP_OTHERS(TPE1, TPE2, ARG3) /* ARG3 is ignored here */ \
    2280             :         do {                                                            \
    2281             :                 oid ncount = i - k;                                     \
    2282             :                 if ((res = GDKrebuild_segment_tree(ncount, sizeof(TPE2), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    2283             :                         goto cleanup;                                   \
    2284             :                 populate_segment_tree(TPE2, ncount, INIT_AGGREGATE_PROD, COMPUTE_LEVEL0_PROD, COMPUTE_LEVELN_PROD_FP, TPE1, TPE2, ARG3); \
    2285             :                 for (; k < i; k++)                                   \
    2286             :                         compute_on_segment_tree(TPE2, start[k] - j, end[k] - j, INIT_AGGREGATE_PROD, COMPUTE_LEVELN_PROD_FP, FINALIZE_AGGREGATE_PROD, TPE1, TPE2, ARG3); \
    2287             :                 j = k;                                                  \
    2288             :         } while (0)
    2289             : 
    2290             : #define ANALYTICAL_PROD_CALC_NUM_PARTITIONS(TPE1, TPE2, TPE3_OR_REAL_IMP, IMP) \
    2291             :         do {                                                            \
    2292             :                 TPE1 *restrict bp = (TPE1*)bi.base;                     \
    2293             :                 TPE2 *rb = (TPE2*)Tloc(r, 0);                           \
    2294             :                 if (p) {                                                \
    2295             :                         while (i < cnt) {                            \
    2296             :                                 if (np[i])      {                       \
    2297             : prod##TPE1##TPE2##IMP:                                                  \
    2298             :                                         IMP(TPE1, TPE2, TPE3_OR_REAL_IMP); \
    2299             :                                 }                                       \
    2300             :                                 if (!last)                              \
    2301             :                                         i++;                            \
    2302             :                         }                                               \
    2303             :                 }                                                       \
    2304             :                 if (!last) {                                            \
    2305             :                         last = true;                                    \
    2306             :                         i = cnt;                                        \
    2307             :                         goto prod##TPE1##TPE2##IMP;                     \
    2308             :                 }                                                       \
    2309             :         } while (0)
    2310             : 
    2311             : #ifdef HAVE_HGE
    2312             : #define ANALYTICAL_PROD_LIMIT(IMP)                                      \
    2313             :         case TYPE_lng:{                                                 \
    2314             :                 switch (tp1) {                                          \
    2315             :                 case TYPE_bte:                                          \
    2316             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(bte, lng, hge, ANALYTICAL_PROD_CALC_NUM_##IMP); \
    2317             :                         break;                                          \
    2318             :                 case TYPE_sht:                                          \
    2319             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(sht, lng, hge, ANALYTICAL_PROD_CALC_NUM_##IMP); \
    2320             :                         break;                                          \
    2321             :                 case TYPE_int:                                          \
    2322             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(int, lng, hge, ANALYTICAL_PROD_CALC_NUM_##IMP); \
    2323             :                         break;                                          \
    2324             :                 case TYPE_lng:                                          \
    2325             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(lng, lng, hge, ANALYTICAL_PROD_CALC_NUM_##IMP); \
    2326             :                         break;                                          \
    2327             :                 default:                                                \
    2328             :                         goto nosupport;                                 \
    2329             :                 }                                                       \
    2330             :                 break;                                                  \
    2331             :         }                                                               \
    2332             :         case TYPE_hge:{                                                 \
    2333             :                 switch (tp1) {                                          \
    2334             :                 case TYPE_bte:                                          \
    2335             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(bte, hge, HGEMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
    2336             :                         break;                                          \
    2337             :                 case TYPE_sht:                                          \
    2338             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(sht, hge, HGEMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
    2339             :                         break;                                          \
    2340             :                 case TYPE_int:                                          \
    2341             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(int, hge, HGEMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
    2342             :                         break;                                          \
    2343             :                 case TYPE_lng:                                          \
    2344             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(lng, hge, HGEMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
    2345             :                         break;                                          \
    2346             :                 case TYPE_hge:                                          \
    2347             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(hge, hge, HGEMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
    2348             :                         break;                                          \
    2349             :                 default:                                                \
    2350             :                         goto nosupport;                                 \
    2351             :                 }                                                       \
    2352             :                 break;                                                  \
    2353             :         }
    2354             : #else
    2355             : #define ANALYTICAL_PROD_LIMIT(IMP)                                      \
    2356             :         case TYPE_lng:{                                                 \
    2357             :                 switch (tp1) {                                          \
    2358             :                 case TYPE_bte:                                          \
    2359             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(bte, lng, LNGMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
    2360             :                         break;                                          \
    2361             :                 case TYPE_sht:                                          \
    2362             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(sht, lng, LNGMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
    2363             :                         break;                                          \
    2364             :                 case TYPE_int:                                          \
    2365             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(int, lng, LNGMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
    2366             :                         break;                                          \
    2367             :                 case TYPE_lng:                                          \
    2368             :                         ANALYTICAL_PROD_CALC_NUM_PARTITIONS(lng, lng, LNGMUL_CHECK, ANALYTICAL_PROD_CALC_NUM_LIMIT_##IMP); \
    2369             :                         break;                                          \
    2370             :                 default:                                                \
    2371             :                         goto nosupport;                                 \
    2372             :                 }                                                       \
    2373             :                 break;                                                  \
    2374             :         }
    2375             : #endif
    2376             : 
    2377             : #define ANALYTICAL_PROD_BRANCHES(IMP)                                   \
    2378             :         do {                                                            \
    2379             :                 switch (tp2) {                                          \
    2380             :                 case TYPE_bte:{                                         \
    2381             :                         switch (tp1) {                                  \
    2382             :                         case TYPE_bte:                                  \
    2383             :                                 ANALYTICAL_PROD_CALC_NUM_PARTITIONS(bte, bte, sht, ANALYTICAL_PROD_CALC_NUM_##IMP); \
    2384             :                                 break;                                  \
    2385             :                         default:                                        \
    2386             :                                 goto nosupport;                         \
    2387             :                         }                                               \
    2388             :                         break;                                          \
    2389             :                 }                                                       \
    2390             :                 case TYPE_sht:{                                         \
    2391             :                         switch (tp1) {                                  \
    2392             :                         case TYPE_bte:                                  \
    2393             :                                 ANALYTICAL_PROD_CALC_NUM_PARTITIONS(bte, sht, int, ANALYTICAL_PROD_CALC_NUM_##IMP); \
    2394             :                                 break;                                  \
    2395             :                         case TYPE_sht:                                  \
    2396             :                                 ANALYTICAL_PROD_CALC_NUM_PARTITIONS(sht, sht, int, ANALYTICAL_PROD_CALC_NUM_##IMP); \
    2397             :                                 break;                                  \
    2398             :                         default:                                        \
    2399             :                                 goto nosupport;                         \
    2400             :                         }                                               \
    2401             :                         break;                                          \
    2402             :                 }                                                       \
    2403             :                 case TYPE_int:{                                         \
    2404             :                         switch (tp1) {                                  \
    2405             :                         case TYPE_bte:                                  \
    2406             :                                 ANALYTICAL_PROD_CALC_NUM_PARTITIONS(bte, int, lng, ANALYTICAL_PROD_CALC_NUM_##IMP); \
    2407             :                                 break;                                  \
    2408             :                         case TYPE_sht:                                  \
    2409             :                                 ANALYTICAL_PROD_CALC_NUM_PARTITIONS(sht, int, lng, ANALYTICAL_PROD_CALC_NUM_##IMP); \
    2410             :                                 break;                                  \
    2411             :                         case TYPE_int:                                  \
    2412             :                                 ANALYTICAL_PROD_CALC_NUM_PARTITIONS(int, int, lng, ANALYTICAL_PROD_CALC_NUM_##IMP); \
    2413             :                                 break;                                  \
    2414             :                         default:                                        \
    2415             :                                 goto nosupport;                         \
    2416             :                         }                                               \
    2417             :                         break;                                          \
    2418             :                 }                                                       \
    2419             :                 ANALYTICAL_PROD_LIMIT(IMP)                              \
    2420             :                 case TYPE_flt:{                                         \
    2421             :                         switch (tp1) {                                  \
    2422             :                         case TYPE_flt:                                  \
    2423             :                                 ANALYTICAL_PROD_CALC_NUM_PARTITIONS(flt, flt, ;, ANALYTICAL_PROD_CALC_FP_##IMP); \
    2424             :                                 break;                                  \
    2425             :                         default:                                        \
    2426             :                                 goto nosupport;                         \
    2427             :                         }                                               \
    2428             :                         break;                                          \
    2429             :                 }                                                       \
    2430             :                 case TYPE_dbl:{                                         \
    2431             :                         switch (tp1) {                                  \
    2432             :                         case TYPE_flt:                                  \
    2433             :                                 ANALYTICAL_PROD_CALC_NUM_PARTITIONS(flt, dbl, ;, ANALYTICAL_PROD_CALC_FP_##IMP); \
    2434             :                                 break;                                  \
    2435             :                         case TYPE_dbl:                                  \
    2436             :                                 ANALYTICAL_PROD_CALC_NUM_PARTITIONS(dbl, dbl, ;, ANALYTICAL_PROD_CALC_FP_##IMP); \
    2437             :                                 break;                                  \
    2438             :                         default:                                        \
    2439             :                                 goto nosupport;                         \
    2440             :                         }                                               \
    2441             :                         break;                                          \
    2442             :                 }                                                       \
    2443             :                 default:                                                \
    2444             :                         goto nosupport;                                 \
    2445             :                 }                                                       \
    2446             :         } while (0)
    2447             : 
    2448             : gdk_return
    2449          31 : GDKanalyticalprod(BAT *r, BAT *p, BAT *o, BAT *b, BAT *s, BAT *e, int tp1, int tp2, int frame_type)
    2450             : {
    2451          31 :         BATiter pi = bat_iterator(p);
    2452          31 :         BATiter oi = bat_iterator(o);
    2453          31 :         BATiter bi = bat_iterator(b);
    2454          31 :         BATiter si = bat_iterator(s);
    2455          31 :         BATiter ei = bat_iterator(e);
    2456             :         bool has_nils = false, last = false;
    2457          31 :         oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b), *restrict start = si.base, *restrict end = ei.base,
    2458          31 :                 *levels_offset = NULL, tree_capacity = 0, nlevels = 0;
    2459          31 :         bit *np = pi.base, *op = oi.base;
    2460             :         int abort_on_error = 1;
    2461             :         BUN nils = 0;
    2462          31 :         void *segment_tree = NULL;
    2463             :         gdk_return res = GDK_SUCCEED;
    2464             : 
    2465          31 :         if (cnt > 0) {
    2466          31 :                 switch (frame_type) {
    2467          12 :                 case 3: /* unbounded until current row */       {
    2468         403 :                         ANALYTICAL_PROD_BRANCHES(UNBOUNDED_TILL_CURRENT_ROW);
    2469             :                 } break;
    2470           0 :                 case 4: /* current row until unbounded */       {
    2471           0 :                         ANALYTICAL_PROD_BRANCHES(CURRENT_ROW_TILL_UNBOUNDED);
    2472             :                 } break;
    2473           7 :                 case 5: /* all rows */  {
    2474         191 :                         ANALYTICAL_PROD_BRANCHES(ALL_ROWS);
    2475             :                 } break;
    2476           0 :                 case 6: /* current row */ {
    2477           0 :                         ANALYTICAL_PROD_BRANCHES(CURRENT_ROW);
    2478             :                 } break;
    2479          12 :                 default: {
    2480         956 :                         ANALYTICAL_PROD_BRANCHES(OTHERS);
    2481             :                 }
    2482             :                 }
    2483             :         }
    2484             : 
    2485          31 :         BATsetcount(r, cnt);
    2486          31 :         r->tnonil = !has_nils;
    2487          31 :         r->tnil = has_nils;
    2488          31 :         goto cleanup; /* all these gotos seem confusing but it cleans up the ending of the operator */
    2489           0 : calc_overflow:
    2490           0 :         GDKerror("22003!overflow in calculation.\n");
    2491             :         res = GDK_FAIL;
    2492          31 : cleanup:
    2493          31 :         bat_iterator_end(&pi);
    2494          31 :         bat_iterator_end(&oi);
    2495          31 :         bat_iterator_end(&bi);
    2496          31 :         bat_iterator_end(&si);
    2497          31 :         bat_iterator_end(&ei);
    2498          31 :         GDKfree(segment_tree);
    2499          31 :         return res;
    2500           0 : nosupport:
    2501           0 :         GDKerror("42000!type combination (prod(%s)->%s) not supported.\n", ATOMname(tp1), ATOMname(tp2));
    2502             :         res = GDK_FAIL;
    2503           0 :         goto cleanup;
    2504             : }
    2505             : 
    2506             : #ifdef HAVE_HGE
    2507             : #define LNG_HGE         hge
    2508             : #define GDK_LNG_HGE_max GDK_hge_max
    2509             : #define LNG_HGE_nil     hge_nil
    2510             : #else
    2511             : #define LNG_HGE         lng
    2512             : #define GDK_LNG_HGE_max GDK_lng_max
    2513             : #define LNG_HGE_nil     lng_nil
    2514             : #endif
    2515             : 
    2516             : /* average on integers */
    2517             : #define ANALYTICAL_AVERAGE_CALC_NUM_STEP1(TPE, IMP, ARG)                \
    2518             :         if (!is_##TPE##_nil(ARG)) {                                     \
    2519             :                 ADD_WITH_CHECK(ARG, sum, LNG_HGE, sum, GDK_LNG_HGE_max, goto avg_overflow##TPE##IMP); \
    2520             :                 /* count only when no overflow occurs */                \
    2521             :                 n++;                                                    \
    2522             :         }
    2523             : 
    2524             : #define ANALYTICAL_AVERAGE_CALC_NUM_STEP2(TPE, IMP)             \
    2525             :                         if (0) {                                \
    2526             : avg_overflow##TPE##IMP:                                         \
    2527             :                                 assert(n > 0);                       \
    2528             :                                 if (sum >= 0) {                      \
    2529             :                                         a = (TPE) (sum / n);    \
    2530             :                                         rr = (lng) (sum % n);   \
    2531             :                                 } else {                        \
    2532             :                                         sum = -sum;             \
    2533             :                                         a = - (TPE) (sum / n);  \
    2534             :                                         rr = (lng) (sum % n);   \
    2535             :                                         if (r) {                \
    2536             :                                                 a--;            \
    2537             :                                                 rr = n - rr;    \
    2538             :                                         }                       \
    2539             :                                 }
    2540             : 
    2541             : #define ANALYTICAL_AVG_IMP_NUM_UNBOUNDED_TILL_CURRENT_ROW(TPE, IMP)     \
    2542             :         do {                                                            \
    2543             :                 TPE a = 0;                                              \
    2544             :                 dbl curval = dbl_nil;                                   \
    2545             :                 for (; k < i;) {                                     \
    2546             :                         j = k;                                          \
    2547             :                         do {                                            \
    2548             :                                 ANALYTICAL_AVERAGE_CALC_NUM_STEP1(TPE, IMP, bp[k]) \
    2549             :                                 ANALYTICAL_AVERAGE_CALC_NUM_STEP2(TPE, IMP) \
    2550             :                                         while (k < i && !op[k]) {    \
    2551             :                                                 TPE v = bp[k++];        \
    2552             :                                                 if (is_##TPE##_nil(v))  \
    2553             :                                                         continue;       \
    2554             :                                                 AVERAGE_ITER(TPE, v, a, rr, n); \
    2555             :                                         }                               \
    2556             :                                         curval = a + (dbl) rr / n;      \
    2557             :                                         goto calc_done##TPE##IMP;       \
    2558             :                                 }                                       \
    2559             :                                 k++;                                    \
    2560             :                         } while (k < i && !op[k]);                   \
    2561             :                         curval = n > 0 ? (dbl) sum / n : dbl_nil;    \
    2562             : calc_done##TPE##IMP:                                                    \
    2563             :                         for (; j < k; j++)                           \
    2564             :                                 rb[j] = curval;                         \
    2565             :                         has_nils |= (n == 0);                           \
    2566             :                 }                                                       \
    2567             :                 n = 0;                                                  \
    2568             :                 sum = 0;                                                \
    2569             :         } while (0)
    2570             : 
    2571             : #define ANALYTICAL_AVG_IMP_NUM_CURRENT_ROW_TILL_UNBOUNDED(TPE, IMP)     \
    2572             :         do {                                                            \
    2573             :                 TPE a = 0;                                              \
    2574             :                 dbl curval = dbl_nil;                                   \
    2575             :                 l = i - 1;                                              \
    2576             :                 for (j = l; ; j--) {                                    \
    2577             :                         ANALYTICAL_AVERAGE_CALC_NUM_STEP1(TPE, IMP, bp[j]) \
    2578             :                         ANALYTICAL_AVERAGE_CALC_NUM_STEP2(TPE, IMP)     \
    2579             :                                 while (!(op[j] || j == k)) {            \
    2580             :                                         TPE v = bp[j--];                \
    2581             :                                         if (is_##TPE##_nil(v))          \
    2582             :                                                 continue;               \
    2583             :                                         AVERAGE_ITER(TPE, v, a, rr, n); \
    2584             :                                 }                                       \
    2585             :                                 curval = a + (dbl) rr / n;              \
    2586             :                                 goto calc_done##TPE##IMP;               \
    2587             :                         }                                               \
    2588             :                         if (op[j] || j == k) {                          \
    2589             :                                 curval = n > 0 ? (dbl) sum / n : dbl_nil; \
    2590             : calc_done##TPE##IMP:                                                    \
    2591             :                                 for (; ; l--) {                         \
    2592             :                                         rb[l] = curval;                 \
    2593             :                                         if (l == j)                     \
    2594             :                                                 break;                  \
    2595             :                                 }                                       \
    2596             :                                 has_nils |= (n == 0);                   \
    2597             :                                 if (j == k)                             \
    2598             :                                         break;                          \
    2599             :                                 l = j - 1;                              \
    2600             :                         }                                               \
    2601             :                 }                                                       \
    2602             :                 n = 0;                                                  \
    2603             :                 sum = 0;                                                \
    2604             :                 k = i;                                                  \
    2605             :         } while (0)
    2606             : 
    2607             : #define ANALYTICAL_AVG_IMP_NUM_ALL_ROWS(TPE, IMP)                       \
    2608             :         do {                                                            \
    2609             :                 TPE a = 0;                                              \
    2610             :                 for (; j < i; j++) {                                 \
    2611             :                         TPE v = bp[j];                                  \
    2612             :                         ANALYTICAL_AVERAGE_CALC_NUM_STEP1(TPE, IMP, v)  \
    2613             :                         ANALYTICAL_AVERAGE_CALC_NUM_STEP2(TPE, IMP)     \
    2614             :                                 for (; j < i; j++) {                 \
    2615             :                                         v = bp[j];                      \
    2616             :                                         if (is_##TPE##_nil(v))          \
    2617             :                                                 continue;               \
    2618             :                                         AVERAGE_ITER(TPE, v, a, rr, n); \
    2619             :                                 }                                       \
    2620             :                                 curval = a + (dbl) rr / n;              \
    2621             :                                 goto calc_done##TPE##IMP;               \
    2622             :                         }                                               \
    2623             :                 }                                                       \
    2624             :                 curval = n > 0 ? (dbl) sum / n : dbl_nil;            \
    2625             : calc_done##TPE##IMP:                                                    \
    2626             :                 for (; k < i; k++)                                   \
    2627             :                         rb[k] = curval;                                 \
    2628             :                 has_nils |= (n == 0);                                   \
    2629             :                 n = 0;                                                  \
    2630             :                 sum = 0;                                                \
    2631             :         } while (0)
    2632             : 
    2633             : #define ANALYTICAL_AVG_IMP_NUM_CURRENT_ROW(TPE, IMP)    \
    2634             :         do {                                            \
    2635             :                 for (; k < i; k++) {                 \
    2636             :                         TPE v = bp[k];                  \
    2637             :                         if (is_##TPE##_nil(v)) {        \
    2638             :                                 rb[k] = dbl_nil;        \
    2639             :                                 has_nils = true;        \
    2640             :                         } else  {                       \
    2641             :                                 rb[k] = (dbl) v;        \
    2642             :                         }                               \
    2643             :                 }                                       \
    2644             :         } while (0)
    2645             : 
    2646             : #define avg_num_deltas(TPE) typedef struct avg_num_deltas##TPE { TPE a; lng n; lng rr;} avg_num_deltas##TPE;
    2647             : avg_num_deltas(bte)
    2648             : avg_num_deltas(sht)
    2649             : avg_num_deltas(int)
    2650             : avg_num_deltas(lng)
    2651             : 
    2652             : #define INIT_AGGREGATE_AVG_NUM(TPE, NOTHING1, NOTHING2) \
    2653             :         do {                                            \
    2654             :                 computed = (avg_num_deltas##TPE) {0};   \
    2655             :         } while (0)
    2656             : #define COMPUTE_LEVEL0_AVG_NUM(X, TPE, NOTHING1, NOTHING2)              \
    2657             :         do {                                                            \
    2658             :                 TPE v = bp[j + X];                                      \
    2659             :                 computed = is_##TPE##_nil(v) ? (avg_num_deltas##TPE){0} : (avg_num_deltas##TPE) {.a = v, .n = 1}; \
    2660             :         } while (0)
    2661             : #define COMPUTE_LEVELN_AVG_NUM(VAL, TPE, NOTHING1, NOTHING2)            \
    2662             :         do {                                                            \
    2663             :                 if (VAL.n)                                              \
    2664             :                         AVERAGE_ITER(TPE, VAL.a, computed.a, computed.rr, computed.n); \
    2665             :         } while (0)
    2666             : #define FINALIZE_AGGREGATE_AVG_NUM(TPE, NOTHING1, NOTHING2)             \
    2667             :         do {                                                            \
    2668             :                 if (computed.n == 0) {                                  \
    2669             :                         rb[k] = dbl_nil;                                \
    2670             :                         has_nils = true;                                \
    2671             :                 } else {                                                \
    2672             :                         rb[k] = computed.a + (dbl) computed.rr / computed.n; \
    2673             :                 }                                                       \
    2674             :         } while (0)
    2675             : #define ANALYTICAL_AVG_IMP_NUM_OTHERS(TPE, IMP)                         \
    2676             :         do {                                                            \
    2677             :                 oid ncount = i - k;                                     \
    2678             :                 if ((res = GDKrebuild_segment_tree(ncount, sizeof(avg_num_deltas##TPE), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    2679             :                         goto cleanup;                                   \
    2680             :                 populate_segment_tree(avg_num_deltas##TPE, ncount, INIT_AGGREGATE_AVG_NUM, COMPUTE_LEVEL0_AVG_NUM, COMPUTE_LEVELN_AVG_NUM, TPE, NOTHING, NOTHING); \
    2681             :                 for (; k < i; k++)                                   \
    2682             :                         compute_on_segment_tree(avg_num_deltas##TPE, start[k] - j, end[k] - j, INIT_AGGREGATE_AVG_NUM, COMPUTE_LEVELN_AVG_NUM, FINALIZE_AGGREGATE_AVG_NUM, TPE, NOTHING, NOTHING); \
    2683             :                 j = k;                                                  \
    2684             :         } while (0)
    2685             : 
    2686             : /* average on floating-points */
    2687             : #define ANALYTICAL_AVG_IMP_FP_UNBOUNDED_TILL_CURRENT_ROW(TPE, IMP)      \
    2688             :         do {                                                            \
    2689             :                 TPE a = 0;                                              \
    2690             :                 dbl curval = dbl_nil;                                   \
    2691             :                 for (; k < i;) {                                     \
    2692             :                         j = k;                                          \
    2693             :                         do {                                            \
    2694             :                                 if (!is_##TPE##_nil(bp[k]))             \
    2695             :                                         AVERAGE_ITER_FLOAT(TPE, bp[k], a, n); \
    2696             :                                 k++;                                    \
    2697             :                         } while (k < i && !op[k]);                   \
    2698             :                         if (n > 0)                                   \
    2699             :                                 curval = a;                             \
    2700             :                         else                                            \
    2701             :                                 has_nils = true;                        \
    2702             :                         for (; j < k; j++)                           \
    2703             :                                 rb[j] = curval;                         \
    2704             :                 }                                                       \
    2705             :                 n = 0;                                                  \
    2706             :         } while (0)
    2707             : 
    2708             : #define ANALYTICAL_AVG_IMP_FP_CURRENT_ROW_TILL_UNBOUNDED(TPE, IMP)      \
    2709             :         do {                                                            \
    2710             :                 TPE a = 0;                                              \
    2711             :                 dbl curval = dbl_nil;                                   \
    2712             :                 l = i - 1;                                              \
    2713             :                 for (j = l; ; j--) {                                    \
    2714             :                         if (!is_##TPE##_nil(bp[j]))                     \
    2715             :                                 AVERAGE_ITER_FLOAT(TPE, bp[j], a, n);   \
    2716             :                         if (op[j] || j == k) {                          \
    2717             :                                 for (; ; l--) {                         \
    2718             :                                         rb[l] = curval;                 \
    2719             :                                         if (l == j)                     \
    2720             :                                                 break;                  \
    2721             :                                 }                                       \
    2722             :                                 has_nils |= is_##TPE##_nil(curval);     \
    2723             :                                 if (j == k)                             \
    2724             :                                         break;                          \
    2725             :                                 l = j - 1;                              \
    2726             :                         }                                               \
    2727             :                 }                                                       \
    2728             :                 n = 0;                                                  \
    2729             :                 k = i;                                                  \
    2730             :         } while (0)
    2731             : 
    2732             : #define ANALYTICAL_AVG_IMP_FP_ALL_ROWS(TPE, IMP)                        \
    2733             :         do {                                                            \
    2734             :                 TPE a = 0;                                              \
    2735             :                 dbl curval = dbl_nil;                                   \
    2736             :                 for (; j < i; j++) {                                 \
    2737             :                         TPE v = bp[j];                                  \
    2738             :                         if (!is_##TPE##_nil(v))                         \
    2739             :                                 AVERAGE_ITER_FLOAT(TPE, v, a, n);       \
    2740             :                 }                                                       \
    2741             :                 if (n > 0)                                           \
    2742             :                         curval = a;                                     \
    2743             :                 else                                                    \
    2744             :                         has_nils = true;                                \
    2745             :                 for (; k < i; k++)                                   \
    2746             :                         rb[k] = curval;                                 \
    2747             :                 n = 0;                                                  \
    2748             :         } while (0)
    2749             : 
    2750             : #define ANALYTICAL_AVG_IMP_FP_CURRENT_ROW(TPE, IMP)      ANALYTICAL_AVG_IMP_NUM_CURRENT_ROW(TPE, IMP)
    2751             : 
    2752             : #define avg_fp_deltas(TPE) typedef struct avg_fp_deltas_##TPE {TPE a; lng n;} avg_fp_deltas_##TPE;
    2753             : avg_fp_deltas(flt)
    2754             : avg_fp_deltas(dbl)
    2755             : 
    2756             : #define INIT_AGGREGATE_AVG_FP(TPE, NOTHING1, NOTHING2)  \
    2757             :         do {                                            \
    2758             :                 computed = (avg_fp_deltas_##TPE) {0};   \
    2759             :         } while (0)
    2760             : #define COMPUTE_LEVEL0_AVG_FP(X, TPE, NOTHING1, NOTHING2)               \
    2761             :         do {                                                            \
    2762             :                 TPE v = bp[j + X];                                      \
    2763             :                 computed = is_##TPE##_nil(v) ? (avg_fp_deltas_##TPE) {0} : (avg_fp_deltas_##TPE) {.n = 1, .a = v}; \
    2764             :         } while (0)
    2765             : #define COMPUTE_LEVELN_AVG_FP(VAL, TPE, NOTHING1, NOTHING2)             \
    2766             :         do {                                                            \
    2767             :                 if (VAL.n)                                              \
    2768             :                         AVERAGE_ITER_FLOAT(TPE, VAL.a, computed.a, computed.n); \
    2769             :         } while (0)
    2770             : #define FINALIZE_AGGREGATE_AVG_FP(TPE, NOTHING1, NOTHING2)      \
    2771             :         do {                                                    \
    2772             :                 if (computed.n == 0) {                          \
    2773             :                         rb[k] = dbl_nil;                        \
    2774             :                         has_nils = true;                        \
    2775             :                 } else {                                        \
    2776             :                         rb[k] = computed.a;                     \
    2777             :                 }                                               \
    2778             :         } while (0)
    2779             : #define ANALYTICAL_AVG_IMP_FP_OTHERS(TPE, IMP)                          \
    2780             :         do {                                                            \
    2781             :                 oid ncount = i - k;                                     \
    2782             :                 if ((res = GDKrebuild_segment_tree(ncount, sizeof(avg_fp_deltas_##TPE), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    2783             :                         goto cleanup;                                   \
    2784             :                 populate_segment_tree(avg_fp_deltas_##TPE, ncount, INIT_AGGREGATE_AVG_FP, COMPUTE_LEVEL0_AVG_FP, COMPUTE_LEVELN_AVG_FP, TPE, NOTHING, NOTHING); \
    2785             :                 for (; k < i; k++)                                   \
    2786             :                         compute_on_segment_tree(avg_fp_deltas_##TPE, start[k] - j, end[k] - j, INIT_AGGREGATE_AVG_FP, COMPUTE_LEVELN_AVG_FP, FINALIZE_AGGREGATE_AVG_FP, TPE, NOTHING, NOTHING); \
    2787             :                 j = k;                                                  \
    2788             :         } while (0)
    2789             : 
    2790             : #define ANALYTICAL_AVG_PARTITIONS(TPE, IMP, REAL_IMP)           \
    2791             :         do {                                                    \
    2792             :                 TPE *restrict bp = (TPE*)bi.base;               \
    2793             :                 if (p) {                                        \
    2794             :                         while (i < cnt) {                    \
    2795             :                                 if (np[i])      {               \
    2796             : avg##TPE##IMP:                                                  \
    2797             :                                         REAL_IMP(TPE, IMP);     \
    2798             :                                 }                               \
    2799             :                                 if (!last)                      \
    2800             :                                         i++;                    \
    2801             :                         }                                       \
    2802             :                 }                                               \
    2803             :                 if (!last) {                                    \
    2804             :                         last = true;                            \
    2805             :                         i = cnt;                                \
    2806             :                         goto avg##TPE##IMP;                     \
    2807             :                 }                                               \
    2808             :         } while (0)
    2809             : 
    2810             : #ifdef HAVE_HGE
    2811             : avg_num_deltas(hge)
    2812             : #define ANALYTICAL_AVG_LIMIT(IMP)                                       \
    2813             :         case TYPE_hge:                                                  \
    2814             :                 ANALYTICAL_AVG_PARTITIONS(hge, IMP, ANALYTICAL_AVG_IMP_NUM_##IMP); \
    2815             :                 break;
    2816             : #else
    2817             : #define ANALYTICAL_AVG_LIMIT(IMP)
    2818             : #endif
    2819             : 
    2820             : #define ANALYTICAL_AVG_BRANCHES(IMP)                                    \
    2821             :         do {                                                            \
    2822             :                 switch (tpe) {                                          \
    2823             :                 case TYPE_bte:                                          \
    2824             :                         ANALYTICAL_AVG_PARTITIONS(bte, IMP, ANALYTICAL_AVG_IMP_NUM_##IMP); \
    2825             :                         break;                                          \
    2826             :                 case TYPE_sht:                                          \
    2827             :                         ANALYTICAL_AVG_PARTITIONS(sht, IMP, ANALYTICAL_AVG_IMP_NUM_##IMP); \
    2828             :                         break;                                          \
    2829             :                 case TYPE_int:                                          \
    2830             :                         ANALYTICAL_AVG_PARTITIONS(int, IMP, ANALYTICAL_AVG_IMP_NUM_##IMP); \
    2831             :                         break;                                          \
    2832             :                 case TYPE_lng:                                          \
    2833             :                         ANALYTICAL_AVG_PARTITIONS(lng, IMP, ANALYTICAL_AVG_IMP_NUM_##IMP); \
    2834             :                         break;                                          \
    2835             :                 ANALYTICAL_AVG_LIMIT(IMP)                               \
    2836             :                 case TYPE_flt:                                          \
    2837             :                         ANALYTICAL_AVG_PARTITIONS(flt, IMP, ANALYTICAL_AVG_IMP_FP_##IMP); \
    2838             :                         break;                                          \
    2839             :                 case TYPE_dbl:                                          \
    2840             :                         ANALYTICAL_AVG_PARTITIONS(dbl, IMP, ANALYTICAL_AVG_IMP_FP_##IMP); \
    2841             :                         break;                                          \
    2842             :                 default:                                                \
    2843             :                         goto nosupport;                                 \
    2844             :                 }                                                       \
    2845             :         } while (0)
    2846             : 
    2847             : gdk_return
    2848          70 : GDKanalyticalavg(BAT *r, BAT *p, BAT *o, BAT *b, BAT *s, BAT *e, int tpe, int frame_type)
    2849             : {
    2850          70 :         BATiter pi = bat_iterator(p);
    2851          70 :         BATiter oi = bat_iterator(o);
    2852          70 :         BATiter bi = bat_iterator(b);
    2853          70 :         BATiter si = bat_iterator(s);
    2854          70 :         BATiter ei = bat_iterator(e);
    2855             :         bool has_nils = false, last = false;
    2856          70 :         oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b), *restrict start = si.base, *restrict end = ei.base,
    2857          70 :                 *levels_offset = NULL, tree_capacity = 0, nlevels = 0;
    2858             :         lng n = 0, rr = 0;
    2859          70 :         dbl *rb = (dbl *) Tloc(r, 0), curval = dbl_nil;
    2860          70 :         bit *np = pi.base, *op = oi.base;
    2861             :         bool abort_on_error = true;
    2862             :         BUN nils = 0;
    2863          70 :         void *segment_tree = NULL;
    2864             :         gdk_return res = GDK_SUCCEED;
    2865             : #ifdef HAVE_HGE
    2866             :         hge sum = 0;
    2867             : #else
    2868             :         lng sum = 0;
    2869             : #endif
    2870             : 
    2871          70 :         if (cnt > 0) {
    2872          70 :                 switch (frame_type) {
    2873          24 :                 case 3: /* unbounded until current row */       {
    2874         579 :                         ANALYTICAL_AVG_BRANCHES(UNBOUNDED_TILL_CURRENT_ROW);
    2875             :                 } break;
    2876           1 :                 case 4: /* current row until unbounded */       {
    2877          11 :                         ANALYTICAL_AVG_BRANCHES(CURRENT_ROW_TILL_UNBOUNDED);
    2878             :                 } break;
    2879          16 :                 case 5: /* all rows */  {
    2880         337 :                         ANALYTICAL_AVG_BRANCHES(ALL_ROWS);
    2881             :                 } break;
    2882           0 :                 case 6: /* current row */ {
    2883           0 :                         ANALYTICAL_AVG_BRANCHES(CURRENT_ROW);
    2884             :                 } break;
    2885          29 :                 default: {
    2886        2083 :                         ANALYTICAL_AVG_BRANCHES(OTHERS);
    2887             :                 }
    2888             :                 }
    2889             :         }
    2890             : 
    2891          70 :         BATsetcount(r, cnt);
    2892          70 :         r->tnonil = !has_nils;
    2893          70 :         r->tnil = has_nils;
    2894          70 : cleanup:
    2895          70 :         bat_iterator_end(&pi);
    2896          70 :         bat_iterator_end(&oi);
    2897          70 :         bat_iterator_end(&bi);
    2898          70 :         bat_iterator_end(&si);
    2899          70 :         bat_iterator_end(&ei);
    2900          70 :         GDKfree(segment_tree);
    2901          70 :         return res;
    2902           0 : nosupport:
    2903           0 :         GDKerror("42000!average of type %s to dbl unsupported.\n", ATOMname(tpe));
    2904             :         res = GDK_FAIL;
    2905           0 :         goto cleanup;
    2906             : }
    2907             : 
    2908             : #ifdef TRUNCATE_NUMBERS
    2909             : #define ANALYTICAL_AVERAGE_INT_CALC_FINALIZE(avg, rem, ncnt)    \
    2910             :         do {                                                    \
    2911             :                 if (rem > 0 && avg < 0)                           \
    2912             :                         avg++;                                  \
    2913             :         } while(0)
    2914             : #else
    2915             : #define ANALYTICAL_AVERAGE_INT_CALC_FINALIZE(avg, rem, ncnt)    \
    2916             :         do {                                                    \
    2917             :                 if (rem > 0) {                                       \
    2918             :                         if (avg < 0) {                               \
    2919             :                                 if (2*rem > ncnt)            \
    2920             :                                         avg++;                  \
    2921             :                         } else {                                \
    2922             :                                 if (2*rem >= ncnt)           \
    2923             :                                         avg++;                  \
    2924             :                         }                                       \
    2925             :                 }                                               \
    2926             :         } while(0)
    2927             : #endif
    2928             : 
    2929             : #define ANALYTICAL_AVG_INT_UNBOUNDED_TILL_CURRENT_ROW(TPE)              \
    2930             :         do {                                                            \
    2931             :                 TPE avg = 0;                                            \
    2932             :                 for (; k < i;) {                                     \
    2933             :                         j = k;                                          \
    2934             :                         do {                                            \
    2935             :                                 if (!is_##TPE##_nil(bp[k]))             \
    2936             :                                         AVERAGE_ITER(TPE, bp[k], avg, rem, ncnt); \
    2937             :                                 k++;                                    \
    2938             :                         } while (k < i && !op[k]);                   \
    2939             :                         if (ncnt == 0) {                                \
    2940             :                                 has_nils = true;                        \
    2941             :                                 for (; j < k; j++)                   \
    2942             :                                         rb[j] = TPE##_nil;              \
    2943             :                         } else {                                        \
    2944             :                                 TPE avgfinal = avg;                     \
    2945             :                                 ANALYTICAL_AVERAGE_INT_CALC_FINALIZE(avgfinal, rem, ncnt); \
    2946             :                                 for (; j < k; j++)                   \
    2947             :                                         rb[j] = avgfinal;               \
    2948             :                         }                                               \
    2949             :                 }                                                       \
    2950             :                 rem = 0;                                                \
    2951             :                 ncnt = 0;                                               \
    2952             :         } while (0)
    2953             : 
    2954             : #define ANALYTICAL_AVG_INT_CURRENT_ROW_TILL_UNBOUNDED(TPE)              \
    2955             :         do {                                                            \
    2956             :                 TPE avg = 0;                                            \
    2957             :                 l = i - 1;                                              \
    2958             :                 for (j = l; ; j--) {                                    \
    2959             :                         if (!is_##TPE##_nil(bp[j]))                     \
    2960             :                                 AVERAGE_ITER(TPE, bp[j], avg, rem, ncnt); \
    2961             :                         if (op[j] || j == k) {                          \
    2962             :                                 if (ncnt == 0) {                        \
    2963             :                                         has_nils = true;                \
    2964             :                                         for (; ; l--) {                 \
    2965             :                                                 rb[l] = TPE##_nil;      \
    2966             :                                                 if (l == j)             \
    2967             :                                                         break;          \
    2968             :                                         }                               \
    2969             :                                 } else {                                \
    2970             :                                         TPE avgfinal = avg;             \
    2971             :                                         ANALYTICAL_AVERAGE_INT_CALC_FINALIZE(avgfinal, rem, ncnt); \
    2972             :                                         for (; ; l--) {                 \
    2973             :                                                 rb[l] = avgfinal;       \
    2974             :                                                 if (l == j)             \
    2975             :                                                         break;          \
    2976             :                                         }                               \
    2977             :                                 }                                       \
    2978             :                                 if (j == k)                             \
    2979             :                                         break;                          \
    2980             :                                 l = j - 1;                              \
    2981             :                         }                                               \
    2982             :                 }                                                       \
    2983             :                 rem = 0;                                                \
    2984             :                 ncnt = 0;                                               \
    2985             :                 k = i;                                                  \
    2986             :         } while (0)
    2987             : 
    2988             : #define ANALYTICAL_AVG_INT_ALL_ROWS(TPE)                                \
    2989             :         do {                                                            \
    2990             :                 TPE avg = 0;                                            \
    2991             :                 for (; j < i; j++) {                                 \
    2992             :                         TPE v = bp[j];                                  \
    2993             :                         if (!is_##TPE##_nil(v))                         \
    2994             :                                 AVERAGE_ITER(TPE, v, avg, rem, ncnt);   \
    2995             :                 }                                                       \
    2996             :                 if (ncnt == 0) {                                        \
    2997             :                         for (; k < i; k++)                           \
    2998             :                                 rb[k] = TPE##_nil;                      \
    2999             :                         has_nils = true;                                \
    3000             :                 } else {                                                \
    3001             :                         ANALYTICAL_AVERAGE_INT_CALC_FINALIZE(avg, rem, ncnt); \
    3002             :                         for (; k < i; k++)                           \
    3003             :                                 rb[k] = avg;                            \
    3004             :                 }                                                       \
    3005             :                 rem = 0;                                                \
    3006             :                 ncnt = 0;                                               \
    3007             :         } while (0)
    3008             : 
    3009             : #define ANALYTICAL_AVG_INT_CURRENT_ROW(TPE)             \
    3010             :         do {                                            \
    3011             :                 for (; k < i; k++) {                 \
    3012             :                         TPE v = bp[k];                  \
    3013             :                         rb[k] = bp[k];                  \
    3014             :                         has_nils |= is_##TPE##_nil(v);  \
    3015             :                 }                                       \
    3016             :         } while (0)
    3017             : 
    3018             : #define avg_int_deltas(TPE) typedef struct avg_int_deltas_##TPE { TPE avg; lng rem, ncnt;} avg_int_deltas_##TPE;
    3019             : avg_int_deltas(bte)
    3020             : avg_int_deltas(sht)
    3021             : avg_int_deltas(int)
    3022             : avg_int_deltas(lng)
    3023             : 
    3024             : #define INIT_AGGREGATE_AVG_INT(TPE, NOTHING1, NOTHING2) \
    3025             :         do {                                            \
    3026             :                 computed = (avg_int_deltas_##TPE) {0};  \
    3027             :         } while (0)
    3028             : #define COMPUTE_LEVEL0_AVG_INT(X, TPE, NOTHING1, NOTHING2)              \
    3029             :         do {                                                            \
    3030             :                 TPE v = bp[j + X];                                      \
    3031             :                 computed = is_##TPE##_nil(v) ? (avg_int_deltas_##TPE) {0} : (avg_int_deltas_##TPE) {.avg = v, .ncnt = 1}; \
    3032             :         } while (0)
    3033             : #define COMPUTE_LEVELN_AVG_INT(VAL, TPE, NOTHING1, NOTHING2)            \
    3034             :         do {                                                            \
    3035             :                 if (VAL.ncnt)                                           \
    3036             :                         AVERAGE_ITER(TPE, VAL.avg, computed.avg, computed.rem, computed.ncnt); \
    3037             :         } while (0)
    3038             : #define FINALIZE_AGGREGATE_AVG_INT(TPE, NOTHING1, NOTHING2)             \
    3039             :         do {                                                            \
    3040             :                 if (computed.ncnt == 0) {                               \
    3041             :                         has_nils = true;                                \
    3042             :                         rb[k] = TPE##_nil;                              \
    3043             :                 } else {                                                \
    3044             :                         ANALYTICAL_AVERAGE_INT_CALC_FINALIZE(computed.avg, computed.rem, computed.ncnt); \
    3045             :                         rb[k] = computed.avg;                           \
    3046             :                 }                                                       \
    3047             :         } while (0)
    3048             : #define ANALYTICAL_AVG_INT_OTHERS(TPE)                                  \
    3049             :         do {                                                            \
    3050             :                 oid ncount = i - k;                                     \
    3051             :                 if ((res = GDKrebuild_segment_tree(ncount, sizeof(avg_int_deltas_##TPE), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    3052             :                         goto cleanup;                                   \
    3053             :                 populate_segment_tree(avg_int_deltas_##TPE, ncount, INIT_AGGREGATE_AVG_INT, COMPUTE_LEVEL0_AVG_INT, COMPUTE_LEVELN_AVG_INT, TPE, NOTHING, NOTHING); \
    3054             :                 for (; k < i; k++)                                   \
    3055             :                         compute_on_segment_tree(avg_int_deltas_##TPE, start[k] - j, end[k] - j, INIT_AGGREGATE_AVG_INT, COMPUTE_LEVELN_AVG_INT, FINALIZE_AGGREGATE_AVG_INT, TPE, NOTHING, NOTHING); \
    3056             :                 j = k;                                                  \
    3057             :         } while (0)
    3058             : 
    3059             : #define ANALYTICAL_AVG_INT_PARTITIONS(TPE, IMP)                         \
    3060             :         do {                                                            \
    3061             :                 TPE *restrict bp = (TPE*)bi.base, *rb = (TPE *) Tloc(r, 0); \
    3062             :                 if (p) {                                                \
    3063             :                         while (i < cnt) {                            \
    3064             :                                 if (np[i])      {                       \
    3065             : avg##TPE##IMP:                                                          \
    3066             :                                         IMP(TPE);                       \
    3067             :                                 }                                       \
    3068             :                                 if (!last)                              \
    3069             :                                         i++;                            \
    3070             :                         }                                               \
    3071             :                 }                                                       \
    3072             :                 if (!last) {                                            \
    3073             :                         last = true;                                    \
    3074             :                         i = cnt;                                        \
    3075             :                         goto avg##TPE##IMP;                             \
    3076             :                 }                                                       \
    3077             :         } while (0)
    3078             : 
    3079             : #ifdef HAVE_HGE
    3080             : avg_int_deltas(hge)
    3081             : #define ANALYTICAL_AVG_INT_LIMIT(IMP)                                   \
    3082             :         case TYPE_hge:                                                  \
    3083             :                 ANALYTICAL_AVG_INT_PARTITIONS(hge, ANALYTICAL_AVG_INT_##IMP); \
    3084             :                 break;
    3085             : #else
    3086             : #define ANALYTICAL_AVG_INT_LIMIT(IMP)
    3087             : #endif
    3088             : 
    3089             : #define ANALYTICAL_AVG_INT_BRANCHES(IMP)                                \
    3090             :         do {                                                            \
    3091             :                 switch (tpe) {                                          \
    3092             :                 case TYPE_bte:                                          \
    3093             :                         ANALYTICAL_AVG_INT_PARTITIONS(bte, ANALYTICAL_AVG_INT_##IMP); \
    3094             :                         break;                                          \
    3095             :                 case TYPE_sht:                                          \
    3096             :                         ANALYTICAL_AVG_INT_PARTITIONS(sht, ANALYTICAL_AVG_INT_##IMP); \
    3097             :                         break;                                          \
    3098             :                 case TYPE_int:                                          \
    3099             :                         ANALYTICAL_AVG_INT_PARTITIONS(int, ANALYTICAL_AVG_INT_##IMP); \
    3100             :                         break;                                          \
    3101             :                 case TYPE_lng:                                          \
    3102             :                         ANALYTICAL_AVG_INT_PARTITIONS(lng, ANALYTICAL_AVG_INT_##IMP); \
    3103             :                         break;                                          \
    3104             :                 ANALYTICAL_AVG_INT_LIMIT(IMP)                           \
    3105             :                 default:                                                \
    3106             :                         goto nosupport;                                 \
    3107             :                 }                                                       \
    3108             :         } while (0)
    3109             : 
    3110             : gdk_return
    3111          48 : GDKanalyticalavginteger(BAT *r, BAT *p, BAT *o, BAT *b, BAT *s, BAT *e, int tpe, int frame_type)
    3112             : {
    3113          48 :         BATiter pi = bat_iterator(p);
    3114          48 :         BATiter oi = bat_iterator(o);
    3115          48 :         BATiter bi = bat_iterator(b);
    3116          48 :         BATiter si = bat_iterator(s);
    3117          48 :         BATiter ei = bat_iterator(e);
    3118             :         bool has_nils = false, last = false;
    3119          48 :         oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b), *restrict start = si.base, *restrict end = ei.base,
    3120          48 :                 *levels_offset = NULL, tree_capacity = 0, nlevels = 0;
    3121             :         lng rem = 0, ncnt = 0;
    3122          48 :         bit *np = pi.base, *op = oi.base;
    3123          48 :         void *segment_tree = NULL;
    3124             :         gdk_return res = GDK_SUCCEED;
    3125             : 
    3126          48 :         if (cnt > 0) {
    3127          48 :                 switch (frame_type) {
    3128          18 :                 case 3: /* unbounded until current row */       {
    3129         708 :                         ANALYTICAL_AVG_INT_BRANCHES(UNBOUNDED_TILL_CURRENT_ROW);
    3130             :                 } break;
    3131           0 :                 case 4: /* current row until unbounded */       {
    3132           0 :                         ANALYTICAL_AVG_INT_BRANCHES(CURRENT_ROW_TILL_UNBOUNDED);
    3133             :                 } break;
    3134          17 :                 case 5: /* all rows */  {
    3135      308509 :                         ANALYTICAL_AVG_INT_BRANCHES(ALL_ROWS);
    3136             :                 } break;
    3137           0 :                 case 6: /* current row */ {
    3138           0 :                         ANALYTICAL_AVG_INT_BRANCHES(CURRENT_ROW);
    3139             :                 } break;
    3140          13 :                 default: {
    3141        1203 :                         ANALYTICAL_AVG_INT_BRANCHES(OTHERS);
    3142             :                 }
    3143             :                 }
    3144             :         }
    3145             : 
    3146          48 :         BATsetcount(r, cnt);
    3147          48 :         r->tnonil = !has_nils;
    3148          48 :         r->tnil = has_nils;
    3149          48 : cleanup:
    3150          48 :         bat_iterator_end(&pi);
    3151          48 :         bat_iterator_end(&oi);
    3152          48 :         bat_iterator_end(&bi);
    3153          48 :         bat_iterator_end(&si);
    3154          48 :         bat_iterator_end(&ei);
    3155          48 :         GDKfree(segment_tree);
    3156          48 :         return res;
    3157           0 : nosupport:
    3158           0 :         GDKerror("42000!average of type %s to %s unsupported.\n", ATOMname(tpe), ATOMname(tpe));
    3159             :         res = GDK_FAIL;
    3160           0 :         goto cleanup;
    3161             : }
    3162             : 
    3163             : #define ANALYTICAL_STDEV_VARIANCE_UNBOUNDED_TILL_CURRENT_ROW(TPE, SAMPLE, OP) \
    3164             :         do {                                                            \
    3165             :                 TPE *restrict bp = (TPE*)bi.base;                       \
    3166             :                 for (; k < i;) {                                     \
    3167             :                         j = k;                                          \
    3168             :                         do {                                            \
    3169             :                                 TPE v = bp[k];                          \
    3170             :                                 if (!is_##TPE##_nil(v))  {              \
    3171             :                                         n++;                            \
    3172             :                                         delta = (dbl) v - mean;         \
    3173             :                                         mean += delta / n;              \
    3174             :                                         m2 += delta * ((dbl) v - mean); \
    3175             :                                 }                                       \
    3176             :                                 k++;                                    \
    3177             :                         } while (k < i && !op[k]);                   \
    3178             :                         if (isinf(m2)) {                                \
    3179             :                                 goto overflow;                          \
    3180             :                         } else if (n > SAMPLE) {                     \
    3181             :                                 for (; j < k; j++)                   \
    3182             :                                         rb[j] = OP;                     \
    3183             :                         } else {                                        \
    3184             :                                 for (; j < k; j++)                   \
    3185             :                                         rb[j] = dbl_nil;                \
    3186             :                                 has_nils = true;                        \
    3187             :                         }                                               \
    3188             :                 }                                                       \
    3189             :                 n = 0;                                                  \
    3190             :                 mean = 0;                                               \
    3191             :                 m2 = 0;                                                 \
    3192             :         } while (0)
    3193             : 
    3194             : #define ANALYTICAL_STDEV_VARIANCE_CURRENT_ROW_TILL_UNBOUNDED(TPE, SAMPLE, OP) \
    3195             :         do {                                                            \
    3196             :                 TPE *restrict bp = (TPE*)bi.base;                       \
    3197             :                 l = i - 1;                                              \
    3198             :                 for (j = l; ; j--) {                                    \
    3199             :                         TPE v = bp[j];                                  \
    3200             :                         if (!is_##TPE##_nil(v)) {                       \
    3201             :                                 n++;                                    \
    3202             :                                 delta = (dbl) v - mean;                 \
    3203             :                                 mean += delta / n;                      \
    3204             :                                 m2 += delta * ((dbl) v - mean);         \
    3205             :                         }                                               \
    3206             :                         if (op[j] || j == k) {                          \
    3207             :                                 if (isinf(m2)) {                        \
    3208             :                                         goto overflow;                  \
    3209             :                                 } else if (n > SAMPLE) {             \
    3210             :                                         for (; ; l--) {                 \
    3211             :                                                 rb[l] = OP;             \
    3212             :                                                 if (l == j)             \
    3213             :                                                         break;          \
    3214             :                                         }                               \
    3215             :                                 } else {                                \
    3216             :                                         for (; ; l--) {                 \
    3217             :                                                 rb[l] = dbl_nil;        \
    3218             :                                                 if (l == j)             \
    3219             :                                                         break;          \
    3220             :                                         }                               \
    3221             :                                         has_nils = true;                \
    3222             :                                 }                                       \
    3223             :                                 if (j == k)                             \
    3224             :                                         break;                          \
    3225             :                                 l = j - 1;                              \
    3226             :                         }                                               \
    3227             :                 }                                                       \
    3228             :                 n = 0;                                                  \
    3229             :                 mean = 0;                                               \
    3230             :                 m2 = 0;                                                 \
    3231             :                 k = i;                                                  \
    3232             :         } while (0)
    3233             : 
    3234             : #define ANALYTICAL_STDEV_VARIANCE_ALL_ROWS(TPE, SAMPLE, OP)     \
    3235             :         do {                                                    \
    3236             :                 TPE *restrict bp = (TPE*)bi.base;               \
    3237             :                 for (; j < i; j++) {                         \
    3238             :                         TPE v = bp[j];                          \
    3239             :                         if (is_##TPE##_nil(v))                  \
    3240             :                                 continue;                       \
    3241             :                         n++;                                    \
    3242             :                         delta = (dbl) v - mean;                 \
    3243             :                         mean += delta / n;                      \
    3244             :                         m2 += delta * ((dbl) v - mean);         \
    3245             :                 }                                               \
    3246             :                 if (isinf(m2)) {                                \
    3247             :                         goto overflow;                          \
    3248             :                 } else if (n > SAMPLE) {                     \
    3249             :                         for (; k < i; k++)                   \
    3250             :                                 rb[k] = OP;                     \
    3251             :                 } else {                                        \
    3252             :                         for (; k < i; k++)                   \
    3253             :                                 rb[k] = dbl_nil;                \
    3254             :                         has_nils = true;                        \
    3255             :                 }                                               \
    3256             :                 n = 0;                                          \
    3257             :                 mean = 0;                                       \
    3258             :                 m2 = 0;                                         \
    3259             :         } while (0)
    3260             : 
    3261             : #define ANALYTICAL_STDEV_VARIANCE_CURRENT_ROW(TPE, SAMPLE, OP)  \
    3262             :         do {                                                    \
    3263             :                 for (; k < i; k++)                           \
    3264             :                         rb[k] = SAMPLE == 1 ? dbl_nil : 0;      \
    3265             :                 has_nils = is_dbl_nil(rb[k - 1]);               \
    3266             :         } while (0)
    3267             : 
    3268             : typedef struct stdev_var_deltas {
    3269             :         BUN n;
    3270             :         dbl mean, delta, m2;
    3271             : } stdev_var_deltas;
    3272             : 
    3273             : #define INIT_AGGREGATE_STDEV_VARIANCE(TPE, SAMPLE, OP)  \
    3274             :         do {                                            \
    3275             :                 computed = (stdev_var_deltas) {0};      \
    3276             :         } while (0)
    3277             : #define COMPUTE_LEVEL0_STDEV_VARIANCE(X, TPE, SAMPLE, OP)               \
    3278             :         do {                                                            \
    3279             :                 TPE v = bp[j + X];                                      \
    3280             :                 computed = is_##TPE##_nil(v) ? (stdev_var_deltas) {0} : (stdev_var_deltas) {.n = 1, .mean = (dbl)v, .delta = (dbl)v}; \
    3281             :         } while (0)
    3282             : #define COMPUTE_LEVELN_STDEV_VARIANCE(VAL, TPE, SAMPLE, OP)             \
    3283             :         do {                                                            \
    3284             :                 if (VAL.n) {                                            \
    3285             :                         computed.n++;                                   \
    3286             :                         computed.delta = VAL.delta - computed.mean;     \
    3287             :                         computed.mean += computed.delta / computed.n;   \
    3288             :                         computed.m2 += computed.delta * (VAL.delta - computed.mean); \
    3289             :                 }                                                       \
    3290             :         } while (0)
    3291             : #define FINALIZE_AGGREGATE_STDEV_VARIANCE(TPE, SAMPLE, OP)      \
    3292             :         do {                                                    \
    3293             :                 dbl m2 = computed.m2;                           \
    3294             :                 BUN n = computed.n;                             \
    3295             :                 if (isinf(m2)) {                                \
    3296             :                         goto overflow;                          \
    3297             :                 } else if (n > SAMPLE) {                     \
    3298             :                         rb[k] = OP;                             \
    3299             :                 } else {                                        \
    3300             :                         rb[k] = dbl_nil;                        \
    3301             :                         has_nils = true;                        \
    3302             :                 }                                               \
    3303             :         } while (0)
    3304             : #define ANALYTICAL_STDEV_VARIANCE_OTHERS(TPE, SAMPLE, OP)               \
    3305             :         do {                                                            \
    3306             :                 TPE *restrict bp = (TPE*)bi.base;                       \
    3307             :                 oid ncount = i - k;                                     \
    3308             :                 if ((res = GDKrebuild_segment_tree(ncount, sizeof(stdev_var_deltas), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    3309             :                         goto cleanup;                                   \
    3310             :                 populate_segment_tree(stdev_var_deltas, ncount, INIT_AGGREGATE_STDEV_VARIANCE, COMPUTE_LEVEL0_STDEV_VARIANCE, COMPUTE_LEVELN_STDEV_VARIANCE, TPE, SAMPLE, OP); \
    3311             :                 for (; k < i; k++)                                   \
    3312             :                         compute_on_segment_tree(stdev_var_deltas, start[k] - j, end[k] - j, INIT_AGGREGATE_STDEV_VARIANCE, COMPUTE_LEVELN_STDEV_VARIANCE, FINALIZE_AGGREGATE_STDEV_VARIANCE, TPE, SAMPLE, OP); \
    3313             :                 j = k;                                                  \
    3314             :         } while (0)
    3315             : 
    3316             : #define ANALYTICAL_STATISTICS_PARTITIONS(TPE, SAMPLE, OP, IMP)  \
    3317             :         do {                                                    \
    3318             :                 if (p) {                                        \
    3319             :                         while (i < cnt) {                    \
    3320             :                                 if (np[i])      {               \
    3321             : statistics##TPE##IMP:                                           \
    3322             :                                         IMP(TPE, SAMPLE, OP);   \
    3323             :                                 }                               \
    3324             :                                 if (!last)                      \
    3325             :                                         i++;                    \
    3326             :                         }                                       \
    3327             :                 }                                               \
    3328             :                 if (!last) {                                    \
    3329             :                         last = true;                            \
    3330             :                         i = cnt;                                \
    3331             :                         goto statistics##TPE##IMP;              \
    3332             :                 }                                               \
    3333             :         } while (0)
    3334             : 
    3335             : #ifdef HAVE_HGE
    3336             : #define ANALYTICAL_STATISTICS_LIMIT(IMP, SAMPLE, OP)                    \
    3337             :         case TYPE_hge:                                                  \
    3338             :                 ANALYTICAL_STATISTICS_PARTITIONS(hge, SAMPLE, OP, ANALYTICAL_##IMP); \
    3339             :                 break;
    3340             : #else
    3341             : #define ANALYTICAL_STATISTICS_LIMIT(IMP, SAMPLE, OP)
    3342             : #endif
    3343             : 
    3344             : #define ANALYTICAL_STATISTICS_BRANCHES(IMP, SAMPLE, OP)                 \
    3345             :         do {                                                            \
    3346             :                 switch (tpe) {                                          \
    3347             :                 case TYPE_bte:                                          \
    3348             :                         ANALYTICAL_STATISTICS_PARTITIONS(bte, SAMPLE, OP, ANALYTICAL_##IMP); \
    3349             :                         break;                                          \
    3350             :                 case TYPE_sht:                                          \
    3351             :                         ANALYTICAL_STATISTICS_PARTITIONS(sht, SAMPLE, OP, ANALYTICAL_##IMP); \
    3352             :                         break;                                          \
    3353             :                 case TYPE_int:                                          \
    3354             :                         ANALYTICAL_STATISTICS_PARTITIONS(int, SAMPLE, OP, ANALYTICAL_##IMP); \
    3355             :                         break;                                          \
    3356             :                 case TYPE_lng:                                          \
    3357             :                         ANALYTICAL_STATISTICS_PARTITIONS(lng, SAMPLE, OP, ANALYTICAL_##IMP); \
    3358             :                         break;                                          \
    3359             :                 case TYPE_flt:                                          \
    3360             :                         ANALYTICAL_STATISTICS_PARTITIONS(flt, SAMPLE, OP, ANALYTICAL_##IMP); \
    3361             :                         break;                                          \
    3362             :                 case TYPE_dbl:                                          \
    3363             :                         ANALYTICAL_STATISTICS_PARTITIONS(dbl, SAMPLE, OP, ANALYTICAL_##IMP); \
    3364             :                         break;                                          \
    3365             :                 ANALYTICAL_STATISTICS_LIMIT(IMP, SAMPLE, OP)            \
    3366             :                 default:                                                \
    3367             :                         goto nosupport;                                 \
    3368             :                 }                                                       \
    3369             :         } while (0)
    3370             : 
    3371             : #define GDK_ANALYTICAL_STDEV_VARIANCE(NAME, SAMPLE, OP, DESC)           \
    3372             : gdk_return                                                              \
    3373             : GDKanalytical_##NAME(BAT *r, BAT *p, BAT *o, BAT *b, BAT *s, BAT *e, int tpe, int frame_type) \
    3374             : {                                                                       \
    3375             :         BATiter pi = bat_iterator(p);                                   \
    3376             :         BATiter oi = bat_iterator(o);                                   \
    3377             :         BATiter bi = bat_iterator(b);                                   \
    3378             :         BATiter si = bat_iterator(s);                                   \
    3379             :         BATiter ei = bat_iterator(e);                                   \
    3380             :         bool has_nils = false, last = false;                            \
    3381             :         oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b), *restrict start = si.base, *restrict end = ei.base, \
    3382             :                 *levels_offset = NULL, tree_capacity = 0, nlevels = 0;  \
    3383             :         lng n = 0;                                                      \
    3384             :         bit *np = pi.base, *op = oi.base;                               \
    3385             :         dbl *rb = (dbl *) Tloc(r, 0), mean = 0, m2 = 0, delta;          \
    3386             :         void *segment_tree = NULL;                                      \
    3387             :         gdk_return res = GDK_SUCCEED;                                   \
    3388             :                                                                         \
    3389             :         if (cnt > 0) {                                                       \
    3390             :                 switch (frame_type) {                                   \
    3391             :                 case 3: /* unbounded until current row */       {       \
    3392             :                         ANALYTICAL_STATISTICS_BRANCHES(STDEV_VARIANCE_UNBOUNDED_TILL_CURRENT_ROW, SAMPLE, OP); \
    3393             :                 } break;                                                \
    3394             :                 case 4: /* current row until unbounded */       {       \
    3395             :                         ANALYTICAL_STATISTICS_BRANCHES(STDEV_VARIANCE_CURRENT_ROW_TILL_UNBOUNDED, SAMPLE, OP); \
    3396             :                 } break;                                                \
    3397             :                 case 5: /* all rows */  {                               \
    3398             :                         ANALYTICAL_STATISTICS_BRANCHES(STDEV_VARIANCE_ALL_ROWS, SAMPLE, OP); \
    3399             :                 } break;                                                \
    3400             :                 case 6: /* current row */ {                             \
    3401             :                         ANALYTICAL_STATISTICS_BRANCHES(STDEV_VARIANCE_CURRENT_ROW, SAMPLE, OP); \
    3402             :                 } break;                                                \
    3403             :                 default: {                                              \
    3404             :                         ANALYTICAL_STATISTICS_BRANCHES(STDEV_VARIANCE_OTHERS, SAMPLE, OP); \
    3405             :                 }                                                       \
    3406             :                 }                                                       \
    3407             :         }                                                               \
    3408             :                                                                         \
    3409             :         BATsetcount(r, cnt);                                            \
    3410             :         r->tnonil = !has_nils;                                               \
    3411             :         r->tnil = has_nils;                                          \
    3412             :         goto cleanup; /* all these gotos seem confusing but it cleans up the ending of the operator */ \
    3413             : overflow:                                                               \
    3414             :         GDKerror("22003!overflow in calculation.\n");                 \
    3415             :         res = GDK_FAIL;                                                 \
    3416             : cleanup:                                                                \
    3417             :         bat_iterator_end(&pi);                                              \
    3418             :         bat_iterator_end(&oi);                                              \
    3419             :         bat_iterator_end(&bi);                                              \
    3420             :         bat_iterator_end(&si);                                              \
    3421             :         bat_iterator_end(&ei);                                              \
    3422             :         GDKfree(segment_tree);                                          \
    3423             :         return res;                                                     \
    3424             : nosupport:                                                              \
    3425             :         GDKerror("42000!%s of type %s unsupported.\n", DESC, ATOMname(tpe)); \
    3426             :         res = GDK_FAIL;                                                 \
    3427             :         goto cleanup;                                                   \
    3428             : }
    3429             : 
    3430         813 : GDK_ANALYTICAL_STDEV_VARIANCE(stddev_samp, 1, sqrt(m2 / (n - 1)), "standard deviation")
    3431         328 : GDK_ANALYTICAL_STDEV_VARIANCE(stddev_pop, 0, sqrt(m2 / n), "standard deviation")
    3432         331 : GDK_ANALYTICAL_STDEV_VARIANCE(variance_samp, 1, m2 / (n - 1), "variance")
    3433         946 : GDK_ANALYTICAL_STDEV_VARIANCE(variance_pop, 0, m2 / n, "variance")
    3434             : 
    3435             : #define ANALYTICAL_COVARIANCE_UNBOUNDED_TILL_CURRENT_ROW(TPE, SAMPLE, OP) \
    3436             :         do {                                                            \
    3437             :                 TPE *bp1 = (TPE*)b1i.base, *bp2 = (TPE*)b2i.base;       \
    3438             :                 for (; k < i;) {                                     \
    3439             :                         j = k;                                          \
    3440             :                         do {                                            \
    3441             :                                 TPE v1 = bp1[k], v2 = bp2[k];           \
    3442             :                                 if (!is_##TPE##_nil(v1) && !is_##TPE##_nil(v2)) { \
    3443             :                                         n++;                            \
    3444             :                                         delta1 = (dbl) v1 - mean1;      \
    3445             :                                         mean1 += delta1 / n;            \
    3446             :                                         delta2 = (dbl) v2 - mean2;      \
    3447             :                                         mean2 += delta2 / n;            \
    3448             :                                         m2 += delta1 * ((dbl) v2 - mean2); \
    3449             :                                 }                                       \
    3450             :                                 k++;                                    \
    3451             :                         } while (k < i && !op[k]);                   \
    3452             :                         if (isinf(m2))                                  \
    3453             :                                 goto overflow;                          \
    3454             :                         if (n > SAMPLE) {                            \
    3455             :                                 for (; j < k; j++)                   \
    3456             :                                         rb[j] = OP;                     \
    3457             :                         } else {                                        \
    3458             :                                 for (; j < k; j++)                   \
    3459             :                                         rb[j] = dbl_nil;                \
    3460             :                                 has_nils = true;                        \
    3461             :                         }                                               \
    3462             :                 }                                                       \
    3463             :                 n = 0;                                                  \
    3464             :                 mean1 = 0;                                              \
    3465             :                 mean2 = 0;                                              \
    3466             :                 m2 = 0;                                                 \
    3467             :         } while (0)
    3468             : 
    3469             : #define ANALYTICAL_COVARIANCE_CURRENT_ROW_TILL_UNBOUNDED(TPE, SAMPLE, OP) \
    3470             :         do {                                                            \
    3471             :                 TPE *bp1 = (TPE*)b1i.base, *bp2 = (TPE*)b2i.base;       \
    3472             :                 l = i - 1;                                              \
    3473             :                 for (j = l; ; j--) {                                    \
    3474             :                         TPE v1 = bp1[j], v2 = bp2[j];                   \
    3475             :                         if (!is_##TPE##_nil(v1) && !is_##TPE##_nil(v2)) { \
    3476             :                                 n++;                                    \
    3477             :                                 delta1 = (dbl) v1 - mean1;              \
    3478             :                                 mean1 += delta1 / n;                    \
    3479             :                                 delta2 = (dbl) v2 - mean2;              \
    3480             :                                 mean2 += delta2 / n;                    \
    3481             :                                 m2 += delta1 * ((dbl) v2 - mean2);      \
    3482             :                         }                                               \
    3483             :                         if (op[j] || j == k) {                          \
    3484             :                                 if (isinf(m2))                          \
    3485             :                                         goto overflow;                  \
    3486             :                                 if (n > SAMPLE) {                    \
    3487             :                                         for (; ; l--) {                 \
    3488             :                                                 rb[l] = OP;             \
    3489             :                                                 if (l == j)             \
    3490             :                                                         break;          \
    3491             :                                         }                               \
    3492             :                                 } else {                                \
    3493             :                                         for (; ; l--) {                 \
    3494             :                                                 rb[l] = dbl_nil;        \
    3495             :                                                 if (l == j)             \
    3496             :                                                         break;          \
    3497             :                                         }                               \
    3498             :                                         has_nils = true;                \
    3499             :                                 }                                       \
    3500             :                                 if (j == k)                             \
    3501             :                                         break;                          \
    3502             :                                 l = j - 1;                              \
    3503             :                         }                                               \
    3504             :                 }                                                       \
    3505             :                 n = 0;                                                  \
    3506             :                 mean1 = 0;                                              \
    3507             :                 mean2 = 0;                                              \
    3508             :                 m2 = 0;                                                 \
    3509             :                 k = i;                                                  \
    3510             :         } while (0)
    3511             : 
    3512             : #define ANALYTICAL_COVARIANCE_ALL_ROWS(TPE, SAMPLE, OP)                 \
    3513             :         do {                                                            \
    3514             :                 TPE *bp1 = (TPE*)b1i.base, *bp2 = (TPE*)b2i.base;       \
    3515             :                 for (; j < i; j++) {                                 \
    3516             :                         TPE v1 = bp1[j], v2 = bp2[j];                   \
    3517             :                         if (!is_##TPE##_nil(v1) && !is_##TPE##_nil(v2)) { \
    3518             :                                 n++;                                    \
    3519             :                                 delta1 = (dbl) v1 - mean1;              \
    3520             :                                 mean1 += delta1 / n;                    \
    3521             :                                 delta2 = (dbl) v2 - mean2;              \
    3522             :                                 mean2 += delta2 / n;                    \
    3523             :                                 m2 += delta1 * ((dbl) v2 - mean2);      \
    3524             :                         }                                               \
    3525             :                 }                                                       \
    3526             :                 if (isinf(m2))                                          \
    3527             :                         goto overflow;                                  \
    3528             :                 if (n > SAMPLE) {                                    \
    3529             :                         for (; k < i; k++)                           \
    3530             :                                 rb[k] = OP;                             \
    3531             :                 } else {                                                \
    3532             :                         for (; k < i; k++)                           \
    3533             :                                 rb[k] = dbl_nil;                        \
    3534             :                         has_nils = true;                                \
    3535             :                 }                                                       \
    3536             :                 n = 0;                                                  \
    3537             :                 mean1 = 0;                                              \
    3538             :                 mean2 = 0;                                              \
    3539             :                 m2 = 0;                                                 \
    3540             :         } while (0)
    3541             : 
    3542             : #define ANALYTICAL_COVARIANCE_CURRENT_ROW(TPE, SAMPLE, OP)      \
    3543             :         do {                                                    \
    3544             :                 for (; k < i; k++)                           \
    3545             :                         rb[k] = SAMPLE == 1 ? dbl_nil : 0;      \
    3546             :                 has_nils = is_dbl_nil(rb[k - 1]);               \
    3547             :         } while (0)
    3548             : 
    3549             : typedef struct covariance_deltas {
    3550             :         BUN n;
    3551             :         dbl mean1, mean2, delta1, delta2, m2;
    3552             : } covariance_deltas;
    3553             : 
    3554             : #define INIT_AGGREGATE_COVARIANCE(TPE, SAMPLE, OP)      \
    3555             :         do {                                            \
    3556             :                 computed = (covariance_deltas) {0};     \
    3557             :         } while (0)
    3558             : #define COMPUTE_LEVEL0_COVARIANCE(X, TPE, SAMPLE, OP)                   \
    3559             :         do {                                                            \
    3560             :                 TPE v1 = bp1[j + X], v2 = bp2[j + X];                   \
    3561             :                 computed = is_##TPE##_nil(v1) || is_##TPE##_nil(v2) ? (covariance_deltas) {0} \
    3562             :                                                                                                                         : (covariance_deltas) {.n = 1, .mean1 = (dbl)v1, .mean2 = (dbl)v2, .delta1 = (dbl)v1, .delta2 = (dbl)v2}; \
    3563             :         } while (0)
    3564             : #define COMPUTE_LEVELN_COVARIANCE(VAL, TPE, SAMPLE, OP)                 \
    3565             :         do {                                                            \
    3566             :                 if (VAL.n) {                                            \
    3567             :                         computed.n++;                                   \
    3568             :                         computed.delta1 = VAL.delta1 - computed.mean1;  \
    3569             :                         computed.mean1 += computed.delta1 / computed.n; \
    3570             :                         computed.delta2 = VAL.delta2 - computed.mean2;  \
    3571             :                         computed.mean2 += computed.delta2 / computed.n; \
    3572             :                         computed.m2 += computed.delta1 * (VAL.delta2 - computed.mean2); \
    3573             :                 }                                                       \
    3574             :         } while (0)
    3575             : #define FINALIZE_AGGREGATE_COVARIANCE(TPE, SAMPLE, OP) FINALIZE_AGGREGATE_STDEV_VARIANCE(TPE, SAMPLE, OP)
    3576             : #define ANALYTICAL_COVARIANCE_OTHERS(TPE, SAMPLE, OP)                   \
    3577             :         do {                                                            \
    3578             :                 TPE *bp1 = (TPE*)b1i.base, *bp2 = (TPE*)b2i.base;       \
    3579             :                 oid ncount = i - k;                                     \
    3580             :                 if ((res = GDKrebuild_segment_tree(ncount, sizeof(covariance_deltas), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    3581             :                         goto cleanup;                                   \
    3582             :                 populate_segment_tree(covariance_deltas, ncount, INIT_AGGREGATE_COVARIANCE, COMPUTE_LEVEL0_COVARIANCE, COMPUTE_LEVELN_COVARIANCE, TPE, SAMPLE, OP); \
    3583             :                 for (; k < i; k++)                                   \
    3584             :                         compute_on_segment_tree(covariance_deltas, start[k] - j, end[k] - j, INIT_AGGREGATE_COVARIANCE, COMPUTE_LEVELN_COVARIANCE, FINALIZE_AGGREGATE_COVARIANCE, TPE, SAMPLE, OP); \
    3585             :                 j = k;                                                  \
    3586             :         } while (0)
    3587             : 
    3588             : #define GDK_ANALYTICAL_COVARIANCE(NAME, SAMPLE, OP)                     \
    3589             : gdk_return                                                              \
    3590             : GDKanalytical_##NAME(BAT *r, BAT *p, BAT *o, BAT *b1, BAT *b2, BAT *s, BAT *e, int tpe, int frame_type) \
    3591             : {                                                                       \
    3592             :         BATiter pi = bat_iterator(p);                                   \
    3593             :         BATiter oi = bat_iterator(o);                                   \
    3594             :         BATiter b1i = bat_iterator(b1);                                 \
    3595             :         BATiter b2i = bat_iterator(b2);                                 \
    3596             :         BATiter si = bat_iterator(s);                                   \
    3597             :         BATiter ei = bat_iterator(e);                                   \
    3598             :         bool has_nils = false, last = false;                            \
    3599             :         oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b1), *restrict start = si.base, *restrict end = ei.base, \
    3600             :                 *levels_offset = NULL, tree_capacity = 0, nlevels = 0;  \
    3601             :         lng n = 0;                                                      \
    3602             :         bit *np = pi.base, *op = oi.base;                               \
    3603             :         dbl *rb = (dbl *) Tloc(r, 0), mean1 = 0, mean2 = 0, m2 = 0, delta1, delta2; \
    3604             :         void *segment_tree = NULL;                                      \
    3605             :         gdk_return res = GDK_SUCCEED;                                   \
    3606             :                                                                         \
    3607             :         if (cnt > 0) {                                                       \
    3608             :                 switch (frame_type) {                                   \
    3609             :                 case 3: /* unbounded until current row */       {       \
    3610             :                         ANALYTICAL_STATISTICS_BRANCHES(COVARIANCE_UNBOUNDED_TILL_CURRENT_ROW, SAMPLE, OP); \
    3611             :                 } break;                                                \
    3612             :                 case 4: /* current row until unbounded */       {       \
    3613             :                         ANALYTICAL_STATISTICS_BRANCHES(COVARIANCE_CURRENT_ROW_TILL_UNBOUNDED, SAMPLE, OP); \
    3614             :                 } break;                                                \
    3615             :                 case 5: /* all rows */  {                               \
    3616             :                         ANALYTICAL_STATISTICS_BRANCHES(COVARIANCE_ALL_ROWS, SAMPLE, OP); \
    3617             :                 } break;                                                \
    3618             :                 case 6: /* current row */ {                             \
    3619             :                         ANALYTICAL_STATISTICS_BRANCHES(COVARIANCE_CURRENT_ROW, SAMPLE, OP); \
    3620             :                 } break;                                                \
    3621             :                 default: {                                              \
    3622             :                         ANALYTICAL_STATISTICS_BRANCHES(COVARIANCE_OTHERS, SAMPLE, OP); \
    3623             :                 }                                                       \
    3624             :                 }                                                       \
    3625             :         }                                                               \
    3626             :                                                                         \
    3627             :         BATsetcount(r, cnt);                                            \
    3628             :         r->tnonil = !has_nils;                                               \
    3629             :         r->tnil = has_nils;                                          \
    3630             :         goto cleanup; /* all these gotos seem confusing but it cleans up the ending of the operator */ \
    3631             : overflow:                                                               \
    3632             :         GDKerror("22003!overflow in calculation.\n");                 \
    3633             :         res = GDK_FAIL;                                                 \
    3634             : cleanup:                                                                \
    3635             :         bat_iterator_end(&pi);                                              \
    3636             :         bat_iterator_end(&oi);                                              \
    3637             :         bat_iterator_end(&b1i);                                             \
    3638             :         bat_iterator_end(&b2i);                                             \
    3639             :         bat_iterator_end(&si);                                              \
    3640             :         bat_iterator_end(&ei);                                              \
    3641             :         GDKfree(segment_tree);                                          \
    3642             :         return res;                                                     \
    3643             : nosupport:                                                              \
    3644             :         GDKerror("42000!covariance of type %s unsupported.\n", ATOMname(tpe)); \
    3645             :         res = GDK_FAIL;                                                 \
    3646             :         goto cleanup;                                                   \
    3647             : }
    3648             : 
    3649        1314 : GDK_ANALYTICAL_COVARIANCE(covariance_samp, 1, m2 / (n - 1))
    3650        1416 : GDK_ANALYTICAL_COVARIANCE(covariance_pop, 0, m2 / n)
    3651             : 
    3652             : #define ANALYTICAL_CORRELATION_UNBOUNDED_TILL_CURRENT_ROW(TPE, SAMPLE, OP)      /* SAMPLE and OP not used */ \
    3653             :         do {                                                            \
    3654             :                 TPE *bp1 = (TPE*)b1i.base, *bp2 = (TPE*)b2i.base;       \
    3655             :                 for (; k < i;) {                                     \
    3656             :                         j = k;                                          \
    3657             :                         do {                                            \
    3658             :                                 TPE v1 = bp1[k], v2 = bp2[k];           \
    3659             :                                 if (!is_##TPE##_nil(v1) && !is_##TPE##_nil(v2)) { \
    3660             :                                         n++;                            \
    3661             :                                         delta1 = (dbl) v1 - mean1;      \
    3662             :                                         mean1 += delta1 / n;            \
    3663             :                                         delta2 = (dbl) v2 - mean2;      \
    3664             :                                         mean2 += delta2 / n;            \
    3665             :                                         aux = (dbl) v2 - mean2;         \
    3666             :                                         up += delta1 * aux;             \
    3667             :                                         down1 += delta1 * ((dbl) v1 - mean1); \
    3668             :                                         down2 += delta2 * aux;          \
    3669             :                                 }                                       \
    3670             :                                 k++;                                    \
    3671             :                         } while (k < i && !op[k]);                   \
    3672             :                         if (isinf(up) || isinf(down1) || isinf(down2))  \
    3673             :                                 goto overflow;                          \
    3674             :                         if (n != 0 && down1 != 0 && down2 != 0) {       \
    3675             :                                 rr = (up / n) / (sqrt(down1 / n) * sqrt(down2 / n)); \
    3676             :                                 assert(!is_dbl_nil(rr));                \
    3677             :                         } else {                                        \
    3678             :                                 rr = dbl_nil;                           \
    3679             :                                 has_nils = true;                        \
    3680             :                         }                                               \
    3681             :                         for (; j < k; j++)                           \
    3682             :                                 rb[j] = rr;                             \
    3683             :                 }                                                       \
    3684             :                 n = 0;                                                  \
    3685             :                 mean1 = 0;                                              \
    3686             :                 mean2 = 0;                                              \
    3687             :                 up = 0;                                                 \
    3688             :                 down1 = 0;                                              \
    3689             :                 down2 = 0;                                              \
    3690             :         } while (0)
    3691             : 
    3692             : #define ANALYTICAL_CORRELATION_CURRENT_ROW_TILL_UNBOUNDED(TPE, SAMPLE, OP)      /* SAMPLE and OP not used */ \
    3693             :         do {                                                            \
    3694             :                 TPE *bp1 = (TPE*)b1i.base, *bp2 = (TPE*)b2i.base;       \
    3695             :                 l = i - 1;                                              \
    3696             :                 for (j = l; ; j--) {                                    \
    3697             :                         TPE v1 = bp1[j], v2 = bp2[j];                   \
    3698             :                         if (!is_##TPE##_nil(v1) && !is_##TPE##_nil(v2)) { \
    3699             :                                 n++;                                    \
    3700             :                                 delta1 = (dbl) v1 - mean1;              \
    3701             :                                 mean1 += delta1 / n;                    \
    3702             :                                 delta2 = (dbl) v2 - mean2;              \
    3703             :                                 mean2 += delta2 / n;                    \
    3704             :                                 aux = (dbl) v2 - mean2;                 \
    3705             :                                 up += delta1 * aux;                     \
    3706             :                                 down1 += delta1 * ((dbl) v1 - mean1);   \
    3707             :                                 down2 += delta2 * aux;                  \
    3708             :                         }                                               \
    3709             :                         if (op[j] || j == k) {                          \
    3710             :                                 if (isinf(up) || isinf(down1) || isinf(down2)) \
    3711             :                                         goto overflow;                  \
    3712             :                                 if (n != 0 && down1 != 0 && down2 != 0) { \
    3713             :                                         rr = (up / n) / (sqrt(down1 / n) * sqrt(down2 / n)); \
    3714             :                                         assert(!is_dbl_nil(rr));        \
    3715             :                                 } else {                                \
    3716             :                                         rr = dbl_nil;                   \
    3717             :                                         has_nils = true;                \
    3718             :                                 }                                       \
    3719             :                                 for (; ; l--) {                         \
    3720             :                                         rb[l] = rr;                     \
    3721             :                                         if (l == j)                     \
    3722             :                                                 break;                  \
    3723             :                                 }                                       \
    3724             :                                 if (j == k)                             \
    3725             :                                         break;                          \
    3726             :                                 l = j - 1;                              \
    3727             :                         }                                               \
    3728             :                 }                                                       \
    3729             :                 n = 0;                                                  \
    3730             :                 mean1 = 0;                                              \
    3731             :                 mean2 = 0;                                              \
    3732             :                 up = 0;                                                 \
    3733             :                 down1 = 0;                                              \
    3734             :                 down2 = 0;                                              \
    3735             :                 k = i;                                                  \
    3736             :         } while (0)
    3737             : 
    3738             : #define ANALYTICAL_CORRELATION_ALL_ROWS(TPE, SAMPLE, OP)        /* SAMPLE and OP not used */ \
    3739             :         do {                                                            \
    3740             :                 TPE *bp1 = (TPE*)b1i.base, *bp2 = (TPE*)b2i.base;       \
    3741             :                 for (; j < i; j++) {                                 \
    3742             :                         TPE v1 = bp1[j], v2 = bp2[j];                   \
    3743             :                         if (!is_##TPE##_nil(v1) && !is_##TPE##_nil(v2)) { \
    3744             :                                 n++;                                    \
    3745             :                                 delta1 = (dbl) v1 - mean1;              \
    3746             :                                 mean1 += delta1 / n;                    \
    3747             :                                 delta2 = (dbl) v2 - mean2;              \
    3748             :                                 mean2 += delta2 / n;                    \
    3749             :                                 aux = (dbl) v2 - mean2;                 \
    3750             :                                 up += delta1 * aux;                     \
    3751             :                                 down1 += delta1 * ((dbl) v1 - mean1);   \
    3752             :                                 down2 += delta2 * aux;                  \
    3753             :                         }                                               \
    3754             :                 }                                                       \
    3755             :                 if (isinf(up) || isinf(down1) || isinf(down2))          \
    3756             :                         goto overflow;                                  \
    3757             :                 if (n != 0 && down1 != 0 && down2 != 0) {               \
    3758             :                         rr = (up / n) / (sqrt(down1 / n) * sqrt(down2 / n)); \
    3759             :                         assert(!is_dbl_nil(rr));                        \
    3760             :                 } else {                                                \
    3761             :                         rr = dbl_nil;                                   \
    3762             :                         has_nils = true;                                \
    3763             :                 }                                                       \
    3764             :                 for (; k < i ; k++)                                  \
    3765             :                         rb[k] = rr;                                     \
    3766             :                 n = 0;                                                  \
    3767             :                 mean1 = 0;                                              \
    3768             :                 mean2 = 0;                                              \
    3769             :                 up = 0;                                                 \
    3770             :                 down1 = 0;                                              \
    3771             :                 down2 = 0;                                              \
    3772             :         } while (0)
    3773             : 
    3774             : #define ANALYTICAL_CORRELATION_CURRENT_ROW(TPE, SAMPLE, OP)     /* SAMPLE and OP not used */ \
    3775             :         do {                                                            \
    3776             :                 for (; k < i; k++)                                   \
    3777             :                         rb[k] = dbl_nil;                                \
    3778             :                 has_nils = true;                                        \
    3779             :         } while (0)
    3780             : 
    3781             : 
    3782             : typedef struct correlation_deltas {
    3783             :         BUN n;
    3784             :         dbl mean1, mean2, delta1, delta2, up, down1, down2;
    3785             : } correlation_deltas;
    3786             : 
    3787             : #define INIT_AGGREGATE_CORRELATION(TPE, SAMPLE, OP)     \
    3788             :         do {                                            \
    3789             :                 computed = (correlation_deltas) {0};    \
    3790             :         } while (0)
    3791             : #define COMPUTE_LEVEL0_CORRELATION(X, TPE, SAMPLE, OP)                  \
    3792             :         do {                                                            \
    3793             :                 TPE v1 = bp1[j + X], v2 = bp2[j + X];                   \
    3794             :                 computed = is_##TPE##_nil(v1) || is_##TPE##_nil(v2) ? (correlation_deltas) {0} \
    3795             :                                                                                                                         : (correlation_deltas) {.n = 1, .mean1 = (dbl)v1, .mean2 = (dbl)v2, .delta1 = (dbl)v1, .delta2 = (dbl)v2}; \
    3796             :         } while (0)
    3797             : #define COMPUTE_LEVELN_CORRELATION(VAL, TPE, SAMPLE, OP)                \
    3798             :         do {                                                            \
    3799             :                 if (VAL.n) {                                            \
    3800             :                         computed.n++;                                   \
    3801             :                         computed.delta1 = VAL.delta1 - computed.mean1;  \
    3802             :                         computed.mean1 += computed.delta1 / computed.n; \
    3803             :                         computed.delta2 = VAL.delta2 - computed.mean2;  \
    3804             :                         computed.mean2 += computed.delta2 / computed.n; \
    3805             :                         dbl aux = VAL.delta2 - computed.mean2;          \
    3806             :                         computed.up += computed.delta1 * aux;           \
    3807             :                         computed.down1 += computed.delta1 * (VAL.delta1 - computed.mean1); \
    3808             :                         computed.down2 += computed.delta2 * aux;        \
    3809             :                 }                                                       \
    3810             :         } while (0)
    3811             : #define FINALIZE_AGGREGATE_CORRELATION(TPE, SAMPLE, OP)                 \
    3812             :         do {                                                            \
    3813             :                 n = computed.n;                                         \
    3814             :                 up = computed.up;                                       \
    3815             :                 down1 = computed.down1;                                 \
    3816             :                 down2 = computed.down2;                                 \
    3817             :                 if (isinf(up) || isinf(down1) || isinf(down2))          \
    3818             :                         goto overflow;                                  \
    3819             :                 if (n != 0 && down1 != 0 && down2 != 0) {               \
    3820             :                         rr = (up / n) / (sqrt(down1 / n) * sqrt(down2 / n)); \
    3821             :                         assert(!is_dbl_nil(rr));                        \
    3822             :                 } else {                                                \
    3823             :                         rr = dbl_nil;                                   \
    3824             :                         has_nils = true;                                \
    3825             :                 }                                                       \
    3826             :                 rb[k] = rr;                                             \
    3827             :         } while (0)
    3828             : #define ANALYTICAL_CORRELATION_OTHERS(TPE, SAMPLE, OP)  /* SAMPLE and OP not used */ \
    3829             :         do {                                                            \
    3830             :                 TPE *bp1 = (TPE*)b1i.base, *bp2 = (TPE*)b2i.base;       \
    3831             :                 oid ncount = i - k;                                     \
    3832             :                 if ((res = GDKrebuild_segment_tree(ncount, sizeof(correlation_deltas), &segment_tree, &tree_capacity, &levels_offset, &nlevels)) != GDK_SUCCEED) \
    3833             :                         goto cleanup;                                   \
    3834             :                 populate_segment_tree(correlation_deltas, ncount, INIT_AGGREGATE_CORRELATION, COMPUTE_LEVEL0_CORRELATION, COMPUTE_LEVELN_CORRELATION, TPE, SAMPLE, OP); \
    3835             :                 for (; k < i; k++)                                   \
    3836             :                         compute_on_segment_tree(correlation_deltas, start[k] - j, end[k] - j, INIT_AGGREGATE_CORRELATION, COMPUTE_LEVELN_CORRELATION, FINALIZE_AGGREGATE_CORRELATION, TPE, SAMPLE, OP); \
    3837             :                 j = k;                                                  \
    3838             :         } while (0)
    3839             : 
    3840             : gdk_return
    3841          46 : GDKanalytical_correlation(BAT *r, BAT *p, BAT *o, BAT *b1, BAT *b2, BAT *s, BAT *e, int tpe, int frame_type)
    3842             : {
    3843             :         bool has_nils = false, last = false;
    3844          46 :         BATiter pi = bat_iterator(p);
    3845          46 :         BATiter oi = bat_iterator(o);
    3846          46 :         BATiter b1i = bat_iterator(b1);
    3847          47 :         BATiter b2i = bat_iterator(b2);
    3848          47 :         BATiter si = bat_iterator(s);
    3849          47 :         BATiter ei = bat_iterator(e);
    3850          46 :         oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(b1),
    3851          46 :                 *levels_offset = NULL, tree_capacity = 0, nlevels = 0;
    3852          46 :         const oid *restrict start = si.base, *restrict end = ei.base;
    3853             :         lng n = 0;
    3854          46 :         const bit *np = pi.base, *op = oi.base;
    3855          46 :         dbl *rb = (dbl *) Tloc(r, 0), mean1 = 0, mean2 = 0, up = 0, down1 = 0, down2 = 0, delta1, delta2, aux, rr;
    3856          46 :         void *segment_tree = NULL;
    3857             :         gdk_return res = GDK_SUCCEED;
    3858             : 
    3859          46 :         if (cnt > 0) {
    3860          46 :                 switch (frame_type) {
    3861          18 :                 case 3: /* unbounded until current row */       {
    3862         516 :                         ANALYTICAL_STATISTICS_BRANCHES(CORRELATION_UNBOUNDED_TILL_CURRENT_ROW, ;, ;);
    3863             :                 } break;
    3864           0 :                 case 4: /* current row until unbounded */       {
    3865           0 :                         ANALYTICAL_STATISTICS_BRANCHES(CORRELATION_CURRENT_ROW_TILL_UNBOUNDED, ;, ;);
    3866             :                 } break;
    3867          17 :                 case 5: /* all rows */  {
    3868         437 :                         ANALYTICAL_STATISTICS_BRANCHES(CORRELATION_ALL_ROWS, ;, ;);
    3869             :                 } break;
    3870           0 :                 case 6: /* current row */ {
    3871           0 :                         ANALYTICAL_STATISTICS_BRANCHES(CORRELATION_CURRENT_ROW, ;, ;);
    3872             :                 } break;
    3873          11 :                 default: {
    3874         973 :                         ANALYTICAL_STATISTICS_BRANCHES(CORRELATION_OTHERS, ;, ;);
    3875             :                 }
    3876             :                 }
    3877             :         }
    3878             : 
    3879          45 :         BATsetcount(r, cnt);
    3880          45 :         r->tnonil = !has_nils;
    3881          45 :         r->tnil = has_nils;
    3882          45 :         goto cleanup; /* all these gotos seem confusing but it cleans up the ending of the operator */
    3883           1 : overflow:
    3884           1 :         GDKerror("22003!overflow in calculation.\n");
    3885             :         res = GDK_FAIL;
    3886          46 : cleanup:
    3887          46 :         bat_iterator_end(&pi);
    3888          47 :         bat_iterator_end(&oi);
    3889          47 :         bat_iterator_end(&b1i);
    3890          47 :         bat_iterator_end(&b2i);
    3891          47 :         bat_iterator_end(&si);
    3892          47 :         bat_iterator_end(&ei);
    3893          47 :         GDKfree(segment_tree);
    3894          46 :         return res;
    3895           0 :   nosupport:
    3896           0 :         GDKerror("42000!correlation of type %s unsupported.\n", ATOMname(tpe));
    3897             :         res = GDK_FAIL;
    3898           0 :         goto cleanup;
    3899             : }

Generated by: LCOV version 1.14