LCOV - code coverage report
Current view: top level - gdk - gdk_analytic_func.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 368 662 55.6 %
Date: 2020-06-29 20:00:14 Functions: 20 20 100.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2020 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "monetdb_config.h"
      10             : #include "gdk.h"
      11             : #include "gdk_analytic.h"
      12             : #include "gdk_calc_private.h"
      13             : 
      14             : #define ANALYTICAL_DIFF_IMP(TPE)                                \
      15             :         do {                                                    \
      16             :                 TPE *bp = (TPE*)Tloc(b, 0);                     \
      17             :                 TPE prev = *bp, *end = bp + cnt;                \
      18             :                 if (np) {                                       \
      19             :                         for (; bp < end; bp++, rb++, np++) { \
      20             :                                 *rb = *np;                      \
      21             :                                 if (*bp != prev) {              \
      22             :                                         *rb = TRUE;             \
      23             :                                         prev = *bp;             \
      24             :                                 }                               \
      25             :                         }                                       \
      26             :                 } else {                                        \
      27             :                         for (; bp < end; bp++, rb++) {               \
      28             :                                 if (*bp == prev) {              \
      29             :                                         *rb = FALSE;            \
      30             :                                 } else {                        \
      31             :                                         *rb = TRUE;             \
      32             :                                         prev = *bp;             \
      33             :                                 }                               \
      34             :                         }                                       \
      35             :                 }                                               \
      36             :         } while (0)
      37             : 
      38             : /* We use NaN for floating point null values, which always output false on equality tests */
      39             : #define ANALYTICAL_DIFF_FLOAT_IMP(TPE)                                  \
      40             :         do {                                                            \
      41             :                 TPE *bp = (TPE*)Tloc(b, 0);                             \
      42             :                 TPE prev = *bp, *end = bp + cnt;                        \
      43             :                 if (np) {                                               \
      44             :                         for (; bp < end; bp++, rb++, np++) {         \
      45             :                                 *rb = *np;                              \
      46             :                                 if (*bp != prev && (!is_##TPE##_nil(*bp) || !is_##TPE##_nil(prev))) { \
      47             :                                         *rb = TRUE;                     \
      48             :                                         prev = *bp;                     \
      49             :                                 }                                       \
      50             :                         }                                               \
      51             :                 } else {                                                \
      52             :                         for (; bp < end; bp++, rb++) {                       \
      53             :                                 if (*bp == prev || (is_##TPE##_nil(*bp) && is_##TPE##_nil(prev))) { \
      54             :                                         *rb = FALSE;                    \
      55             :                                 } else {                                \
      56             :                                         *rb = TRUE;                     \
      57             :                                         prev = *bp;                     \
      58             :                                 }                                       \
      59             :                         }                                               \
      60             :                 }                                                       \
      61             :         } while (0)
      62             : 
      63             : gdk_return
      64         758 : GDKanalyticaldiff(BAT *r, BAT *b, BAT *p, int tpe)
      65             : {
      66         758 :         BUN i, cnt = BATcount(b);
      67         758 :         bit *restrict rb = (bit *) Tloc(r, 0), *restrict np = p ? (bit *) Tloc(p, 0) : NULL;
      68             : 
      69         758 :         switch (tpe) {
      70           8 :         case TYPE_bit:
      71          12 :                 ANALYTICAL_DIFF_IMP(bit);
      72             :                 break;
      73           6 :         case TYPE_bte:
      74         277 :                 ANALYTICAL_DIFF_IMP(bte);
      75             :                 break;
      76           0 :         case TYPE_sht:
      77           0 :                 ANALYTICAL_DIFF_IMP(sht);
      78             :                 break;
      79         514 :         case TYPE_int:
      80     2258930 :                 ANALYTICAL_DIFF_IMP(int);
      81             :                 break;
      82          14 :         case TYPE_lng:
      83         490 :                 ANALYTICAL_DIFF_IMP(lng);
      84             :                 break;
      85             : #ifdef HAVE_HGE
      86          43 :         case TYPE_hge:
      87      505684 :                 ANALYTICAL_DIFF_IMP(hge);
      88             :                 break;
      89             : #endif
      90           0 :         case TYPE_flt: {
      91           0 :                 if (b->tnonil) {
      92           0 :                         ANALYTICAL_DIFF_IMP(flt);
      93             :                 } else { /* Because of NaN values, use this path */
      94           0 :                         ANALYTICAL_DIFF_FLOAT_IMP(flt);
      95             :                 }
      96             :         } break;
      97          23 :         case TYPE_dbl: {
      98          23 :                 if (b->tnonil) {
      99       16573 :                         ANALYTICAL_DIFF_IMP(dbl);
     100             :                 } else { /* Because of NaN values, use this path */
     101         408 :                         ANALYTICAL_DIFF_FLOAT_IMP(dbl);
     102             :                 }
     103             :         } break;
     104         150 :         default:{
     105         150 :                 BATiter it = bat_iterator(b);
     106         290 :                 ptr v = BUNtail(it, 0), next;
     107         150 :                 int (*atomcmp) (const void *, const void *) = ATOMcompare(tpe);
     108         150 :                 if (np) {
     109      532388 :                         for (i = 0; i < cnt; i++, rb++, np++) {
     110      532356 :                                 *rb = *np;
     111      532356 :                                 next = BUNtail(it, i);
     112      532356 :                                 if (atomcmp(v, next) != 0) {
     113       20439 :                                         *rb = TRUE;
     114       20439 :                                         v = next;
     115             :                                 }
     116             :                         }
     117             :                 } else {
     118      711192 :                         for (i = 0; i < cnt; i++, rb++) {
     119      711074 :                                 next = BUNtail(it, i);
     120      711074 :                                 if (atomcmp(v, next) != 0) {
     121         635 :                                         *rb = TRUE;
     122         635 :                                         v = next;
     123             :                                 } else {
     124      710439 :                                         *rb = FALSE;
     125             :                                 }
     126             :                         }
     127             :                 }
     128             :         }
     129             :         }
     130         758 :         BATsetcount(r, cnt);
     131         758 :         r->tnonil = true;
     132         758 :         r->tnil = false;
     133         758 :         return GDK_SUCCEED;
     134             : }
     135             : 
     136             : #define NTILE_CALC(TPE, NEXT_VALUE, LNG_HGE, UPCAST)    \
     137             :         do {                                    \
     138             :                 for (TPE i = 0; rb < rp; i++, rb++) {        \
     139             :                         TPE val = NEXT_VALUE; \
     140             :                         if (is_##TPE##_nil(val)) {      \
     141             :                                 has_nils = true;        \
     142             :                                 *rb = TPE##_nil;        \
     143             :                         } else { \
     144             :                                 UPCAST nval = (UPCAST) LNG_HGE; \
     145             :                                 if (nval >= ncnt) { \
     146             :                                         *rb = i + 1;  \
     147             :                                 } else { \
     148             :                                         UPCAST bsize = ncnt / nval; \
     149             :                                         UPCAST top = ncnt - nval * bsize; \
     150             :                                         UPCAST small = top * (bsize + 1); \
     151             :                                         if ((UPCAST) i < small) \
     152             :                                                 *rb = (TPE)(1 + i / (bsize + 1)); \
     153             :                                         else \
     154             :                                                 *rb = (TPE)(1 + top + (i - small) / bsize); \
     155             :                                 } \
     156             :                         } \
     157             :                 } \
     158             :         } while (0)
     159             : 
     160             : #define ANALYTICAL_NTILE_IMP(TPE, NEXT_VALUE, LNG_HGE, UPCAST)  \
     161             :         do {                                                    \
     162             :                 TPE *rp, *rb;   \
     163             :                 UPCAST ncnt; \
     164             :                 rb = rp = (TPE*)Tloc(r, 0);             \
     165             :                 if (p) {                                        \
     166             :                         pnp = np = (bit*)Tloc(p, 0);    \
     167             :                         end = np + cnt;                         \
     168             :                         for (; np < end; np++) {     \
     169             :                                 if (*np) {                      \
     170             :                                         ncnt = np - pnp;        \
     171             :                                         rp += ncnt;             \
     172             :                                         NTILE_CALC(TPE, NEXT_VALUE, LNG_HGE, UPCAST);\
     173             :                                         pnp = np;       \
     174             :                                 }                               \
     175             :                         }                                       \
     176             :                         ncnt = np - pnp;                        \
     177             :                         rp += ncnt;                             \
     178             :                         NTILE_CALC(TPE, NEXT_VALUE, LNG_HGE, UPCAST);   \
     179             :                 } else {                                        \
     180             :                         ncnt = (UPCAST) cnt; \
     181             :                         rp += cnt;                              \
     182             :                         NTILE_CALC(TPE, NEXT_VALUE, LNG_HGE, UPCAST);   \
     183             :                 }                                               \
     184             :         } while (0)
     185             : 
     186             : #define ANALYTICAL_NTILE_SINGLE_IMP(TPE, LNG_HGE, UPCAST) \
     187             :         do {    \
     188             :                 TPE ntl = *(TPE*) ntile; \
     189             :                 ANALYTICAL_NTILE_IMP(TPE, ntl, LNG_HGE, UPCAST); \
     190             :         } while (0)
     191             : 
     192             : #define ANALYTICAL_NTILE_MULTI_IMP(TPE, LNG_HGE, UPCAST) \
     193             :         do {    \
     194             :                 BUN k = 0; \
     195             :                 TPE *restrict nn = (TPE*)Tloc(n, 0);    \
     196             :                 ANALYTICAL_NTILE_IMP(TPE, nn[k++], LNG_HGE, UPCAST); \
     197             :         } while (0)
     198             : 
     199             : gdk_return
     200          59 : GDKanalyticalntile(BAT *r, BAT *b, BAT *p, BAT *n, int tpe, const void *restrict ntile)
     201             : {
     202          59 :         BUN cnt = BATcount(b);
     203          59 :         bit *np, *pnp, *end;
     204          59 :         bool has_nils = false;
     205             : 
     206          59 :         assert((n && !ntile) || (!n && ntile));
     207             : 
     208          59 :         if (ntile) {
     209          32 :                 switch (tpe) {
     210          32 :                 case TYPE_bte:
     211         480 :                         ANALYTICAL_NTILE_SINGLE_IMP(bte, val, BUN);
     212             :                         break;
     213           0 :                 case TYPE_sht:
     214           0 :                         ANALYTICAL_NTILE_SINGLE_IMP(sht, val, BUN);
     215             :                         break;
     216           0 :                 case TYPE_int:
     217           0 :                         ANALYTICAL_NTILE_SINGLE_IMP(int, val, BUN);
     218             :                         break;
     219           0 :                 case TYPE_lng:
     220             : #if SIZEOF_OID == SIZEOF_INT
     221             :                         ANALYTICAL_NTILE_SINGLE_IMP(lng, val, lng);
     222             : #else
     223           0 :                         ANALYTICAL_NTILE_SINGLE_IMP(lng, val, BUN);
     224             : #endif
     225             :                         break;
     226             : #ifdef HAVE_HGE
     227           0 :                 case TYPE_hge:
     228             : #if SIZEOF_OID == SIZEOF_INT
     229             :                         ANALYTICAL_NTILE_SINGLE_IMP(hge, (val > (hge) GDK_int_max) ? GDK_int_max : (lng) val, lng);
     230             : #else
     231           0 :                         ANALYTICAL_NTILE_SINGLE_IMP(hge, (val > (hge) GDK_lng_max) ? GDK_lng_max : (lng) val, BUN);
     232             : #endif
     233             : #endif
     234             :                 default:
     235           0 :                         goto nosupport;
     236             :                 }
     237             :         } else {
     238          27 :                 switch (tpe) {
     239           1 :                 case TYPE_bte:
     240          11 :                         ANALYTICAL_NTILE_MULTI_IMP(bte, val, BUN);
     241             :                         break;
     242           0 :                 case TYPE_sht:
     243           0 :                         ANALYTICAL_NTILE_MULTI_IMP(sht, val, BUN);
     244             :                         break;
     245          26 :                 case TYPE_int:
     246         394 :                         ANALYTICAL_NTILE_MULTI_IMP(int, val, BUN);
     247             :                         break;
     248           0 :                 case TYPE_lng:
     249             : #if SIZEOF_OID == SIZEOF_INT
     250             :                         ANALYTICAL_NTILE_MULTI_IMP(lng, val, lng);
     251             : #else
     252           0 :                         ANALYTICAL_NTILE_MULTI_IMP(lng, val, BUN);
     253             : #endif
     254             :                         break;
     255             : #ifdef HAVE_HGE
     256           0 :                 case TYPE_hge:
     257             : #if SIZEOF_OID == SIZEOF_INT
     258             :                         ANALYTICAL_NTILE_MULTI_IMP(hge, (val > (hge) GDK_int_max) ? GDK_int_max : (lng) val, lng);
     259             : #else
     260           0 :                         ANALYTICAL_NTILE_MULTI_IMP(hge, (val > (hge) GDK_lng_max) ? GDK_lng_max : (lng) val, BUN);
     261             : #endif
     262             :                 break;
     263             : #endif
     264           0 :                 default:
     265           0 :                         goto nosupport;
     266             :                 }
     267             :         }
     268          59 :         BATsetcount(r, cnt);
     269          59 :         r->tnonil = !has_nils;
     270          59 :         r->tnil = has_nils;
     271          59 :         return GDK_SUCCEED;
     272           0 : nosupport:
     273           0 :         GDKerror("type %s not supported for the ntile type.\n", ATOMname(tpe));
     274           0 :         return GDK_FAIL;
     275             : }
     276             : 
     277             : #define ANALYTICAL_FIRST_IMP(TPE)                               \
     278             :         do {                                                    \
     279             :                 TPE *bp, *bs, *be, curval, *restrict rb;        \
     280             :                 bp = (TPE*)Tloc(b, 0);                          \
     281             :                 rb = (TPE*)Tloc(r, 0);                          \
     282             :                 for (; i < cnt; i++, rb++) {                 \
     283             :                         bs = bp + start[i];                     \
     284             :                         be = bp + end[i];                       \
     285             :                         curval = (be > bs) ? *bs : TPE##_nil;        \
     286             :                         *rb = curval;                           \
     287             :                         has_nils |= is_##TPE##_nil(curval);             \
     288             :                 }                                               \
     289             :         } while (0)
     290             : 
     291             : gdk_return
     292          32 : GDKanalyticalfirst(BAT *r, BAT *b, BAT *s, BAT *e, int tpe)
     293             : {
     294          32 :         BUN i = 0, cnt = BATcount(b);
     295          32 :         lng *restrict start, *restrict end;
     296          32 :         bool has_nils = false;
     297             : 
     298          32 :         assert(s && e);
     299          32 :         start = (lng *) Tloc(s, 0);
     300          32 :         end = (lng *) Tloc(e, 0);
     301             : 
     302          32 :         switch (tpe) {
     303           0 :         case TYPE_bit:
     304           0 :                 ANALYTICAL_FIRST_IMP(bit);
     305             :                 break;
     306           1 :         case TYPE_bte:
     307          11 :                 ANALYTICAL_FIRST_IMP(bte);
     308             :                 break;
     309           0 :         case TYPE_sht:
     310           0 :                 ANALYTICAL_FIRST_IMP(sht);
     311             :                 break;
     312          23 :         case TYPE_int:
     313         244 :                 ANALYTICAL_FIRST_IMP(int);
     314             :                 break;
     315           1 :         case TYPE_lng:
     316          12 :                 ANALYTICAL_FIRST_IMP(lng);
     317             :                 break;
     318             : #ifdef HAVE_HGE
     319           0 :         case TYPE_hge:
     320           0 :                 ANALYTICAL_FIRST_IMP(hge);
     321             :                 break;
     322             : #endif
     323           0 :         case TYPE_flt:
     324           0 :                 ANALYTICAL_FIRST_IMP(flt);
     325             :                 break;
     326           2 :         case TYPE_dbl:
     327          14 :                 ANALYTICAL_FIRST_IMP(dbl);
     328             :                 break;
     329           5 :         default:{
     330           5 :                 const void *restrict nil = ATOMnilptr(tpe);
     331           5 :                 int (*atomcmp) (const void *, const void *) = ATOMcompare(tpe);
     332           5 :                 BATiter bpi = bat_iterator(b);
     333           5 :                 void *curval;
     334             : 
     335          50 :                 for (; i < cnt; i++) {
     336          45 :                         curval = (end[i] > start[i]) ? BUNtail(bpi, (BUN) start[i]) : (void *) nil;
     337          45 :                         if (BUNappend(r, curval, false) != GDK_SUCCEED)
     338           0 :                                 return GDK_FAIL;
     339          45 :                         has_nils |= atomcmp(curval, nil) == 0;
     340             :                 }
     341             :         }
     342             :         }
     343          32 :         BATsetcount(r, cnt);
     344          32 :         r->tnonil = !has_nils;
     345          32 :         r->tnil = has_nils;
     346          32 :         return GDK_SUCCEED;
     347             : }
     348             : 
     349             : #define ANALYTICAL_LAST_IMP(TPE)                                        \
     350             :         do {                                                            \
     351             :                 TPE *bp, *bs, *be, curval, *restrict rb;                \
     352             :                 bp = (TPE*)Tloc(b, 0);                                  \
     353             :                 rb = (TPE*)Tloc(r, 0);                                  \
     354             :                 for (; i<cnt; i++, rb++) {                           \
     355             :                         bs = bp + start[i];                             \
     356             :                         be = bp + end[i];                               \
     357             :                         curval = (be > bs) ? *(be - 1) : TPE##_nil;  \
     358             :                         *rb = curval;                                   \
     359             :                         has_nils |= is_##TPE##_nil(curval);                     \
     360             :                 }                                                       \
     361             :         } while (0)
     362             : 
     363             : gdk_return
     364          31 : GDKanalyticallast(BAT *r, BAT *b, BAT *s, BAT *e, int tpe)
     365             : {
     366          31 :         BUN i = 0, cnt = BATcount(b);
     367          31 :         lng *restrict start, *restrict end;
     368          31 :         bool has_nils = false;
     369             : 
     370          31 :         assert(s && e);
     371          31 :         start = (lng *) Tloc(s, 0);
     372          31 :         end = (lng *) Tloc(e, 0);
     373             : 
     374          31 :         switch (tpe) {
     375           0 :         case TYPE_bit:
     376           0 :                 ANALYTICAL_LAST_IMP(bit);
     377             :                 break;
     378           1 :         case TYPE_bte:
     379          11 :                 ANALYTICAL_LAST_IMP(bte);
     380             :                 break;
     381           0 :         case TYPE_sht:
     382           0 :                 ANALYTICAL_LAST_IMP(sht);
     383             :                 break;
     384          22 :         case TYPE_int:
     385         339 :                 ANALYTICAL_LAST_IMP(int);
     386             :                 break;
     387           1 :         case TYPE_lng:
     388          12 :                 ANALYTICAL_LAST_IMP(lng);
     389             :                 break;
     390             : #ifdef HAVE_HGE
     391           0 :         case TYPE_hge:
     392           0 :                 ANALYTICAL_LAST_IMP(hge);
     393             :                 break;
     394             : #endif
     395           0 :         case TYPE_flt:
     396           0 :                 ANALYTICAL_LAST_IMP(flt);
     397             :                 break;
     398           2 :         case TYPE_dbl:
     399          14 :                 ANALYTICAL_LAST_IMP(dbl);
     400             :                 break;
     401           5 :         default:{
     402           5 :                 const void *restrict nil = ATOMnilptr(tpe);
     403           5 :                 int (*atomcmp) (const void *, const void *) = ATOMcompare(tpe);
     404           5 :                 BATiter bpi = bat_iterator(b);
     405           5 :                 void *curval;
     406             : 
     407          50 :                 for (; i < cnt; i++) {
     408          45 :                         curval = (end[i] > start[i]) ? BUNtail(bpi, (BUN) (end[i] - 1)) : (void *) nil;
     409          45 :                         if (BUNappend(r, curval, false) != GDK_SUCCEED)
     410           0 :                                 return GDK_FAIL;
     411          45 :                         has_nils |= atomcmp(curval, nil) == 0;
     412             :                 }
     413             :         }
     414             :         }
     415          31 :         BATsetcount(r, cnt);
     416          31 :         r->tnonil = !has_nils;
     417          31 :         r->tnil = has_nils;
     418          31 :         return GDK_SUCCEED;
     419             : }
     420             : 
     421             : #define ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(TPE1)                      \
     422             :         do {                                                            \
     423             :                 TPE1 *bp = (TPE1*)Tloc(b, 0), *bs, *be, curval, *restrict rb = (TPE1*)Tloc(r, 0); \
     424             :                 if (is_lng_nil(nth)) {                                  \
     425             :                         has_nils = true;                                \
     426             :                         for (; i < cnt; i++, rb++)                   \
     427             :                                 *rb = TPE1##_nil;                       \
     428             :                 } else {                                                \
     429             :                         nth--;                                          \
     430             :                         for (; i < cnt; i++, rb++) {                 \
     431             :                                 bs = bp + start[i];                     \
     432             :                                 be = bp + end[i];                       \
     433             :                                 curval = (be > bs && nth < (end[i] - start[i])) ? *(bs + nth) : TPE1##_nil; \
     434             :                                 *rb = curval;                           \
     435             :                                 has_nils |= is_##TPE1##_nil(curval);    \
     436             :                         }                                               \
     437             :                 }                                                       \
     438             :         } while (0)
     439             : 
     440             : #define ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE1, TPE2, TPE3)           \
     441             :         do {                                                            \
     442             :                 TPE2 *restrict lp = (TPE2*)Tloc(l, 0);                  \
     443             :                 for (; i < cnt; i++, rb++) {                         \
     444             :                         TPE2 lnth = lp[i];                              \
     445             :                         bs = bp + start[i];                             \
     446             :                         be = bp + end[i];                               \
     447             :                         if (is_##TPE2##_nil(lnth) || be <= bs || (TPE3)(lnth - 1) > (TPE3)(end[i] - start[i])) { \
     448             :                                 curval = TPE1##_nil;    \
     449             :                                 has_nils = true;        \
     450             :                         } else {                                                \
     451             :                                 curval = *(bs + lnth - 1);              \
     452             :                                 has_nils |= is_##TPE1##_nil(curval);    \
     453             :                         }       \
     454             :                         *rb = curval;   \
     455             :                 }                                                       \
     456             :         } while (0)
     457             : 
     458             : #ifdef HAVE_HGE
     459             : #define ANALYTICAL_NTHVALUE_CALC_FIXED_HGE(TPE1)                        \
     460             :         case TYPE_hge:                                                  \
     461             :                 ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE1, hge, hge);    \
     462             :                 break;
     463             : #else
     464             : #define ANALYTICAL_NTHVALUE_CALC_FIXED_HGE(TPE1)
     465             : #endif
     466             : 
     467             : #define ANALYTICAL_NTHVALUE_CALC_FIXED(TPE1)                            \
     468             :         do {                                                            \
     469             :                 TPE1 *bp = (TPE1*)Tloc(b, 0), *bs, *be, curval, *restrict rb = (TPE1*)Tloc(r, 0);       \
     470             :                 switch (tp2) {                                          \
     471             :                 case TYPE_bte:                                          \
     472             :                         ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE1, bte, lng); \
     473             :                         break;                                          \
     474             :                 case TYPE_sht:                                          \
     475             :                         ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE1, sht, lng); \
     476             :                         break;                                          \
     477             :                 case TYPE_int:                                          \
     478             :                         ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE1, int, lng); \
     479             :                         break;                                          \
     480             :                 case TYPE_lng:                                          \
     481             :                         ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE1, lng, lng); \
     482             :                         break;                                          \
     483             :                 ANALYTICAL_NTHVALUE_CALC_FIXED_HGE(TPE1)                \
     484             :                 default:                                                \
     485             :                         goto nosupport;                                 \
     486             :                 }                                                       \
     487             :         } while (0)
     488             : 
     489             : #define ANALYTICAL_NTHVALUE_IMP_MULTI_VARSIZED(TPE1, TPE2)              \
     490             :         do {                                                            \
     491             :                 TPE1 *restrict lp = (TPE1*)Tloc(l, 0);                  \
     492             :                 for (; i < cnt; i++) {                                       \
     493             :                         TPE1 lnth = lp[i];                              \
     494             :                         if (is_##TPE1##_nil(lnth) || end[i] <= start[i] || (TPE2)(lnth - 1) > (TPE2)(end[i] - start[i])) {        \
     495             :                                 curval = (void *) nil;                  \
     496             :                                 has_nils = true; \
     497             :                         } else {        \
     498             :                                 curval = BUNtail(bpi, (BUN) (start[i] + lnth - 1)); \
     499             :                                 has_nils |= atomcmp(curval, nil) == 0;  \
     500             :                         }       \
     501             :                         if (BUNappend(r, curval, false) != GDK_SUCCEED) \
     502             :                                 return GDK_FAIL;                        \
     503             :                 }                                                       \
     504             :         } while (0)
     505             : 
     506             : gdk_return
     507          41 : GDKanalyticalnthvalue(BAT *r, BAT *b, BAT *s, BAT *e, BAT *l, const void *restrict bound, int tp1, int tp2)
     508             : {
     509          41 :         BUN i = 0, cnt = BATcount(b);
     510          41 :         lng *restrict start, *restrict end, nth = 0;
     511          41 :         bool has_nils = false;
     512          41 :         const void *restrict nil = ATOMnilptr(tp1);
     513          41 :         int (*atomcmp) (const void *, const void *) = ATOMcompare(tp1);
     514          41 :         void *curval;
     515             : 
     516          41 :         assert(s && e && ((l && !bound) || (!l && bound)));
     517          41 :         start = (lng *) Tloc(s, 0);
     518          41 :         end = (lng *) Tloc(e, 0);
     519             : 
     520          41 :         if (bound) {
     521          36 :                 switch (tp2) {
     522          35 :                 case TYPE_bte:{
     523          35 :                         bte val = *(bte *) bound;
     524          35 :                         nth = !is_bte_nil(val) ? (lng) val : lng_nil;
     525             :                 } break;
     526           1 :                 case TYPE_sht:{
     527           1 :                         sht val = *(sht *) bound;
     528           1 :                         nth = !is_sht_nil(val) ? (lng) val : lng_nil;
     529             :                 } break;
     530           0 :                 case TYPE_int:{
     531           0 :                         int val = *(int *) bound;
     532           0 :                         nth = !is_int_nil(val) ? (lng) val : lng_nil;
     533             :                 } break;
     534           0 :                 case TYPE_lng:{
     535           0 :                         nth = *(lng *) bound;
     536           0 :                 } break;
     537             : #ifdef HAVE_HGE
     538           0 :                 case TYPE_hge:{
     539           0 :                         hge nval = *(hge *) bound;
     540           0 :                         nth = is_hge_nil(nval) ? lng_nil : (nval > (hge) GDK_lng_max) ? GDK_lng_max : (lng) nval;
     541             :                 } break;
     542             : #endif
     543           0 :                 default:
     544           0 :                         goto nosupport;
     545             :                 }
     546          36 :                 switch (tp1) {
     547           0 :                 case TYPE_bit:
     548           0 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(bit);
     549             :                         break;
     550           2 :                 case TYPE_bte:
     551          13 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(bte);
     552             :                         break;
     553           0 :                 case TYPE_sht:
     554           0 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(sht);
     555             :                         break;
     556          23 :                 case TYPE_int:
     557         243 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(int);
     558             :                         break;
     559           0 :                 case TYPE_lng:
     560           0 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(lng);
     561             :                         break;
     562             : #ifdef HAVE_HGE
     563           0 :                 case TYPE_hge:
     564           0 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(hge);
     565             :                         break;
     566             : #endif
     567           0 :                 case TYPE_flt:
     568           0 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(flt);
     569             :                         break;
     570           0 :                 case TYPE_dbl:
     571           0 :                         ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(dbl);
     572             :                         break;
     573          11 :                 default:{
     574          11 :                         BATiter bpi = bat_iterator(b);
     575          11 :                         if (is_lng_nil(nth)) {
     576           0 :                                 has_nils = true;
     577           0 :                                 for (; i < cnt; i++)
     578           0 :                                         if (BUNappend(r, nil, false) != GDK_SUCCEED)
     579           0 :                                                 return GDK_FAIL;
     580             :                         } else {
     581          11 :                                 nth--;
     582         112 :                                 for (; i < cnt; i++) {
     583         101 :                                         curval = (end[i] > start[i] && nth < (end[i] - start[i])) ? BUNtail(bpi, (BUN) (start[i] + nth)) : (void *) nil;
     584         101 :                                         if (BUNappend(r, curval, false) != GDK_SUCCEED)
     585             :                                                 return GDK_FAIL;
     586         101 :                                         has_nils |= atomcmp(curval, nil) == 0;
     587             :                                 }
     588             :                         }
     589             :                 }
     590             :                 }
     591             :         } else {
     592           5 :                 switch (tp1) {
     593           0 :                 case TYPE_bit:
     594           0 :                         ANALYTICAL_NTHVALUE_CALC_FIXED(bit);
     595             :                         break;
     596           3 :                 case TYPE_bte:
     597          33 :                         ANALYTICAL_NTHVALUE_CALC_FIXED(bte);
     598             :                         break;
     599           0 :                 case TYPE_sht:
     600           0 :                         ANALYTICAL_NTHVALUE_CALC_FIXED(sht);
     601             :                         break;
     602           2 :                 case TYPE_int:
     603          22 :                         ANALYTICAL_NTHVALUE_CALC_FIXED(int);
     604             :                         break;
     605           0 :                 case TYPE_lng:
     606           0 :                         ANALYTICAL_NTHVALUE_CALC_FIXED(lng);
     607             :                         break;
     608             : #ifdef HAVE_HGE
     609           0 :                 case TYPE_hge:
     610           0 :                         ANALYTICAL_NTHVALUE_CALC_FIXED(hge);
     611             :                         break;
     612             : #endif
     613           0 :                 case TYPE_flt:
     614           0 :                         ANALYTICAL_NTHVALUE_CALC_FIXED(flt);
     615             :                         break;
     616           0 :                 case TYPE_dbl:
     617           0 :                         ANALYTICAL_NTHVALUE_CALC_FIXED(dbl);
     618             :                         break;
     619           0 :                 default:{
     620           0 :                         BATiter bpi = bat_iterator(b);
     621           0 :                         switch (tp2) {
     622           0 :                         case TYPE_bte:
     623           0 :                                 ANALYTICAL_NTHVALUE_IMP_MULTI_VARSIZED(bte, lng);
     624             :                                 break;
     625           0 :                         case TYPE_sht:
     626           0 :                                 ANALYTICAL_NTHVALUE_IMP_MULTI_VARSIZED(sht, lng);
     627             :                                 break;
     628           0 :                         case TYPE_int:
     629           0 :                                 ANALYTICAL_NTHVALUE_IMP_MULTI_VARSIZED(int, lng);
     630             :                                 break;
     631           0 :                         case TYPE_lng:
     632           0 :                                 ANALYTICAL_NTHVALUE_IMP_MULTI_VARSIZED(lng, lng);
     633             :                                 break;
     634             : #ifdef HAVE_HGE
     635           0 :                         case TYPE_hge:
     636           0 :                                 ANALYTICAL_NTHVALUE_IMP_MULTI_VARSIZED(hge, hge);
     637             :                                 break;
     638             : #endif
     639           0 :                         default:
     640           0 :                                 goto nosupport;
     641             :                         }
     642             :                 }
     643             :                 }
     644             :         }
     645          41 :         BATsetcount(r, cnt);
     646          41 :         r->tnonil = !has_nils;
     647          41 :         r->tnil = has_nils;
     648          41 :         return GDK_SUCCEED;
     649           0 :       nosupport:
     650           0 :         GDKerror("type %s not supported for the nth_value.\n", ATOMname(tp2));
     651           0 :         return GDK_FAIL;
     652             : }
     653             : 
     654             : #define ANALYTICAL_LAG_CALC(TPE)                                \
     655             :         do {                                                    \
     656             :                 for (i = 0; i < lag && rb < rp; i++, rb++)        \
     657             :                         *rb = def;                              \
     658             :                 has_nils |= (lag > 0 && is_##TPE##_nil(def));        \
     659             :                 for (; rb < rp; rb++, bp++) {                        \
     660             :                         next = *bp;                             \
     661             :                         *rb = next;                             \
     662             :                         has_nils |= is_##TPE##_nil(next);               \
     663             :                 }                                               \
     664             :         } while (0)
     665             : 
     666             : #define ANALYTICAL_LAG_IMP(TPE)                                         \
     667             :         do {                                                            \
     668             :                 TPE *rp, *rb, *bp, *nbp, *rend,                         \
     669             :                         def = *((TPE *) default_value), next;           \
     670             :                 bp = (TPE*)Tloc(b, 0);                                  \
     671             :                 rb = rp = (TPE*)Tloc(r, 0);                             \
     672             :                 rend = rb + cnt;                                        \
     673             :                 if (lag == BUN_NONE) {                                  \
     674             :                         has_nils = true;                                \
     675             :                         for (; rb < rend; rb++)                              \
     676             :                                 *rb = TPE##_nil;                        \
     677             :                 } else if (p) {                                         \
     678             :                         pnp = np = (bit*)Tloc(p, 0);                    \
     679             :                         end = np + cnt;                                 \
     680             :                         for (; np < end; np++) {                     \
     681             :                                 if (*np) {                              \
     682             :                                         ncnt = (np - pnp);              \
     683             :                                         rp += ncnt;                     \
     684             :                                         nbp = bp + ncnt;                \
     685             :                                         ANALYTICAL_LAG_CALC(TPE);       \
     686             :                                         bp = nbp;                       \
     687             :                                         pnp = np;                       \
     688             :                                 }                                       \
     689             :                         }                                               \
     690             :                         rp += (np - pnp);                               \
     691             :                         ANALYTICAL_LAG_CALC(TPE);                       \
     692             :                 } else {                                                \
     693             :                         rp += cnt;                                      \
     694             :                         ANALYTICAL_LAG_CALC(TPE);                       \
     695             :                 }                                                       \
     696             :         } while (0)
     697             : 
     698             : #define ANALYTICAL_LAG_OTHERS                                           \
     699             :         do {                                                            \
     700             :                 for (i = 0; i < lag && k < j; i++, k++) {         \
     701             :                         if (BUNappend(r, default_value, false) != GDK_SUCCEED) \
     702             :                                 return GDK_FAIL;                        \
     703             :                 }                                                       \
     704             :                 has_nils |= (lag > 0 && atomcmp(default_value, nil) == 0);   \
     705             :                 for (l = k - lag; k < j; k++, l++) {                 \
     706             :                         curval = BUNtail(bpi, l);                       \
     707             :                         if (BUNappend(r, curval, false) != GDK_SUCCEED) \
     708             :                                 return GDK_FAIL;                        \
     709             :                         has_nils |= atomcmp(curval, nil) == 0;                  \
     710             :                 }       \
     711             :         } while (0)
     712             : 
     713             : gdk_return
     714          30 : GDKanalyticallag(BAT *r, BAT *b, BAT *p, BUN lag, const void *restrict default_value, int tpe)
     715             : {
     716          30 :         int (*atomcmp) (const void *, const void *);
     717          30 :         const void *restrict nil;
     718          30 :         BUN i = 0, j = 0, k = 0, l = 0, ncnt, cnt = BATcount(b);
     719          30 :         bit *np, *pnp, *end;
     720          30 :         bool has_nils = false;
     721             : 
     722          30 :         assert(default_value);
     723             : 
     724          30 :         switch (tpe) {
     725           0 :         case TYPE_bit:
     726           0 :                 ANALYTICAL_LAG_IMP(bit);
     727             :                 break;
     728           3 :         case TYPE_bte:
     729          33 :                 ANALYTICAL_LAG_IMP(bte);
     730             :                 break;
     731           0 :         case TYPE_sht:
     732           0 :                 ANALYTICAL_LAG_IMP(sht);
     733             :                 break;
     734          21 :         case TYPE_int:
     735         337 :                 ANALYTICAL_LAG_IMP(int);
     736             :                 break;
     737           1 :         case TYPE_lng:
     738          23 :                 ANALYTICAL_LAG_IMP(lng);
     739             :                 break;
     740             : #ifdef HAVE_HGE
     741           0 :         case TYPE_hge:
     742           0 :                 ANALYTICAL_LAG_IMP(hge);
     743             :                 break;
     744             : #endif
     745           0 :         case TYPE_flt:
     746           0 :                 ANALYTICAL_LAG_IMP(flt);
     747             :                 break;
     748           0 :         case TYPE_dbl:
     749           0 :                 ANALYTICAL_LAG_IMP(dbl);
     750             :                 break;
     751           5 :         default:{
     752           5 :                 BATiter bpi = bat_iterator(b);
     753           5 :                 const void *restrict curval;
     754           5 :                 nil = ATOMnilptr(tpe);
     755           5 :                 atomcmp = ATOMcompare(tpe);
     756           5 :                 if (lag == BUN_NONE) {
     757           0 :                         has_nils = true;
     758           0 :                         for (j = 0; j < cnt; j++) {
     759           0 :                                 if (BUNappend(r, nil, false) != GDK_SUCCEED)
     760           0 :                                         return GDK_FAIL;
     761             :                         }
     762           5 :                 } else if (p) {
     763           3 :                         pnp = np = (bit *) Tloc(p, 0);
     764           3 :                         end = np + cnt;
     765          30 :                         for (; np < end; np++) {
     766          27 :                                 if (*np) {
     767           9 :                                         j += (np - pnp);
     768          31 :                                         ANALYTICAL_LAG_OTHERS;
     769             :                                         pnp = np;
     770             :                                 }
     771             :                         }
     772           3 :                         j += (np - pnp);
     773           8 :                         ANALYTICAL_LAG_OTHERS;
     774             :                 } else {
     775           4 :                         j += cnt;
     776          23 :                         ANALYTICAL_LAG_OTHERS;
     777             :                 }
     778             :         }
     779             :         }
     780          30 :         BATsetcount(r, cnt);
     781          30 :         r->tnonil = !has_nils;
     782          30 :         r->tnil = has_nils;
     783          30 :         return GDK_SUCCEED;
     784             : }
     785             : 
     786             : #define LEAD_CALC(TPE)                                          \
     787             :         do {                                                    \
     788             :                 if (lead < ncnt) {                           \
     789             :                         bp += lead;                             \
     790             :                         l = ncnt - lead;                        \
     791             :                         for (i = 0; i < l; i++, rb++, bp++) {        \
     792             :                                 next = *bp;                     \
     793             :                                 *rb = next;                     \
     794             :                                 has_nils |= is_##TPE##_nil(next);       \
     795             :                         }                                       \
     796             :                 } else {                                        \
     797             :                         bp += ncnt;                             \
     798             :                 }                                               \
     799             :                 for (;rb < rp; rb++)                         \
     800             :                         *rb = def;                              \
     801             :                 has_nils |= (lead > 0 && is_##TPE##_nil(def));       \
     802             :         } while (0)
     803             : 
     804             : #define ANALYTICAL_LEAD_IMP(TPE)                                \
     805             :         do {                                                    \
     806             :                 TPE *rp, *rb, *bp, *rend,                       \
     807             :                         def = *((TPE *) default_value), next;   \
     808             :                 bp = (TPE*)Tloc(b, 0);                          \
     809             :                 rb = rp = (TPE*)Tloc(r, 0);                     \
     810             :                 rend = rb + cnt;                                \
     811             :                 if (lead == BUN_NONE) {                         \
     812             :                         has_nils = true;                        \
     813             :                         for (; rb < rend; rb++)                      \
     814             :                                 *rb = TPE##_nil;                \
     815             :                 } else if (p) {                                 \
     816             :                         pnp = np = (bit*)Tloc(p, 0);            \
     817             :                         end = np + cnt;                         \
     818             :                         for (; np < end; np++) {             \
     819             :                                 if (*np) {                      \
     820             :                                         ncnt = (np - pnp);      \
     821             :                                         rp += ncnt;             \
     822             :                                         LEAD_CALC(TPE);         \
     823             :                                         pnp = np;               \
     824             :                                 }                               \
     825             :                         }                                       \
     826             :                         ncnt = (np - pnp);                      \
     827             :                         rp += ncnt;                             \
     828             :                         LEAD_CALC(TPE);                         \
     829             :                 } else {                                        \
     830             :                         ncnt = cnt;                             \
     831             :                         rp += ncnt;                             \
     832             :                         LEAD_CALC(TPE);                         \
     833             :                 }                                               \
     834             :         } while (0)
     835             : 
     836             : #define ANALYTICAL_LEAD_OTHERS                                          \
     837             :         do {                                                            \
     838             :                 j += ncnt;                                              \
     839             :                 if (lead < ncnt) {                                   \
     840             :                         m = ncnt - lead;                                \
     841             :                         for (i = 0,n = k + lead; i < m; i++, n++) {  \
     842             :                                 curval = BUNtail(bpi, n);               \
     843             :                                 if (BUNappend(r, curval, false) != GDK_SUCCEED) \
     844             :                                         return GDK_FAIL;                \
     845             :                                 has_nils |= atomcmp(curval, nil) == 0;          \
     846             :                         }                                               \
     847             :                         k += i;                                         \
     848             :                 }                                                       \
     849             :                 for (; k < j; k++) {                                 \
     850             :                         if (BUNappend(r, default_value, false) != GDK_SUCCEED) \
     851             :                                 return GDK_FAIL;                        \
     852             :                 }                                                       \
     853             :                 has_nils |= (lead > 0 && atomcmp(default_value, nil) == 0);  \
     854             :         } while (0)
     855             : 
     856             : gdk_return
     857          28 : GDKanalyticallead(BAT *r, BAT *b, BAT *p, BUN lead, const void *restrict default_value, int tpe)
     858             : {
     859          28 :         int (*atomcmp) (const void *, const void *);
     860          28 :         const void *restrict nil;
     861          28 :         BUN i = 0, j = 0, k = 0, l = 0, ncnt, cnt = BATcount(b);
     862          28 :         bit *np, *pnp, *end;
     863          28 :         bool has_nils = false;
     864             : 
     865          28 :         assert(default_value);
     866             : 
     867          28 :         switch (tpe) {
     868           0 :         case TYPE_bit:
     869           0 :                 ANALYTICAL_LEAD_IMP(bit);
     870             :                 break;
     871           3 :         case TYPE_bte:
     872          33 :                 ANALYTICAL_LEAD_IMP(bte);
     873             :                 break;
     874           0 :         case TYPE_sht:
     875           0 :                 ANALYTICAL_LEAD_IMP(sht);
     876             :                 break;
     877          18 :         case TYPE_int:
     878         304 :                 ANALYTICAL_LEAD_IMP(int);
     879             :                 break;
     880           1 :         case TYPE_lng:
     881          23 :                 ANALYTICAL_LEAD_IMP(lng);
     882             :                 break;
     883             : #ifdef HAVE_HGE
     884           0 :         case TYPE_hge:
     885           0 :                 ANALYTICAL_LEAD_IMP(hge);
     886             :                 break;
     887             : #endif
     888           0 :         case TYPE_flt:
     889           0 :                 ANALYTICAL_LEAD_IMP(flt);
     890             :                 break;
     891           0 :         case TYPE_dbl:
     892           0 :                 ANALYTICAL_LEAD_IMP(dbl);
     893             :                 break;
     894           6 :         default:{
     895           6 :                 BUN m = 0, n = 0;
     896           6 :                 BATiter bpi = bat_iterator(b);
     897           6 :                 const void *restrict curval;
     898           6 :                 nil = ATOMnilptr(tpe);
     899           6 :                 atomcmp = ATOMcompare(tpe);
     900           6 :                 if (lead == BUN_NONE) {
     901           0 :                         has_nils = true;
     902           0 :                         for (j = 0; j < cnt; j++) {
     903           0 :                                 if (BUNappend(r, nil, false) != GDK_SUCCEED)
     904           0 :                                         return GDK_FAIL;
     905             :                         }
     906           6 :                 } else if (p) {
     907           4 :                         pnp = np = (bit *) Tloc(p, 0);
     908           4 :                         end = np + cnt;
     909          42 :                         for (; np < end; np++) {
     910          38 :                                 if (*np) {
     911          12 :                                         ncnt = (np - pnp);
     912          56 :                                         ANALYTICAL_LEAD_OTHERS;
     913          12 :                                         pnp = np;
     914             :                                 }
     915             :                         }
     916           4 :                         ncnt = (np - pnp);
     917          14 :                         ANALYTICAL_LEAD_OTHERS;
     918             :                 } else {
     919           2 :                         ncnt = cnt;
     920          24 :                         ANALYTICAL_LEAD_OTHERS;
     921             :                 }
     922             :         }
     923             :         }
     924          28 :         BATsetcount(r, cnt);
     925          28 :         r->tnonil = !has_nils;
     926          28 :         r->tnil = has_nils;
     927          28 :         return GDK_SUCCEED;
     928             : }
     929             : 
     930             : #define ANALYTICAL_MIN_MAX_CALC(TPE, OP)                                \
     931             :         do {                                                            \
     932             :                 TPE *bp = (TPE*)Tloc(b, 0), *bs, *be, v,                \
     933             :                         curval = TPE##_nil, *restrict rb = (TPE*)Tloc(r, 0); \
     934             :                 for (; i < cnt; i++, rb++) {                         \
     935             :                         bs = bp + start[i];                             \
     936             :                         be = bp + end[i];                               \
     937             :                         for (; bs < be; bs++) {                              \
     938             :                                 v = *bs;                                \
     939             :                                 if (!is_##TPE##_nil(v)) {               \
     940             :                                         if (is_##TPE##_nil(curval))     \
     941             :                                                 curval = v;             \
     942             :                                         else                            \
     943             :                                                 curval = OP(v, curval); \
     944             :                                 }                                       \
     945             :                         }                                               \
     946             :                         *rb = curval;                                   \
     947             :                         if (is_##TPE##_nil(curval))                     \
     948             :                                 has_nils = true;                        \
     949             :                         else                                            \
     950             :                                 curval = TPE##_nil;     /* For the next iteration */    \
     951             :                 }                                                       \
     952             :         } while (0)
     953             : 
     954             : #ifdef HAVE_HGE
     955             : #define ANALYTICAL_MIN_MAX_LIMIT(OP)                    \
     956             :         case TYPE_hge:                                  \
     957             :                 ANALYTICAL_MIN_MAX_CALC(hge, OP);       \
     958             :         break;
     959             : #else
     960             : #define ANALYTICAL_MIN_MAX_LIMIT(OP)
     961             : #endif
     962             : 
     963             : #define ANALYTICAL_MIN_MAX(OP, IMP, SIGN_OP)                            \
     964             : gdk_return                                                              \
     965             : GDKanalytical##OP(BAT *r, BAT *b, BAT *s, BAT *e, int tpe)              \
     966             : {                                                                       \
     967             :         bool has_nils = false;                                          \
     968             :         BUN i = 0, cnt = BATcount(b);                                   \
     969             :         lng *restrict start, *restrict end, j = 0, l = 0;               \
     970             :                                                                         \
     971             :         assert(s && e);                                                 \
     972             :         start = (lng*)Tloc(s, 0);                                       \
     973             :         end = (lng*)Tloc(e, 0);                                         \
     974             :                                                                         \
     975             :         switch (tpe) {                                                  \
     976             :         case TYPE_bit:                                                  \
     977             :                 ANALYTICAL_MIN_MAX_CALC(bit, IMP);                      \
     978             :                 break;                                                  \
     979             :         case TYPE_bte:                                                  \
     980             :                 ANALYTICAL_MIN_MAX_CALC(bte, IMP);                      \
     981             :                 break;                                                  \
     982             :         case TYPE_sht:                                                  \
     983             :                 ANALYTICAL_MIN_MAX_CALC(sht, IMP);                      \
     984             :                 break;                                                  \
     985             :         case TYPE_int:                                                  \
     986             :                 ANALYTICAL_MIN_MAX_CALC(int, IMP);                      \
     987             :                 break;                                                  \
     988             :         case TYPE_lng:                                                  \
     989             :                 ANALYTICAL_MIN_MAX_CALC(lng, IMP);                      \
     990             :                 break;                                                  \
     991             :                 ANALYTICAL_MIN_MAX_LIMIT(IMP)                           \
     992             :         case TYPE_flt:                                                  \
     993             :                 ANALYTICAL_MIN_MAX_CALC(flt, IMP);                      \
     994             :                 break;                                                  \
     995             :         case TYPE_dbl:                                                  \
     996             :                 ANALYTICAL_MIN_MAX_CALC(dbl, IMP);                      \
     997             :                 break;                                                  \
     998             :         default: {                                                      \
     999             :                 BATiter bpi = bat_iterator(b);                          \
    1000             :                 const void *nil = ATOMnilptr(tpe);                      \
    1001             :                 int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe); \
    1002             :                 void *curval;                                           \
    1003             :                 for (; i < cnt; i++) {                                       \
    1004             :                         j = start[i];                                   \
    1005             :                         l = end[i];                                     \
    1006             :                         curval = (void*)nil;                            \
    1007             :                         for (;j < l; j++) {                          \
    1008             :                                 void *next = BUNtail(bpi, (BUN) j);     \
    1009             :                                 if (atomcmp(next, nil) != 0) {          \
    1010             :                                         if (atomcmp(curval, nil) == 0)  \
    1011             :                                                 curval = next;          \
    1012             :                                         else                            \
    1013             :                                                 curval = atomcmp(next, curval) SIGN_OP 0 ? curval : next; \
    1014             :                                 }                                       \
    1015             :                         }                                               \
    1016             :                         if (BUNappend(r, curval, false) != GDK_SUCCEED) \
    1017             :                                 return GDK_FAIL;                        \
    1018             :                         has_nils |= atomcmp(curval, nil) == 0;          \
    1019             :                 }                                                       \
    1020             :         }                                                               \
    1021             :         }                                                               \
    1022             :         BATsetcount(r, cnt);                                            \
    1023             :         r->tnonil = !has_nils;                                               \
    1024             :         r->tnil = has_nils;                                          \
    1025             :         return GDK_SUCCEED;                                             \
    1026             : }
    1027             : 
    1028        3098 : ANALYTICAL_MIN_MAX(min, MIN, >)
    1029    43570500 : ANALYTICAL_MIN_MAX(max, MAX, <)
    1030             : 
    1031             : #define ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(TPE)             \
    1032             :         do {                                                    \
    1033             :                 TPE *bp, *bs, *be;                              \
    1034             :                 bp = (TPE*)Tloc(b, 0);                          \
    1035             :                 for (; i < cnt; i++, rb++) {                 \
    1036             :                         bs = bp + start[i];             \
    1037             :                         be = bp + end[i];               \
    1038             :                         for (; bs < be; bs++)                        \
    1039             :                                 curval += !is_##TPE##_nil(*bs); \
    1040             :                         *rb = curval;           \
    1041             :                         curval = 0;             \
    1042             :                 }                                               \
    1043             :         } while (0)
    1044             : 
    1045             : #define ANALYTICAL_COUNT_NO_NIL_STR_IMP(TPE_CAST, OFFSET)               \
    1046             :         do {                                                            \
    1047             :                 for (; i < cnt; i++, rb++) {                         \
    1048             :                         j = start[i];                                   \
    1049             :                         l = end[i];                                     \
    1050             :                         for (; j < l; j++)                           \
    1051             :                                 curval += base[(var_t) ((TPE_CAST) bp) OFFSET] != '\200'; \
    1052             :                         *rb = curval;                                   \
    1053             :                         curval = 0;                                     \
    1054             :                 }                                                       \
    1055             :         } while (0)
    1056             : 
    1057             : gdk_return
    1058         167 : GDKanalyticalcount(BAT *r, BAT *b, BAT *s, BAT *e, const bit *restrict ignore_nils, int tpe)
    1059             : {
    1060         167 :         BUN i = 0, cnt = BATcount(b);
    1061         167 :         lng *restrict rb = (lng *) Tloc(r, 0), *restrict start, *restrict end, curval = 0, j = 0, l = 0;
    1062             : 
    1063         167 :         assert(s && e && ignore_nils);
    1064         167 :         start = (lng *) Tloc(s, 0);
    1065         167 :         end = (lng *) Tloc(e, 0);
    1066             : 
    1067         167 :         if (!*ignore_nils || b->tnonil) {
    1068         959 :                 for (; i < cnt; i++, rb++)
    1069         850 :                         *rb = (end[i] > start[i]) ? (end[i] - start[i]) : 0;
    1070             :         } else {
    1071          58 :                 switch (tpe) {
    1072           0 :                 case TYPE_bit:
    1073           0 :                         ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(bit);
    1074             :                         break;
    1075           1 :                 case TYPE_bte:
    1076         111 :                         ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(bte);
    1077             :                         break;
    1078           0 :                 case TYPE_sht:
    1079           0 :                         ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(sht);
    1080             :                         break;
    1081          33 :                 case TYPE_int:
    1082        1377 :                         ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(int);
    1083             :                         break;
    1084           4 :                 case TYPE_lng:
    1085         192 :                         ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(lng);
    1086             :                         break;
    1087             : #ifdef HAVE_HGE
    1088           0 :                 case TYPE_hge:
    1089           0 :                         ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(hge);
    1090             :                         break;
    1091             : #endif
    1092           0 :                 case TYPE_flt:
    1093           0 :                         ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(flt);
    1094             :                         break;
    1095           0 :                 case TYPE_dbl:
    1096           0 :                         ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(dbl);
    1097             :                         break;
    1098          20 :                 case TYPE_str:{
    1099          20 :                         const char *restrict base = b->tvheap->base;
    1100          20 :                         const void *restrict bp = Tloc(b, 0);
    1101          20 :                         switch (b->twidth) {
    1102             :                         case 1:
    1103         961 :                                 ANALYTICAL_COUNT_NO_NIL_STR_IMP(const unsigned char *,[j] + GDK_VAROFFSET);
    1104             :                                 break;
    1105             :                         case 2:
    1106           0 :                                 ANALYTICAL_COUNT_NO_NIL_STR_IMP(const unsigned short *,[j] + GDK_VAROFFSET);
    1107             :                                 break;
    1108             : #if SIZEOF_VAR_T != SIZEOF_INT
    1109             :                         case 4:
    1110           0 :                                 ANALYTICAL_COUNT_NO_NIL_STR_IMP(const unsigned int *,[j]);
    1111             :                                 break;
    1112             : #endif
    1113             :                         default:
    1114           0 :                                 ANALYTICAL_COUNT_NO_NIL_STR_IMP(const var_t *,[j]);
    1115             :                                 break;
    1116             :                         }
    1117             :                         break;
    1118             :                 }
    1119           0 :                 default:{
    1120           0 :                         const void *restrict nil = ATOMnilptr(tpe);
    1121           0 :                         int (*cmp) (const void *, const void *) = ATOMcompare(tpe);
    1122           0 :                         if (b->tvarsized) {
    1123           0 :                                 const char *restrict base = b->tvheap->base;
    1124           0 :                                 const void *restrict bp = Tloc(b, 0);
    1125           0 :                                 for (; i < cnt; i++, rb++) {
    1126           0 :                                         j = start[i];
    1127           0 :                                         l = end[i];
    1128           0 :                                         for (; j < l; j++)
    1129           0 :                                                 curval += cmp(nil, base + ((const var_t *) bp)[j]) != 0;
    1130           0 :                                         *rb = curval;
    1131           0 :                                         curval = 0;
    1132             :                                 }
    1133             :                         } else {
    1134           0 :                                 for (; i < cnt; i++, rb++) {
    1135           0 :                                         j = start[i];
    1136           0 :                                         l = end[i];
    1137           0 :                                         for (; j < l; j++)
    1138           0 :                                                 curval += cmp(Tloc(b, j), nil) != 0;
    1139           0 :                                         *rb = curval;
    1140           0 :                                         curval = 0;
    1141             :                                 }
    1142             :                         }
    1143             :                 }
    1144             :                 }
    1145             :         }
    1146         167 :         BATsetcount(r, cnt);
    1147         167 :         r->tnonil = true;
    1148         167 :         r->tnil = false;
    1149         167 :         return GDK_SUCCEED;
    1150             : }
    1151             : 
    1152             : #define ANALYTICAL_SUM_IMP_NUM(TPE1, TPE2)                              \
    1153             :         do {                                                            \
    1154             :                 TPE1 *bs, *be, v;                                       \
    1155             :                 for (; i < cnt; i++, rb++) {                         \
    1156             :                         bs = bp + start[i];                             \
    1157             :                         be = bp + end[i];                               \
    1158             :                         for (; bs < be; bs++) {                              \
    1159             :                                 v = *bs;                                \
    1160             :                                 if (!is_##TPE1##_nil(v)) {              \
    1161             :                                         if (is_##TPE2##_nil(curval))    \
    1162             :                                                 curval = (TPE2) v;      \
    1163             :                                         else                            \
    1164             :                                                 ADD_WITH_CHECK(v, curval, TPE2, curval, GDK_##TPE2##_max, goto calc_overflow); \
    1165             :                                 }                                       \
    1166             :                         }                                               \
    1167             :                         *rb = curval;                                   \
    1168             :                         if (is_##TPE2##_nil(curval))                    \
    1169             :                                 has_nils = true;                        \
    1170             :                         else                                            \
    1171             :                                 curval = TPE2##_nil;    /* For the next iteration */ \
    1172             :                 }                                                       \
    1173             :         } while (0)
    1174             : 
    1175             : #define ANALYTICAL_SUM_IMP_FP(TPE1, TPE2)                               \
    1176             :         do {                                                            \
    1177             :                 TPE1 *bs;                                               \
    1178             :                 BUN parcel;                                             \
    1179             :                 for (; i < cnt; i++, rb++) {                         \
    1180             :                         if (end[i] > start[i]) {                     \
    1181             :                                 bs = bp + start[i];                     \
    1182             :                                 parcel = (BUN)(end[i] - start[i]);      \
    1183             :                                 if (dofsum(bs, 0,                       \
    1184             :                                            &(struct canditer){.tpe = cand_dense, .ncand = parcel,}, \
    1185             :                                            parcel, &curval, 1, TYPE_##TPE1, \
    1186             :                                            TYPE_##TPE2, NULL, 0, 0, true, \
    1187             :                                            false, true) == BUN_NONE) {  \
    1188             :                                         goto bailout;                   \
    1189             :                                 }                                       \
    1190             :                         }                                               \
    1191             :                         *rb = curval;                                   \
    1192             :                         if (is_##TPE2##_nil(curval))                    \
    1193             :                                 has_nils = true;                        \
    1194             :                         else                                            \
    1195             :                                 curval = TPE2##_nil;    /* For the next iteration */ \
    1196             :                 }                                                       \
    1197             :         } while (0)
    1198             : 
    1199             : #define ANALYTICAL_SUM_CALC(TPE1, TPE2, IMP)            \
    1200             :         do {                                            \
    1201             :                 TPE1 *bp = (TPE1*)Tloc(b, 0);           \
    1202             :                 TPE2 *restrict rb, curval = TPE2##_nil; \
    1203             :                 rb = (TPE2*)Tloc(r, 0);                 \
    1204             :                 IMP(TPE1, TPE2);                        \
    1205             :         } while (0)
    1206             : 
    1207             : gdk_return
    1208         117 : GDKanalyticalsum(BAT *r, BAT *b, BAT *s, BAT *e, int tp1, int tp2)
    1209             : {
    1210         117 :         bool has_nils = false;
    1211         117 :         BUN i = 0, cnt = BATcount(b), nils = 0;
    1212         117 :         int abort_on_error = 1;
    1213         117 :         lng *restrict start, *restrict end;
    1214             : 
    1215         117 :         assert(s && e);
    1216         117 :         start = (lng *) Tloc(s, 0);
    1217         117 :         end = (lng *) Tloc(e, 0);
    1218             : 
    1219         117 :         switch (tp2) {
    1220           0 :         case TYPE_bte:{
    1221           0 :                 switch (tp1) {
    1222           0 :                 case TYPE_bte:
    1223           0 :                         ANALYTICAL_SUM_CALC(bte, bte, ANALYTICAL_SUM_IMP_NUM);
    1224             :                         break;
    1225           0 :                 default:
    1226           0 :                         goto nosupport;
    1227             :                 }
    1228             :                 break;
    1229             :         }
    1230           0 :         case TYPE_sht:{
    1231           0 :                 switch (tp1) {
    1232           0 :                 case TYPE_bte:
    1233           0 :                         ANALYTICAL_SUM_CALC(bte, sht, ANALYTICAL_SUM_IMP_NUM);
    1234             :                         break;
    1235           0 :                 case TYPE_sht:
    1236           0 :                         ANALYTICAL_SUM_CALC(sht, sht, ANALYTICAL_SUM_IMP_NUM);
    1237             :                         break;
    1238           0 :                 default:
    1239           0 :                         goto nosupport;
    1240             :                 }
    1241             :                 break;
    1242             :         }
    1243           0 :         case TYPE_int:{
    1244           0 :                 switch (tp1) {
    1245           0 :                 case TYPE_bte:
    1246           0 :                         ANALYTICAL_SUM_CALC(bte, int, ANALYTICAL_SUM_IMP_NUM);
    1247             :                         break;
    1248           0 :                 case TYPE_sht:
    1249           0 :                         ANALYTICAL_SUM_CALC(sht, int, ANALYTICAL_SUM_IMP_NUM);
    1250             :                         break;
    1251           0 :                 case TYPE_int:
    1252           0 :                         ANALYTICAL_SUM_CALC(int, int, ANALYTICAL_SUM_IMP_NUM);
    1253             :                         break;
    1254           0 :                 default:
    1255           0 :                         goto nosupport;
    1256             :                 }
    1257             :                 break;
    1258             :         }
    1259           0 :         case TYPE_lng:{
    1260           0 :                 switch (tp1) {
    1261           0 :                 case TYPE_bte:
    1262           0 :                         ANALYTICAL_SUM_CALC(bte, lng, ANALYTICAL_SUM_IMP_NUM);
    1263             :                         break;
    1264           0 :                 case TYPE_sht:
    1265           0 :                         ANALYTICAL_SUM_CALC(sht, lng, ANALYTICAL_SUM_IMP_NUM);
    1266             :                         break;
    1267           0 :                 case TYPE_int:
    1268           0 :                         ANALYTICAL_SUM_CALC(int, lng, ANALYTICAL_SUM_IMP_NUM);
    1269             :                         break;
    1270           0 :                 case TYPE_lng:
    1271           0 :                         ANALYTICAL_SUM_CALC(lng, lng, ANALYTICAL_SUM_IMP_NUM);
    1272             :                         break;
    1273           0 :                 default:
    1274           0 :                         goto nosupport;
    1275             :                 }
    1276             :                 break;
    1277             :         }
    1278             : #ifdef HAVE_HGE
    1279          94 :         case TYPE_hge:{
    1280          94 :                 switch (tp1) {
    1281          10 :                 case TYPE_bte:
    1282         452 :                         ANALYTICAL_SUM_CALC(bte, hge, ANALYTICAL_SUM_IMP_NUM);
    1283             :                         break;
    1284           0 :                 case TYPE_sht:
    1285           0 :                         ANALYTICAL_SUM_CALC(sht, hge, ANALYTICAL_SUM_IMP_NUM);
    1286             :                         break;
    1287          65 :                 case TYPE_int:
    1288        2629 :                         ANALYTICAL_SUM_CALC(int, hge, ANALYTICAL_SUM_IMP_NUM);
    1289             :                         break;
    1290           5 :                 case TYPE_lng:
    1291         193 :                         ANALYTICAL_SUM_CALC(lng, hge, ANALYTICAL_SUM_IMP_NUM);
    1292             :                         break;
    1293          14 :                 case TYPE_hge:
    1294    16338400 :                         ANALYTICAL_SUM_CALC(hge, hge, ANALYTICAL_SUM_IMP_NUM);
    1295             :                         break;
    1296           0 :                 default:
    1297           0 :                         goto nosupport;
    1298             :                 }
    1299             :                 break;
    1300             :         }
    1301             : #endif
    1302          12 :         case TYPE_flt:{
    1303          12 :                 switch (tp1) {
    1304          12 :                 case TYPE_flt:
    1305         126 :                         ANALYTICAL_SUM_CALC(flt, flt, ANALYTICAL_SUM_IMP_FP);
    1306          12 :                         break;
    1307           0 :                 default:
    1308           0 :                         goto nosupport;
    1309             :                 }
    1310             :                 break;
    1311             :         }
    1312          11 :         case TYPE_dbl:{
    1313          11 :                 switch (tp1) {
    1314           0 :                 case TYPE_flt:
    1315           0 :                         ANALYTICAL_SUM_CALC(flt, dbl, ANALYTICAL_SUM_IMP_FP);
    1316           0 :                         break;
    1317          11 :                 case TYPE_dbl:
    1318          73 :                         ANALYTICAL_SUM_CALC(dbl, dbl, ANALYTICAL_SUM_IMP_FP);
    1319          11 :                         break;
    1320           0 :                 default:
    1321           0 :                         goto nosupport;
    1322             :                 }
    1323             :                 break;
    1324             :         }
    1325           0 :         default:
    1326           0 :                 goto nosupport;
    1327             :         }
    1328         117 :         BATsetcount(r, cnt);
    1329         117 :         r->tnonil = !has_nils;
    1330         117 :         r->tnil = has_nils;
    1331         117 :         return GDK_SUCCEED;
    1332           0 :       bailout:
    1333           0 :         GDKerror("error while calculating floating-point sum\n");
    1334           0 :         return GDK_FAIL;
    1335           0 :       nosupport:
    1336           0 :         GDKerror("type combination (sum(%s)->%s) not supported.\n", ATOMname(tp1), ATOMname(tp2));
    1337           0 :         return GDK_FAIL;
    1338           0 :       calc_overflow:
    1339           0 :         GDKerror("22003!overflow in calculation.\n");
    1340           0 :         return GDK_FAIL;
    1341             : }
    1342             : 
    1343             : #define ANALYTICAL_PROD_CALC_NUM(TPE1, TPE2, TPE3)                      \
    1344             :         do {                                                            \
    1345             :                 TPE1 *bp = (TPE1*)Tloc(b, 0), *bs, *be, v;              \
    1346             :                 TPE2 *restrict rb, curval = TPE2##_nil;                 \
    1347             :                 rb = (TPE2*)Tloc(r, 0);                                 \
    1348             :                 for (; i < cnt; i++, rb++) {                         \
    1349             :                         bs = bp + start[i];                             \
    1350             :                         be = bp + end[i];                               \
    1351             :                         for (; bs < be; bs++) {                              \
    1352             :                                 v = *bs;                                \
    1353             :                                 if (!is_##TPE1##_nil(v)) {              \
    1354             :                                         if (is_##TPE2##_nil(curval))    \
    1355             :                                                 curval = (TPE2) v;      \
    1356             :                                         else                            \
    1357             :                                                 MUL4_WITH_CHECK(v, curval, TPE2, curval, GDK_##TPE2##_max, TPE3, \
    1358             :                                                                                 goto calc_overflow); \
    1359             :                                 }                                       \
    1360             :                         }                                               \
    1361             :                         *rb = curval;                                   \
    1362             :                         if (is_##TPE2##_nil(curval))                    \
    1363             :                                 has_nils = true;                        \
    1364             :                         else                                            \
    1365             :                                 curval = TPE2##_nil;    /* For the next iteration */    \
    1366             :                 }                                                       \
    1367             :         } while (0)
    1368             : 
    1369             : #define ANALYTICAL_PROD_CALC_NUM_LIMIT(TPE1, TPE2, REAL_IMP)            \
    1370             :         do {                                                            \
    1371             :                 TPE1 *bp = (TPE1*)Tloc(b, 0), *bs, *be, v;              \
    1372             :                 TPE2 *restrict rb, curval = TPE2##_nil;                 \
    1373             :                 rb = (TPE2*)Tloc(r, 0);                                 \
    1374             :                 for (; i < cnt; i++, rb++) {                         \
    1375             :                         bs = bp + start[i];                             \
    1376             :                         be = bp + end[i];                               \
    1377             :                         for (; bs < be; bs++) {                              \
    1378             :                                 v = *bs;                                \
    1379             :                                 if (!is_##TPE1##_nil(v)) {              \
    1380             :                                         if (is_##TPE2##_nil(curval))    \
    1381             :                                                 curval = (TPE2) v;      \
    1382             :                                         else                            \
    1383             :                                                 REAL_IMP(v, curval, curval, GDK_##TPE2##_max, goto calc_overflow); \
    1384             :                                 }                                       \
    1385             :                         }                                               \
    1386             :                         *rb = curval;                                   \
    1387             :                         if (is_##TPE2##_nil(curval))                    \
    1388             :                                 has_nils = true;                        \
    1389             :                         else                                            \
    1390             :                                 curval = TPE2##_nil;    /* For the next iteration */    \
    1391             :                 }                                                       \
    1392             :         } while (0)
    1393             : 
    1394             : #define ANALYTICAL_PROD_CALC_FP(TPE1, TPE2)                             \
    1395             :         do {                                                            \
    1396             :                 TPE1 *bp = (TPE1*)Tloc(b, 0), *bs, *be, v;              \
    1397             :                 TPE2 *restrict rb, curval = TPE2##_nil;                 \
    1398             :                 rb = (TPE2*)Tloc(r, 0);                                 \
    1399             :                 for (; i < cnt; i++, rb++) {                         \
    1400             :                         bs = bp + start[i];                             \
    1401             :                         be = bp + end[i];                               \
    1402             :                         for (; bs < be; bs++) {                              \
    1403             :                                 v = *bs;                                \
    1404             :                                 if (!is_##TPE1##_nil(v)) {              \
    1405             :                                         if (is_##TPE2##_nil(curval)) {  \
    1406             :                                                 curval = (TPE2) v;      \
    1407             :                                         } else if (ABSOLUTE(curval) > 1 && GDK_##TPE2##_max / ABSOLUTE(v) < ABSOLUTE(curval)) { \
    1408             :                                                 if (abort_on_error)     \
    1409             :                                                         goto calc_overflow; \
    1410             :                                                 curval = TPE2##_nil;    \
    1411             :                                                 nils++;                 \
    1412             :                                         } else {                        \
    1413             :                                                 curval *= v;            \
    1414             :                                         }                               \
    1415             :                                 }                                       \
    1416             :                         }                                               \
    1417             :                         *rb = curval;                                   \
    1418             :                         if (is_##TPE2##_nil(curval))                    \
    1419             :                                 has_nils = true;                        \
    1420             :                         else                                            \
    1421             :                                 curval = TPE2##_nil;    /* For the next iteration */    \
    1422             :                 }                                                       \
    1423             :         } while (0)
    1424             : 
    1425             : gdk_return
    1426          31 : GDKanalyticalprod(BAT *r, BAT *b, BAT *s, BAT *e, int tp1, int tp2)
    1427             : {
    1428          31 :         bool has_nils = false;
    1429          31 :         BUN i = 0, cnt = BATcount(b), nils = 0;
    1430          31 :         int abort_on_error = 1;
    1431          31 :         lng *restrict start, *restrict end;
    1432             : 
    1433          31 :         assert(s && e);
    1434          31 :         start = (lng *) Tloc(s, 0);
    1435          31 :         end = (lng *) Tloc(e, 0);
    1436             : 
    1437          31 :         switch (tp2) {
    1438           0 :         case TYPE_bte:{
    1439           0 :                 switch (tp1) {
    1440           0 :                 case TYPE_bte:
    1441           0 :                         ANALYTICAL_PROD_CALC_NUM(bte, bte, sht);
    1442             :                         break;
    1443           0 :                 default:
    1444           0 :                         goto nosupport;
    1445             :                 }
    1446             :                 break;
    1447             :         }
    1448           0 :         case TYPE_sht:{
    1449           0 :                 switch (tp1) {
    1450           0 :                 case TYPE_bte:
    1451           0 :                         ANALYTICAL_PROD_CALC_NUM(bte, sht, int);
    1452             :                         break;
    1453           0 :                 case TYPE_sht:
    1454           0 :                         ANALYTICAL_PROD_CALC_NUM(sht, sht, int);
    1455             :                         break;
    1456           0 :                 default:
    1457           0 :                         goto nosupport;
    1458             :                 }
    1459             :                 break;
    1460             :         }
    1461           0 :         case TYPE_int:{
    1462           0 :                 switch (tp1) {
    1463           0 :                 case TYPE_bte:
    1464           0 :                         ANALYTICAL_PROD_CALC_NUM(bte, int, lng);
    1465             :                         break;
    1466           0 :                 case TYPE_sht:
    1467           0 :                         ANALYTICAL_PROD_CALC_NUM(sht, int, lng);
    1468             :                         break;
    1469           0 :                 case TYPE_int:
    1470           0 :                         ANALYTICAL_PROD_CALC_NUM(int, int, lng);
    1471             :                         break;
    1472           0 :                 default:
    1473           0 :                         goto nosupport;
    1474             :                 }
    1475             :                 break;
    1476             :         }
    1477             : #ifdef HAVE_HGE
    1478           0 :         case TYPE_lng:{
    1479           0 :                 switch (tp1) {
    1480           0 :                 case TYPE_bte:
    1481           0 :                         ANALYTICAL_PROD_CALC_NUM(bte, lng, hge);
    1482             :                         break;
    1483           0 :                 case TYPE_sht:
    1484           0 :                         ANALYTICAL_PROD_CALC_NUM(sht, lng, hge);
    1485             :                         break;
    1486           0 :                 case TYPE_int:
    1487           0 :                         ANALYTICAL_PROD_CALC_NUM(int, lng, hge);
    1488             :                         break;
    1489           0 :                 case TYPE_lng:
    1490           0 :                         ANALYTICAL_PROD_CALC_NUM(lng, lng, hge);
    1491             :                         break;
    1492           0 :                 default:
    1493           0 :                         goto nosupport;
    1494             :                 }
    1495             :                 break;
    1496             :         }
    1497          23 :         case TYPE_hge:{
    1498          23 :                 switch (tp1) {
    1499           1 :                 case TYPE_bte:
    1500         111 :                         ANALYTICAL_PROD_CALC_NUM_LIMIT(bte, hge, HGEMUL_CHECK);
    1501             :                         break;
    1502           2 :                 case TYPE_sht:
    1503         144 :                         ANALYTICAL_PROD_CALC_NUM_LIMIT(sht, hge, HGEMUL_CHECK);
    1504             :                         break;
    1505          17 :                 case TYPE_int:
    1506         784 :                         ANALYTICAL_PROD_CALC_NUM_LIMIT(int, hge, HGEMUL_CHECK);
    1507             :                         break;
    1508           3 :                 case TYPE_lng:
    1509         117 :                         ANALYTICAL_PROD_CALC_NUM_LIMIT(lng, hge, HGEMUL_CHECK);
    1510             :                         break;
    1511           0 :                 case TYPE_hge:
    1512           0 :                         ANALYTICAL_PROD_CALC_NUM_LIMIT(hge, hge, HGEMUL_CHECK);
    1513             :                         break;
    1514           0 :                 default:
    1515           0 :                         goto nosupport;
    1516             :                 }
    1517             :                 break;
    1518             :         }
    1519             : #else
    1520             :         case TYPE_lng:{
    1521             :                 switch (tp1) {
    1522             :                 case TYPE_bte:
    1523             :                         ANALYTICAL_PROD_CALC_NUM_LIMIT(bte, lng, LNGMUL_CHECK);
    1524             :                         break;
    1525             :                 case TYPE_sht:
    1526             :                         ANALYTICAL_PROD_CALC_NUM_LIMIT(sht, lng, LNGMUL_CHECK);
    1527             :                         break;
    1528             :                 case TYPE_int:
    1529             :                         ANALYTICAL_PROD_CALC_NUM_LIMIT(int, lng, LNGMUL_CHECK);
    1530             :                         break;
    1531             :                 case TYPE_lng:
    1532             :                         ANALYTICAL_PROD_CALC_NUM_LIMIT(lng, lng, LNGMUL_CHECK);
    1533             :                         break;
    1534             :                 default:
    1535             :                         goto nosupport;
    1536             :                 }
    1537             :                 break;
    1538             :         }
    1539             : #endif
    1540           8 :         case TYPE_flt:{
    1541           8 :                 switch (tp1) {
    1542           8 :                 case TYPE_flt:
    1543         354 :                         ANALYTICAL_PROD_CALC_FP(flt, flt);
    1544             :                         break;
    1545           0 :                 default:
    1546           0 :                         goto nosupport;
    1547             :                 }
    1548             :                 break;
    1549             :         }
    1550           0 :         case TYPE_dbl:{
    1551           0 :                 switch (tp1) {
    1552           0 :                 case TYPE_flt:
    1553           0 :                         ANALYTICAL_PROD_CALC_FP(flt, dbl);
    1554             :                         break;
    1555           0 :                 case TYPE_dbl:
    1556           0 :                         ANALYTICAL_PROD_CALC_FP(dbl, dbl);
    1557             :                         break;
    1558           0 :                 default:
    1559           0 :                         goto nosupport;
    1560             :                 }
    1561             :                 break;
    1562             :         }
    1563           0 :         default:
    1564           0 :                 goto nosupport;
    1565             :         }
    1566          31 :         BATsetcount(r, cnt);
    1567          31 :         r->tnonil = !has_nils;
    1568          31 :         r->tnil = has_nils;
    1569          31 :         return GDK_SUCCEED;
    1570           0 :       nosupport:
    1571           0 :         GDKerror("type combination (prod(%s)->%s) not supported.\n", ATOMname(tp1), ATOMname(tp2));
    1572           0 :         return GDK_FAIL;
    1573           0 :       calc_overflow:
    1574           0 :         GDKerror("22003!overflow in calculation.\n");
    1575           0 :         return GDK_FAIL;
    1576             : }
    1577             : 
    1578             : #define ANALYTICAL_AVERAGE_CALC_NUM(TPE,lng_hge)                        \
    1579             :         do {                                                            \
    1580             :                 TPE *bp = (TPE*)Tloc(b, 0), *bs, *be, v, a = 0;         \
    1581             :                 for (; i < cnt; i++, rb++) {                         \
    1582             :                         bs = bp + start[i];                             \
    1583             :                         be = bp + end[i];                               \
    1584             :                         for (; bs < be; bs++) {                              \
    1585             :                                 v = *bs;                                \
    1586             :                                 if (!is_##TPE##_nil(v)) {               \
    1587             :                                         ADD_WITH_CHECK(v, sum, lng_hge, sum, GDK_##lng_hge##_max, goto avg_overflow##TPE); \
    1588             :                                         /* count only when no overflow occurs */ \
    1589             :                                         n++;                            \
    1590             :                                 }                                       \
    1591             :                         }                                               \
    1592             :                         if (0) {                                        \
    1593             : avg_overflow##TPE:                                                      \
    1594             :                                 assert(n > 0);                               \
    1595             :                                 if (sum >= 0) {                              \
    1596             :                                         a = (TPE) (sum / (lng_hge) n);  \
    1597             :                                         rr = (BUN) (sum % (SBUN) n);    \
    1598             :                                 } else {                                \
    1599             :                                         sum = -sum;                     \
    1600             :                                         a = - (TPE) (sum / (lng_hge) n); \
    1601             :                                         rr = (BUN) (sum % (SBUN) n);    \
    1602             :                                         if (r) {                        \
    1603             :                                                 a--;                    \
    1604             :                                                 rr = n - rr;            \
    1605             :                                         }                               \
    1606             :                                 }                                       \
    1607             :                                 for (; bs < be; bs++) {                      \
    1608             :                                         v = *bs;                        \
    1609             :                                         if (is_##TPE##_nil(v))          \
    1610             :                                                 continue;               \
    1611             :                                         AVERAGE_ITER(TPE, v, a, rr, n); \
    1612             :                                 }                                       \
    1613             :                                 curval = a + (dbl) rr / n;              \
    1614             :                                 goto calc_done##TPE;                    \
    1615             :                         }                                               \
    1616             :                         curval = n > 0 ? (dbl) sum / n : dbl_nil;    \
    1617             : calc_done##TPE:                                                         \
    1618             :                         *rb = curval;                                   \
    1619             :                         has_nils = has_nils || (n == 0);                \
    1620             :                         n = 0;                                          \
    1621             :                         sum = 0;                                        \
    1622             :                 }                                                       \
    1623             :         } while (0)
    1624             : 
    1625             : #ifdef HAVE_HGE
    1626             : #define ANALYTICAL_AVERAGE_LNG_HGE(TPE) ANALYTICAL_AVERAGE_CALC_NUM(TPE,hge)
    1627             : #else
    1628             : #define ANALYTICAL_AVERAGE_LNG_HGE(TPE) ANALYTICAL_AVERAGE_CALC_NUM(TPE,lng)
    1629             : #endif
    1630             : 
    1631             : #define ANALYTICAL_AVERAGE_CALC_FP(TPE)                                 \
    1632             :         do {                                                            \
    1633             :                 TPE *bp = (TPE*)Tloc(b, 0), *bs, *be, v;                \
    1634             :                 dbl a = 0;                                              \
    1635             :                 for (; i < cnt; i++, rb++) {                         \
    1636             :                         bs = bp + start[i];                             \
    1637             :                         be = bp + end[i];                               \
    1638             :                         for (; bs < be; bs++) {                              \
    1639             :                                 v = *bs;                                \
    1640             :                                 if (!is_##TPE##_nil(v))                 \
    1641             :                                         AVERAGE_ITER_FLOAT(TPE, v, a, n); \
    1642             :                         }                                               \
    1643             :                         curval = (n > 0) ? a : dbl_nil;                      \
    1644             :                         *rb = curval;                                   \
    1645             :                         has_nils = has_nils || (n == 0);                \
    1646             :                         n = 0;                                          \
    1647             :                         a = 0;                                          \
    1648             :                 }                                                       \
    1649             :         } while (0)
    1650             : 
    1651             : gdk_return
    1652          89 : GDKanalyticalavg(BAT *r, BAT *b, BAT *s, BAT *e, int tpe)
    1653             : {
    1654          89 :         bool has_nils = false;
    1655          89 :         BUN i = 0, cnt = BATcount(b), nils = 0, n = 0, rr = 0;
    1656          89 :         bool abort_on_error = true;
    1657          89 :         lng *restrict start, *restrict end;
    1658          89 :         dbl *restrict rb = (dbl *) Tloc(r, 0), curval;
    1659             : #ifdef HAVE_HGE
    1660          89 :         hge sum = 0;
    1661             : #else
    1662             :         lng sum = 0;
    1663             : #endif
    1664             : 
    1665          89 :         assert(s && e);
    1666          89 :         start = (lng *) Tloc(s, 0);
    1667          89 :         end = (lng *) Tloc(e, 0);
    1668             : 
    1669          89 :         switch (tpe) {
    1670           4 :         case TYPE_bte:
    1671         228 :                 ANALYTICAL_AVERAGE_LNG_HGE(bte);
    1672             :                 break;
    1673           0 :         case TYPE_sht:
    1674           0 :                 ANALYTICAL_AVERAGE_LNG_HGE(sht);
    1675             :                 break;
    1676          41 :         case TYPE_int:
    1677        1752 :                 ANALYTICAL_AVERAGE_LNG_HGE(int);
    1678             :                 break;
    1679           4 :         case TYPE_lng:
    1680         192 :                 ANALYTICAL_AVERAGE_LNG_HGE(lng);
    1681             :                 break;
    1682             : #ifdef HAVE_HGE
    1683          18 :         case TYPE_hge:
    1684         632 :                 ANALYTICAL_AVERAGE_LNG_HGE(hge);
    1685             :                 break;
    1686             : #endif
    1687          19 :         case TYPE_flt:
    1688     1092200 :                 ANALYTICAL_AVERAGE_CALC_FP(flt);
    1689             :                 break;
    1690           3 :         case TYPE_dbl:
    1691           9 :                 ANALYTICAL_AVERAGE_CALC_FP(dbl);
    1692             :                 break;
    1693           0 :         default:
    1694           0 :                 GDKerror("average of type %s unsupported.\n", ATOMname(tpe));
    1695           0 :                 return GDK_FAIL;
    1696             :         }
    1697          89 :         BATsetcount(r, cnt);
    1698          89 :         r->tnonil = !has_nils;
    1699          89 :         r->tnil = has_nils;
    1700          89 :         return GDK_SUCCEED;
    1701             : }
    1702             : 
    1703             : #define ANALYTICAL_STDEV_VARIANCE_CALC(TPE, SAMPLE, OP) \
    1704             :         do {                                                            \
    1705             :                 TPE *bp = (TPE*)Tloc(b, 0), *bs, *be, v;                \
    1706             :                 for (; i < cnt; i++, rb++) {                         \
    1707             :                         bs = bp + start[i];                             \
    1708             :                         be = bp + end[i];                               \
    1709             :                         for (; bs < be; bs++) {                              \
    1710             :                                 v = *bs;                                \
    1711             :                                 if (is_##TPE##_nil(v))          \
    1712             :                                         continue;               \
    1713             :                                 n++;                            \
    1714             :                                 delta = (dbl) v - mean;         \
    1715             :                                 mean += delta / n;              \
    1716             :                                 m2 += delta * ((dbl) v - mean); \
    1717             :                         }                                               \
    1718             :                         if (isinf(m2)) {        \
    1719             :                                 goto overflow;          \
    1720             :                         } else if (n > SAMPLE) { \
    1721             :                                 *rb = OP; \
    1722             :                         } else { \
    1723             :                                 *rb = dbl_nil; \
    1724             :                                 nils++; \
    1725             :                         } \
    1726             :                         n = 0;  \
    1727             :                         mean = 0;       \
    1728             :                         m2 = 0; \
    1729             :                 }       \
    1730             :         } while (0)
    1731             : 
    1732             : #ifdef HAVE_HGE
    1733             : #define ANALYTICAL_STDEV_VARIANCE_LIMIT(SAMPLE, OP) \
    1734             :         case TYPE_hge: \
    1735             :                 ANALYTICAL_STDEV_VARIANCE_CALC(hge, SAMPLE, OP); \
    1736             :         break;
    1737             : #else
    1738             : #define ANALYTICAL_STDEV_VARIANCE_LIMIT(SAMPLE, OP)
    1739             : #endif
    1740             : 
    1741             : #define GDK_ANALYTICAL_STDEV_VARIANCE(NAME, SAMPLE, OP, DESC) \
    1742             : gdk_return \
    1743             : GDKanalytical_##NAME(BAT *r, BAT *b, BAT *s, BAT *e, int tpe) \
    1744             : { \
    1745             :         BUN i = 0, cnt = BATcount(b), n = 0, nils = 0; \
    1746             :         lng *restrict start, *restrict end; \
    1747             :         dbl *restrict rb = (dbl *) Tloc(r, 0), mean = 0, m2 = 0, delta; \
    1748             :  \
    1749             :         assert(s && e); \
    1750             :         start = (lng *) Tloc(s, 0); \
    1751             :         end = (lng *) Tloc(e, 0); \
    1752             :  \
    1753             :         switch (tpe) { \
    1754             :         case TYPE_bte: \
    1755             :                 ANALYTICAL_STDEV_VARIANCE_CALC(bte, SAMPLE, OP); \
    1756             :                 break; \
    1757             :         case TYPE_sht: \
    1758             :                 ANALYTICAL_STDEV_VARIANCE_CALC(sht, SAMPLE, OP); \
    1759             :                 break; \
    1760             :         case TYPE_int: \
    1761             :                 ANALYTICAL_STDEV_VARIANCE_CALC(int, SAMPLE, OP); \
    1762             :                 break; \
    1763             :         case TYPE_lng: \
    1764             :                 ANALYTICAL_STDEV_VARIANCE_CALC(lng, SAMPLE, OP); \
    1765             :                 break; \
    1766             :         ANALYTICAL_STDEV_VARIANCE_LIMIT(SAMPLE, OP) \
    1767             :         case TYPE_flt:\
    1768             :                 ANALYTICAL_STDEV_VARIANCE_CALC(flt, SAMPLE, OP); \
    1769             :                 break; \
    1770             :         case TYPE_dbl: \
    1771             :                 ANALYTICAL_STDEV_VARIANCE_CALC(dbl, SAMPLE, OP); \
    1772             :                 break; \
    1773             :         default: \
    1774             :                 GDKerror("%s of type %s unsupported.\n", DESC, ATOMname(tpe)); \
    1775             :                 return GDK_FAIL; \
    1776             :         } \
    1777             :         BATsetcount(r, cnt); \
    1778             :         r->tnonil = nils == 0; \
    1779             :         r->tnil = nils > 0; \
    1780             :         return GDK_SUCCEED; \
    1781             :   overflow: \
    1782             :         GDKerror("22003!overflow in calculation.\n"); \
    1783             :         return GDK_FAIL; \
    1784             : }
    1785             : 
    1786         609 : GDK_ANALYTICAL_STDEV_VARIANCE(stddev_samp, 1, sqrt(m2 / (n - 1)), "standard deviation")
    1787         606 : GDK_ANALYTICAL_STDEV_VARIANCE(stddev_pop, 0, sqrt(m2 / n), "standard deviation")
    1788         609 : GDK_ANALYTICAL_STDEV_VARIANCE(variance_samp, 1, m2 / (n - 1), "variance")
    1789         606 : GDK_ANALYTICAL_STDEV_VARIANCE(variance_pop, 0, m2 / n, "variance")
    1790             : 
    1791             : #define ANALYTICAL_COVARIANCE_CALC(TPE, SAMPLE, OP)     \
    1792             :         do {                                                            \
    1793             :                 TPE *bp1 = (TPE*)Tloc(b1, 0), *bp2 = (TPE*)Tloc(b2, 0), *bs1, *be1, *bs2, v1, v2;       \
    1794             :                 for (; i < cnt; i++, rb++) {         \
    1795             :                         bs1 = bp1 + start[i];                           \
    1796             :                         be1 = bp1 + end[i];                             \
    1797             :                         bs2 = bp2 + start[i];           \
    1798             :                         for (; bs1 < be1; bs1++, bs2++) {    \
    1799             :                                 v1 = *bs1;                              \
    1800             :                                 v2 = *bs2;                              \
    1801             :                                 if (is_##TPE##_nil(v1) || is_##TPE##_nil(v2))   \
    1802             :                                         continue;               \
    1803             :                                 n++;                            \
    1804             :                                 delta1 = (dbl) v1 - mean1;              \
    1805             :                                 mean1 += delta1 / n;            \
    1806             :                                 delta2 = (dbl) v2 - mean2;              \
    1807             :                                 mean2 += delta2 / n;            \
    1808             :                                 m2 += delta1 * ((dbl) v2 - mean2);      \
    1809             :                         }       \
    1810             :                         if (isinf(m2)) {        \
    1811             :                                 goto overflow;          \
    1812             :                         } else if (n > SAMPLE) { \
    1813             :                                 *rb = OP; \
    1814             :                         } else { \
    1815             :                                 *rb = dbl_nil; \
    1816             :                                 nils++; \
    1817             :                         } \
    1818             :                         n = 0;  \
    1819             :                         mean1 = 0;      \
    1820             :                         mean2 = 0;      \
    1821             :                         m2 = 0; \
    1822             :                 }       \
    1823             :         } while (0)
    1824             : 
    1825             : #ifdef HAVE_HGE
    1826             : #define ANALYTICAL_COVARIANCE_LIMIT(SAMPLE, OP) \
    1827             :         case TYPE_hge: \
    1828             :                 ANALYTICAL_COVARIANCE_CALC(hge, SAMPLE, OP); \
    1829             :         break;
    1830             : #else
    1831             : #define ANALYTICAL_COVARIANCE_LIMIT(SAMPLE, OP)
    1832             : #endif
    1833             : 
    1834             : #define GDK_ANALYTICAL_COVARIANCE(NAME, SAMPLE, OP) \
    1835             : gdk_return \
    1836             : GDKanalytical_##NAME(BAT *r, BAT *b1, BAT *b2, BAT *s, BAT *e, int tpe) \
    1837             : { \
    1838             :         BUN i = 0, cnt = BATcount(b1), n = 0, nils = 0; \
    1839             :         lng *restrict start, *restrict end; \
    1840             :         dbl *restrict rb = (dbl *) Tloc(r, 0), mean1 = 0, mean2 = 0, m2 = 0, delta1, delta2; \
    1841             :  \
    1842             :         assert(s && e && BATcount(b1) == BATcount(b2)); \
    1843             :         start = (lng *) Tloc(s, 0); \
    1844             :         end = (lng *) Tloc(e, 0); \
    1845             :  \
    1846             :         switch (tpe) { \
    1847             :         case TYPE_bte: \
    1848             :                 ANALYTICAL_COVARIANCE_CALC(bte, SAMPLE, OP); \
    1849             :                 break; \
    1850             :         case TYPE_sht: \
    1851             :                 ANALYTICAL_COVARIANCE_CALC(sht, SAMPLE, OP); \
    1852             :                 break; \
    1853             :         case TYPE_int: \
    1854             :                 ANALYTICAL_COVARIANCE_CALC(int, SAMPLE, OP); \
    1855             :                 break; \
    1856             :         case TYPE_lng: \
    1857             :                 ANALYTICAL_COVARIANCE_CALC(lng, SAMPLE, OP); \
    1858             :                 break; \
    1859             :         ANALYTICAL_COVARIANCE_LIMIT(SAMPLE, OP) \
    1860             :         case TYPE_flt:\
    1861             :                 ANALYTICAL_COVARIANCE_CALC(flt, SAMPLE, OP); \
    1862             :                 break; \
    1863             :         case TYPE_dbl: \
    1864             :                 ANALYTICAL_COVARIANCE_CALC(dbl, SAMPLE, OP); \
    1865             :                 break; \
    1866             :         default: \
    1867             :                 GDKerror("covariance of type %s unsupported.\n", ATOMname(tpe)); \
    1868             :                 return GDK_FAIL; \
    1869             :         } \
    1870             :         BATsetcount(r, cnt); \
    1871             :         r->tnonil = nils == 0; \
    1872             :         r->tnil = nils > 0; \
    1873             :         return GDK_SUCCEED; \
    1874             :   overflow: \
    1875             :         GDKerror("22003!overflow in calculation.\n"); \
    1876             :         return GDK_FAIL; \
    1877             : }
    1878             : 
    1879        1659 : GDK_ANALYTICAL_COVARIANCE(covariance_samp, 1, m2 / (n - 1))
    1880        1656 : GDK_ANALYTICAL_COVARIANCE(covariance_pop, 0, m2 / n)
    1881             : 
    1882             : #define ANALYTICAL_CORRELATION_CALC(TPE)        \
    1883             :         do {                                                            \
    1884             :                 TPE *bp1 = (TPE*)Tloc(b1, 0), *bp2 = (TPE*)Tloc(b2, 0), *bs1, *be1, *bs2, v1, v2;       \
    1885             :                 for (; i < cnt; i++, rb++) {         \
    1886             :                         bs1 = bp1 + start[i];                           \
    1887             :                         be1 = bp1 + end[i];                             \
    1888             :                         bs2 = bp2 + start[i];           \
    1889             :                         for (; bs1 < be1; bs1++, bs2++) {    \
    1890             :                                 v1 = *bs1;                              \
    1891             :                                 v2 = *bs2;                              \
    1892             :                                 if (is_##TPE##_nil(v1) || is_##TPE##_nil(v2))   \
    1893             :                                         continue;               \
    1894             :                                 n++;    \
    1895             :                                 delta1 = (dbl) v1 - mean1;      \
    1896             :                                 mean1 += delta1 / n;    \
    1897             :                                 delta2 = (dbl) v2 - mean2;      \
    1898             :                                 mean2 += delta2 / n;    \
    1899             :                                 aux = (dbl) v2 - mean2; \
    1900             :                                 up += delta1 * aux;     \
    1901             :                                 down1 += delta1 * ((dbl) v1 - mean1);   \
    1902             :                                 down2 += delta2 * aux;  \
    1903             :                         }       \
    1904             :                         if (isinf(up) || isinf(down1) || isinf(down2)) {        \
    1905             :                                 goto overflow;  \
    1906             :                         } else if (n != 0 && down1 != 0 && down2 != 0) { \
    1907             :                                 *rb = (up / n) / (sqrt(down1 / n) * sqrt(down2 / n)); \
    1908             :                                 assert(!is_dbl_nil(*rb)); \
    1909             :                         } else { \
    1910             :                                 *rb = dbl_nil; \
    1911             :                                 nils++; \
    1912             :                         } \
    1913             :                         n = 0;  \
    1914             :                         mean1 = 0;      \
    1915             :                         mean2 = 0;      \
    1916             :                         up = 0; \
    1917             :                         down1 = 0;      \
    1918             :                         down2 = 0;      \
    1919             :                 }       \
    1920             :         } while (0)
    1921             : 
    1922             : gdk_return
    1923          26 : GDKanalytical_correlation(BAT *r, BAT *b1, BAT *b2, BAT *s, BAT *e, int tpe)
    1924             : {
    1925          26 :         BUN i = 0, cnt = BATcount(b1), n = 0, nils = 0;
    1926          26 :         lng *restrict start, *restrict end;
    1927          26 :         dbl *restrict rb = (dbl *) Tloc(r, 0), mean1 = 0, mean2 = 0, up = 0, down1 = 0, down2 = 0, delta1, delta2, aux;
    1928             : 
    1929          26 :         assert(s && e && BATcount(b1) == BATcount(b2));
    1930          26 :         start = (lng *) Tloc(s, 0);
    1931          26 :         end = (lng *) Tloc(e, 0);
    1932             : 
    1933          26 :         switch (tpe) {
    1934           4 :         case TYPE_bte:
    1935         444 :                 ANALYTICAL_CORRELATION_CALC(bte);
    1936             :                 break;
    1937           0 :         case TYPE_sht:
    1938           0 :                 ANALYTICAL_CORRELATION_CALC(sht);
    1939             :                 break;
    1940          21 :         case TYPE_int:
    1941        1485 :                 ANALYTICAL_CORRELATION_CALC(int);
    1942             :                 break;
    1943           0 :         case TYPE_lng:
    1944           0 :                 ANALYTICAL_CORRELATION_CALC(lng);
    1945             :                 break;
    1946             : #ifdef HAVE_HGE
    1947           0 :         case TYPE_hge:
    1948           0 :                 ANALYTICAL_CORRELATION_CALC(hge);
    1949             :                 break;
    1950             : #endif
    1951           0 :         case TYPE_flt:
    1952           0 :                 ANALYTICAL_CORRELATION_CALC(flt);
    1953             :                 break;
    1954           1 :         case TYPE_dbl:
    1955           3 :                 ANALYTICAL_CORRELATION_CALC(dbl);
    1956             :                 break;
    1957           0 :         default:
    1958           0 :                 GDKerror("correlation of type %s unsupported.\n", ATOMname(tpe));
    1959           0 :                 return GDK_FAIL;
    1960             :         }
    1961          25 :         BATsetcount(r, cnt);
    1962          25 :         r->tnonil = nils == 0;
    1963          25 :         r->tnil = nils > 0;
    1964          25 :         return GDK_SUCCEED;
    1965           1 :   overflow:
    1966           1 :         GDKerror("22003!overflow in calculation.\n");
    1967           1 :         return GDK_FAIL;
    1968             : }

Generated by: LCOV version 1.14