LCOV - code coverage report
Current view: top level - gdk - gdk_calc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1623 2679 60.6 %
Date: 2024-04-25 20:03:45 Functions: 58 64 90.6 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "gdk.h"
      15             : #include "gdk_private.h"
      16             : #include "gdk_calc_private.h"
      17             : 
      18             : /* Generally, the functions return a new BAT aligned with the input
      19             :  * BAT(s).  If there are multiple input BATs, they must be aligned.
      20             :  * If there is a candidate list, the calculations are only done for
      21             :  * the candidates, all other values are NIL (so that the output is
      22             :  * still aligned). */
      23             : 
      24             : static inline gdk_return
      25        3025 : checkbats(BATiter *b1i, BATiter *b2i, const char *func)
      26             : {
      27        3025 :         if (b1i->count != b2i->count) {
      28           0 :                 GDKerror("%s: inputs not the same size.\n", func);
      29           0 :                 return GDK_FAIL;
      30             :         }
      31             :         return GDK_SUCCEED;
      32             : }
      33             : 
      34             : /* ---------------------------------------------------------------------- */
      35             : /* logical (for type bit) or bitwise (for integral types) NOT */
      36             : 
      37             : #define NOT(x)          (~(x))
      38             : #define NOTBIT(x)       (!(x))
      39             : 
      40             : BAT *
      41         901 : BATcalcnot(BAT *b, BAT *s)
      42             : {
      43         901 :         lng t0 = 0;
      44         901 :         BAT *bn;
      45         901 :         BUN nils = 0;
      46         901 :         BUN i;
      47         901 :         oid x, bhseqbase;
      48         901 :         struct canditer ci;
      49             : 
      50         901 :         lng timeoffset = 0;
      51         901 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
      52         901 :         if (qry_ctx != NULL) {
      53         901 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
      54             :         }
      55             : 
      56         901 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
      57             : 
      58         901 :         BATcheck(b, NULL);
      59             : 
      60         901 :         bhseqbase = b->hseqbase;
      61         901 :         canditer_init(&ci, b, s);
      62         901 :         if (ci.ncand == 0)
      63         417 :                 return BATconstant(ci.hseq, b->ttype,
      64         417 :                                    ATOMnilptr(b->ttype), ci.ncand, TRANSIENT);
      65             : 
      66         484 :         bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
      67         484 :         if (bn == NULL)
      68             :                 return NULL;
      69             : 
      70         484 :         BATiter bi = bat_iterator(b);
      71         484 :         switch (ATOMbasetype(bi.type)) {
      72           0 :         case TYPE_msk:
      73           0 :                 if (ci.tpe == cand_dense) {
      74           0 :                         const uint32_t *restrict src = (const uint32_t *) bi.base + (ci.seq - b->hseqbase) / 32;
      75           0 :                         uint32_t *restrict dst = Tloc(bn, 0);
      76           0 :                         int bits = (ci.seq - b->hseqbase) % 32;
      77           0 :                         BUN ncand = (ci.ncand + 31) / 32;
      78           0 :                         if (bits == 0) {
      79           0 :                                 TIMEOUT_LOOP_IDX(i, ncand, timeoffset) {
      80           0 :                                         dst[i] = ~src[i];
      81             :                                 }
      82           0 :                                 TIMEOUT_CHECK(timeoffset,
      83             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
      84             :                         } else {
      85           0 :                                 TIMEOUT_LOOP_IDX(i, ncand, timeoffset) {
      86           0 :                                         dst[i] = (~src[i] >> bits) | ~(src[i + 1] >> (32 - bits));
      87             :                                 }
      88           0 :                                 TIMEOUT_CHECK(timeoffset,
      89             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
      90             :                         }
      91           0 :                         if (ci.ncand % 32 != 0)
      92           0 :                                 dst[ci.ncand / 32] &= (1U << (ci.ncand % 32)) - 1;
      93             :                 } else {
      94           0 :                         TIMEOUT_LOOP_IDX(i, ci.ncand, timeoffset) {
      95           0 :                                 x = canditer_next(&ci) - bhseqbase;
      96           0 :                                 mskSetVal(bn, i, !Tmskval(&bi, x));
      97             :                         }
      98           0 :                         TIMEOUT_CHECK(timeoffset,
      99             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout));
     100             :                 }
     101             :                 break;
     102         484 :         case TYPE_bte:
     103         484 :                 if (bi.type == TYPE_bit) {
     104     2375013 :                         UNARY_2TYPE_FUNC(bit, bit, NOTBIT);
     105             :                 } else {
     106           0 :                         UNARY_2TYPE_FUNC_nilcheck(bte, bte, NOT, ON_OVERFLOW1(bte, "NOT"));
     107             :                 }
     108             :                 break;
     109           0 :         case TYPE_sht:
     110           0 :                 UNARY_2TYPE_FUNC_nilcheck(sht, sht, NOT, ON_OVERFLOW1(sht, "NOT"));
     111             :                 break;
     112           0 :         case TYPE_int:
     113           0 :                 UNARY_2TYPE_FUNC_nilcheck(int, int, NOT, ON_OVERFLOW1(int, "NOT"));
     114             :                 break;
     115           0 :         case TYPE_lng:
     116           0 :                 UNARY_2TYPE_FUNC_nilcheck(lng, lng, NOT, ON_OVERFLOW1(lng, "NOT"));
     117             :                 break;
     118             : #ifdef HAVE_HGE
     119           0 :         case TYPE_hge:
     120           0 :                 UNARY_2TYPE_FUNC_nilcheck(hge, hge, NOT, ON_OVERFLOW1(hge, "NOT"));
     121             :                 break;
     122             : #endif
     123           0 :         default:
     124           0 :                 GDKerror("type %s not supported.\n", ATOMname(bi.type));
     125           0 :                 goto bailout;
     126             :         }
     127             : 
     128         484 :         BATsetcount(bn, ci.ncand);
     129             : 
     130             :         /* NOT reverses the order, but NILs mess it up */
     131         484 :         bn->tsorted = nils == 0 && bi.revsorted;
     132         484 :         bn->trevsorted = nils == 0 && bi.sorted;
     133         484 :         bn->tnil = nils != 0;
     134         484 :         bn->tnonil = nils == 0;
     135         484 :         bn->tkey = bi.key && nils <= 1;
     136         484 :         bat_iterator_end(&bi);
     137             : 
     138         484 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
     139             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
     140             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
     141             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
     142             : 
     143             :         return bn;
     144             : 
     145           0 : bailout:
     146           0 :         bat_iterator_end(&bi);
     147           0 :         BBPunfix(bn->batCacheid);
     148           0 :         return NULL;
     149             : }
     150             : 
     151             : gdk_return
     152     1178749 : VARcalcnot(ValPtr ret, const ValRecord *v)
     153             : {
     154     1178749 :         ret->vtype = v->vtype;
     155     1178752 :         switch (ATOMbasetype(v->vtype)) {
     156           0 :         case TYPE_msk:
     157           0 :                 ret->val.mval = !v->val.mval;
     158           0 :                 break;
     159     1178749 :         case TYPE_bte:
     160     1178749 :                 if (is_bit_nil(v->val.btval))
     161        7855 :                         ret->val.btval = bit_nil;
     162     1170894 :                 else if (v->vtype == TYPE_bit)
     163     1170891 :                         ret->val.btval = !v->val.btval;
     164             :                 else {
     165           3 :                         ret->val.btval = ~v->val.btval;
     166           3 :                         if (is_bte_nil(ret->val.btval)) {
     167           0 :                                 GDKerror("22003!overflow in calculation "
     168             :                                          "NOT(" FMTbte ").\n", v->val.btval);
     169           0 :                                 return GDK_FAIL;
     170             :                         }
     171             :                 }
     172             :                 break;
     173           0 :         case TYPE_sht:
     174           0 :                 if (is_sht_nil(v->val.shval))
     175           0 :                         ret->val.shval = sht_nil;
     176             :                 else {
     177           0 :                         ret->val.shval = ~v->val.shval;
     178           0 :                         if (is_sht_nil(ret->val.shval)) {
     179           0 :                                 GDKerror("22003!overflow in calculation "
     180             :                                          "NOT(" FMTsht ").\n", v->val.shval);
     181           0 :                                 return GDK_FAIL;
     182             :                         }
     183             :                 }
     184             :                 break;
     185           0 :         case TYPE_int:
     186           0 :                 if (is_int_nil(v->val.ival))
     187           0 :                         ret->val.ival = int_nil;
     188             :                 else {
     189           0 :                         ret->val.ival = ~v->val.ival;
     190           0 :                         if (is_int_nil(ret->val.ival)) {
     191           0 :                                 GDKerror("22003!overflow in calculation "
     192             :                                          "NOT(" FMTint ").\n", v->val.ival);
     193           0 :                                 return GDK_FAIL;
     194             :                         }
     195             :                 }
     196             :                 break;
     197           0 :         case TYPE_lng:
     198           0 :                 if (is_lng_nil(v->val.lval))
     199           0 :                         ret->val.lval = lng_nil;
     200             :                 else {
     201           0 :                         ret->val.lval = ~v->val.lval;
     202           0 :                         if (is_lng_nil(ret->val.lval)) {
     203           0 :                                 GDKerror("22003!overflow in calculation "
     204             :                                          "NOT(" FMTlng ").\n", v->val.lval);
     205           0 :                                 return GDK_FAIL;
     206             :                         }
     207             :                 }
     208             :                 break;
     209             : #ifdef HAVE_HGE
     210           0 :         case TYPE_hge:
     211           0 :                 if (is_hge_nil(v->val.hval))
     212           0 :                         ret->val.hval = hge_nil;
     213             :                 else {
     214           0 :                         ret->val.hval = ~v->val.hval;
     215           0 :                         if (is_hge_nil(ret->val.hval)) {
     216           0 :                                 GDKerror("22003!overflow in calculation "
     217             :                                          "NOT(" FMThge ").\n",
     218             :                                          CSThge v->val.hval);
     219           0 :                                 return GDK_FAIL;
     220             :                         }
     221             :                 }
     222             :                 break;
     223             : #endif
     224           0 :         default:
     225           0 :                 GDKerror("bad input type %s.\n", ATOMname(v->vtype));
     226           0 :                 return GDK_FAIL;
     227             :         }
     228             :         return GDK_SUCCEED;
     229             : }
     230             : 
     231             : /* ---------------------------------------------------------------------- */
     232             : /* negate value (any numeric type) */
     233             : 
     234             : #define NEGATE(x)       (-(x))
     235             : 
     236             : BAT *
     237         201 : BATcalcnegate(BAT *b, BAT *s)
     238             : {
     239         201 :         lng t0 = 0;
     240         201 :         BAT *bn;
     241         201 :         BUN nils = 0;
     242         201 :         BUN i;
     243         201 :         oid x, bhseqbase;
     244         201 :         struct canditer ci;
     245             : 
     246         201 :         lng timeoffset = 0;
     247         201 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     248         201 :         if (qry_ctx != NULL) {
     249         201 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
     250             :         }
     251             : 
     252             : 
     253         201 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
     254             : 
     255         201 :         BATcheck(b, NULL);
     256             : 
     257         201 :         bhseqbase = b->hseqbase;
     258         201 :         canditer_init(&ci, b, s);
     259         201 :         if (ci.ncand == 0)
     260          22 :                 return BATconstant(ci.hseq, b->ttype,
     261          22 :                                    ATOMnilptr(b->ttype), ci.ncand, TRANSIENT);
     262             : 
     263         179 :         bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
     264         179 :         if (bn == NULL)
     265             :                 return NULL;
     266             : 
     267         179 :         BATiter bi = bat_iterator(b);
     268         358 :         switch (ATOMbasetype(bi.type)) {
     269           7 :         case TYPE_bte:
     270          94 :                 UNARY_2TYPE_FUNC(bte, bte, NEGATE);
     271             :                 break;
     272           5 :         case TYPE_sht:
     273         117 :                 UNARY_2TYPE_FUNC(sht, sht, NEGATE);
     274             :                 break;
     275         102 :         case TYPE_int:
     276         667 :                 UNARY_2TYPE_FUNC(int, int, NEGATE);
     277             :                 break;
     278          23 :         case TYPE_lng:
     279         322 :                 UNARY_2TYPE_FUNC(lng, lng, NEGATE);
     280             :                 break;
     281             : #ifdef HAVE_HGE
     282          22 :         case TYPE_hge:
     283         355 :                 UNARY_2TYPE_FUNC(hge, hge, NEGATE);
     284             :                 break;
     285             : #endif
     286           0 :         case TYPE_flt:
     287           0 :                 UNARY_2TYPE_FUNC(flt, flt, NEGATE);
     288             :                 break;
     289          20 :         case TYPE_dbl:
     290         141 :                 UNARY_2TYPE_FUNC(dbl, dbl, NEGATE);
     291             :                 break;
     292           0 :         default:
     293           0 :                 GDKerror("type %s not supported.\n", ATOMname(bi.type));
     294           0 :                 goto bailout;
     295             :         }
     296             : 
     297         179 :         BATsetcount(bn, ci.ncand);
     298             : 
     299             :         /* unary - reverses the order, but NILs mess it up */
     300         179 :         bn->tsorted = nils == 0 && bi.revsorted;
     301         179 :         bn->trevsorted = nils == 0 && bi.sorted;
     302         179 :         bn->tnil = nils != 0;
     303         179 :         bn->tnonil = nils == 0;
     304         179 :         bn->tkey = bi.key && nils <= 1;
     305         179 :         bat_iterator_end(&bi);
     306             : 
     307         179 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
     308             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
     309             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
     310             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
     311             : 
     312             :         return bn;
     313           0 : bailout:
     314           0 :         bat_iterator_end(&bi);
     315           0 :         BBPunfix(bn->batCacheid);
     316           0 :         return NULL;
     317             : }
     318             : 
     319             : gdk_return
     320        9274 : VARcalcnegate(ValPtr ret, const ValRecord *v)
     321             : {
     322        9274 :         ret->vtype = v->vtype;
     323       18548 :         switch (ATOMbasetype(v->vtype)) {
     324        6663 :         case TYPE_bte:
     325        6663 :                 if (is_bte_nil(v->val.btval))
     326           4 :                         ret->val.btval = bte_nil;
     327             :                 else
     328        6659 :                         ret->val.btval = -v->val.btval;
     329             :                 break;
     330         283 :         case TYPE_sht:
     331         283 :                 if (is_sht_nil(v->val.shval))
     332           1 :                         ret->val.shval = sht_nil;
     333             :                 else
     334         282 :                         ret->val.shval = -v->val.shval;
     335             :                 break;
     336         835 :         case TYPE_int:
     337         835 :                 if (is_int_nil(v->val.ival))
     338          11 :                         ret->val.ival = int_nil;
     339             :                 else
     340         824 :                         ret->val.ival = -v->val.ival;
     341             :                 break;
     342        1297 :         case TYPE_lng:
     343        1297 :                 if (is_lng_nil(v->val.lval))
     344           5 :                         ret->val.lval = lng_nil;
     345             :                 else
     346        1292 :                         ret->val.lval = -v->val.lval;
     347             :                 break;
     348             : #ifdef HAVE_HGE
     349          90 :         case TYPE_hge:
     350          90 :                 if (is_hge_nil(v->val.hval))
     351           4 :                         ret->val.hval = hge_nil;
     352             :                 else
     353          86 :                         ret->val.hval = -v->val.hval;
     354             :                 break;
     355             : #endif
     356           8 :         case TYPE_flt:
     357           8 :                 if (is_flt_nil(v->val.fval))
     358           8 :                         ret->val.fval = flt_nil;
     359             :                 else
     360           0 :                         ret->val.fval = -v->val.fval;
     361             :                 break;
     362          98 :         case TYPE_dbl:
     363          98 :                 if (is_dbl_nil(v->val.dval))
     364           2 :                         ret->val.dval = dbl_nil;
     365             :                 else
     366          96 :                         ret->val.dval = -v->val.dval;
     367             :                 break;
     368           0 :         default:
     369           0 :                 GDKerror("bad input type %s.\n", ATOMname(v->vtype));
     370           0 :                 return GDK_FAIL;
     371             :         }
     372             :         return GDK_SUCCEED;
     373             : }
     374             : 
     375             : /* ---------------------------------------------------------------------- */
     376             : /* absolute value (any numeric type) */
     377             : 
     378             : BAT *
     379        4519 : BATcalcabsolute(BAT *b, BAT *s)
     380             : {
     381        4519 :         lng t0 = 0;
     382        4519 :         BAT *bn;
     383        4519 :         BUN nils = 0;
     384        4519 :         BUN i;
     385        4519 :         oid x, bhseqbase;
     386        4519 :         struct canditer ci;
     387             : 
     388        4519 :         lng timeoffset = 0;
     389        4519 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     390        4519 :         if (qry_ctx != NULL) {
     391        4519 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
     392             :         }
     393             : 
     394             : 
     395        4519 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
     396             : 
     397        4519 :         BATcheck(b, NULL);
     398             : 
     399        4519 :         bhseqbase = b->hseqbase;
     400        4519 :         canditer_init(&ci, b, s);
     401        4519 :         if (ci.ncand == 0)
     402         735 :                 return BATconstant(ci.hseq, b->ttype,
     403         735 :                                    ATOMnilptr(b->ttype), ci.ncand, TRANSIENT);
     404             : 
     405        3784 :         bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
     406        3784 :         if (bn == NULL)
     407             :                 return NULL;
     408             : 
     409        3784 :         BATiter bi = bat_iterator(b);
     410        7568 :         switch (ATOMbasetype(bi.type)) {
     411           2 :         case TYPE_bte:
     412           9 :                 UNARY_2TYPE_FUNC(bte, bte, (bte) abs);
     413             :                 break;
     414           4 :         case TYPE_sht:
     415          17 :                 UNARY_2TYPE_FUNC(sht, sht, (sht) abs);
     416             :                 break;
     417        1800 :         case TYPE_int:
     418       21614 :                 UNARY_2TYPE_FUNC(int, int, abs);
     419             :                 break;
     420        1963 :         case TYPE_lng:
     421       22973 :                 UNARY_2TYPE_FUNC(lng, lng, llabs);
     422             :                 break;
     423             : #ifdef HAVE_HGE
     424           5 :         case TYPE_hge:
     425       85518 :                 UNARY_2TYPE_FUNC(hge, hge, ABSOLUTE);
     426             :                 break;
     427             : #endif
     428           1 :         case TYPE_flt:
     429          10 :                 UNARY_2TYPE_FUNC(flt, flt, fabsf);
     430             :                 break;
     431           9 :         case TYPE_dbl:
     432          60 :                 UNARY_2TYPE_FUNC(dbl, dbl, fabs);
     433             :                 break;
     434           0 :         default:
     435           0 :                 GDKerror("bad input type %s.\n", ATOMname(bi.type));
     436           0 :                 goto bailout;
     437             :         }
     438        3784 :         bat_iterator_end(&bi);
     439             : 
     440        3784 :         BATsetcount(bn, ci.ncand);
     441             : 
     442             :         /* ABSOLUTE messes up order (unless all values were negative
     443             :          * or all values were positive, but we don't know anything
     444             :          * about that) */
     445        3784 :         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
     446        3784 :         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
     447        3784 :         bn->tkey = ci.ncand <= 1;
     448        3784 :         bn->tnil = nils != 0;
     449        3784 :         bn->tnonil = nils == 0;
     450             : 
     451        3784 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
     452             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
     453             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
     454             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
     455             : 
     456             :         return bn;
     457           0 : bailout:
     458           0 :         bat_iterator_end(&bi);
     459           0 :         BBPunfix(bn->batCacheid);
     460           0 :         return NULL;
     461             : }
     462             : 
     463             : gdk_return
     464         260 : VARcalcabsolute(ValPtr ret, const ValRecord *v)
     465             : {
     466         260 :         ret->vtype = v->vtype;
     467         520 :         switch (ATOMbasetype(v->vtype)) {
     468          28 :         case TYPE_bte:
     469          28 :                 if (is_bte_nil(v->val.btval))
     470           3 :                         ret->val.btval = bte_nil;
     471             :                 else
     472          25 :                         ret->val.btval = (bte) abs(v->val.btval);
     473             :                 break;
     474          10 :         case TYPE_sht:
     475          10 :                 if (is_sht_nil(v->val.shval))
     476           0 :                         ret->val.shval = sht_nil;
     477             :                 else
     478          10 :                         ret->val.shval = (sht) abs(v->val.shval);
     479             :                 break;
     480          20 :         case TYPE_int:
     481          20 :                 if (is_int_nil(v->val.ival))
     482           0 :                         ret->val.ival = int_nil;
     483             :                 else
     484          20 :                         ret->val.ival = abs(v->val.ival);
     485             :                 break;
     486         196 :         case TYPE_lng:
     487         196 :                 if (is_lng_nil(v->val.lval))
     488           0 :                         ret->val.lval = lng_nil;
     489             :                 else
     490         196 :                         ret->val.lval = llabs(v->val.lval);
     491             :                 break;
     492             : #ifdef HAVE_HGE
     493           0 :         case TYPE_hge:
     494           0 :                 if (is_hge_nil(v->val.hval))
     495           0 :                         ret->val.hval = hge_nil;
     496             :                 else
     497           0 :                         ret->val.hval = ABSOLUTE(v->val.hval);
     498             :                 break;
     499             : #endif
     500           1 :         case TYPE_flt:
     501           1 :                 if (is_flt_nil(v->val.fval))
     502           0 :                         ret->val.fval = flt_nil;
     503             :                 else
     504           1 :                         ret->val.fval = fabsf(v->val.fval);
     505             :                 break;
     506           5 :         case TYPE_dbl:
     507           5 :                 if (is_dbl_nil(v->val.dval))
     508           0 :                         ret->val.dval = dbl_nil;
     509             :                 else
     510           5 :                         ret->val.dval = fabs(v->val.dval);
     511             :                 break;
     512           0 :         default:
     513           0 :                 GDKerror("bad input type %s.\n", ATOMname(v->vtype));
     514           0 :                 return GDK_FAIL;
     515             :         }
     516             :         return GDK_SUCCEED;
     517             : }
     518             : 
     519             : /* ---------------------------------------------------------------------- */
     520             : /* is the value equal to zero (any numeric type) */
     521             : 
     522             : #define ISZERO(x)               ((bit) ((x) == 0))
     523             : 
     524             : BAT *
     525           0 : BATcalciszero(BAT *b, BAT *s)
     526             : {
     527           0 :         lng t0 = 0;
     528           0 :         BAT *bn;
     529           0 :         BUN nils = 0;
     530           0 :         BUN i;
     531           0 :         oid x, bhseqbase;
     532           0 :         struct canditer ci;
     533             : 
     534           0 :         lng timeoffset = 0;
     535           0 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     536           0 :         if (qry_ctx != NULL) {
     537           0 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
     538             :         }
     539             : 
     540           0 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
     541             : 
     542           0 :         BATcheck(b, NULL);
     543             : 
     544           0 :         bhseqbase = b->hseqbase;
     545           0 :         canditer_init(&ci, b, s);
     546           0 :         if (ci.ncand == 0)
     547           0 :                 return BATconstant(ci.hseq, TYPE_bit,
     548             :                                    ATOMnilptr(TYPE_bit), ci.ncand, TRANSIENT);
     549             : 
     550           0 :         bn = COLnew(ci.hseq, TYPE_bit, ci.ncand, TRANSIENT);
     551           0 :         if (bn == NULL)
     552             :                 return NULL;
     553             : 
     554           0 :         BATiter bi = bat_iterator(b);
     555           0 :         switch (ATOMbasetype(bi.type)) {
     556           0 :         case TYPE_bte:
     557           0 :                 UNARY_2TYPE_FUNC(bte, bit, ISZERO);
     558             :                 break;
     559           0 :         case TYPE_sht:
     560           0 :                 UNARY_2TYPE_FUNC(sht, bit, ISZERO);
     561             :                 break;
     562           0 :         case TYPE_int:
     563           0 :                 UNARY_2TYPE_FUNC(int, bit, ISZERO);
     564             :                 break;
     565           0 :         case TYPE_lng:
     566           0 :                 UNARY_2TYPE_FUNC(lng, bit, ISZERO);
     567             :                 break;
     568             : #ifdef HAVE_HGE
     569           0 :         case TYPE_hge:
     570           0 :                 UNARY_2TYPE_FUNC(hge, bit, ISZERO);
     571             :                 break;
     572             : #endif
     573           0 :         case TYPE_flt:
     574           0 :                 UNARY_2TYPE_FUNC(flt, bit, ISZERO);
     575             :                 break;
     576           0 :         case TYPE_dbl:
     577           0 :                 UNARY_2TYPE_FUNC(dbl, bit, ISZERO);
     578             :                 break;
     579           0 :         default:
     580           0 :                 GDKerror("bad input type %s.\n", ATOMname(bi.type));
     581           0 :                 goto bailout;
     582             :         }
     583           0 :         bat_iterator_end(&bi);
     584             : 
     585           0 :         BATsetcount(bn, ci.ncand);
     586             : 
     587           0 :         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
     588           0 :         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
     589           0 :         bn->tkey = ci.ncand <= 1;
     590           0 :         bn->tnil = nils != 0;
     591           0 :         bn->tnonil = nils == 0;
     592             : 
     593           0 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
     594             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
     595             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
     596             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
     597             : 
     598             :         return bn;
     599           0 : bailout:
     600           0 :         bat_iterator_end(&bi);
     601           0 :         BBPunfix(bn->batCacheid);
     602           0 :         return NULL;
     603             : }
     604             : 
     605             : gdk_return
     606           0 : VARcalciszero(ValPtr ret, const ValRecord *v)
     607             : {
     608           0 :         ret->vtype = TYPE_bit;
     609           0 :         switch (ATOMbasetype(v->vtype)) {
     610           0 :         case TYPE_bte:
     611           0 :                 if (is_bte_nil(v->val.btval))
     612           0 :                         ret->val.btval = bit_nil;
     613             :                 else
     614           0 :                         ret->val.btval = ISZERO(v->val.btval);
     615             :                 break;
     616           0 :         case TYPE_sht:
     617           0 :                 if (is_sht_nil(v->val.shval))
     618           0 :                         ret->val.btval = bit_nil;
     619             :                 else
     620           0 :                         ret->val.btval = ISZERO(v->val.shval);
     621             :                 break;
     622           0 :         case TYPE_int:
     623           0 :                 if (is_int_nil(v->val.ival))
     624           0 :                         ret->val.btval = bit_nil;
     625             :                 else
     626           0 :                         ret->val.btval = ISZERO(v->val.ival);
     627             :                 break;
     628           0 :         case TYPE_lng:
     629           0 :                 if (is_lng_nil(v->val.lval))
     630           0 :                         ret->val.btval = bit_nil;
     631             :                 else
     632           0 :                         ret->val.btval = ISZERO(v->val.lval);
     633             :                 break;
     634             : #ifdef HAVE_HGE
     635           0 :         case TYPE_hge:
     636           0 :                 if (is_hge_nil(v->val.hval))
     637           0 :                         ret->val.btval = bit_nil;
     638             :                 else
     639           0 :                         ret->val.btval = ISZERO(v->val.hval);
     640             :                 break;
     641             : #endif
     642           0 :         case TYPE_flt:
     643           0 :                 if (is_flt_nil(v->val.fval))
     644           0 :                         ret->val.btval = bit_nil;
     645             :                 else
     646           0 :                         ret->val.btval = ISZERO(v->val.fval);
     647             :                 break;
     648           0 :         case TYPE_dbl:
     649           0 :                 if (is_dbl_nil(v->val.dval))
     650           0 :                         ret->val.btval = bit_nil;
     651             :                 else
     652           0 :                         ret->val.btval = ISZERO(v->val.dval);
     653             :                 break;
     654           0 :         default:
     655           0 :                 GDKerror("bad input type %s.\n", ATOMname(v->vtype));
     656           0 :                 return GDK_FAIL;
     657             :         }
     658             :         return GDK_SUCCEED;
     659             : }
     660             : 
     661             : /* ---------------------------------------------------------------------- */
     662             : /* sign of value (-1 for negative, 0 for 0, +1 for positive; any
     663             :  * numeric type) */
     664             : 
     665             : #define SIGN(x)         ((bte) ((x) < 0 ? -1 : (x) > 0))
     666             : 
     667             : BAT *
     668          14 : BATcalcsign(BAT *b, BAT *s)
     669             : {
     670          14 :         lng t0 = 0;
     671          14 :         BAT *bn;
     672          14 :         BUN nils = 0;
     673          14 :         BUN i;
     674          14 :         oid x, bhseqbase;
     675          14 :         struct canditer ci;
     676             : 
     677          14 :         lng timeoffset = 0;
     678          14 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     679          14 :         if (qry_ctx != NULL) {
     680          14 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
     681             :         }
     682             : 
     683          14 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
     684             : 
     685          14 :         BATcheck(b, NULL);
     686             : 
     687          14 :         bhseqbase = b->hseqbase;
     688          14 :         canditer_init(&ci, b, s);
     689          14 :         if (ci.ncand == 0)
     690           0 :                 return BATconstant(ci.hseq, TYPE_bte,
     691             :                                    ATOMnilptr(TYPE_bte), ci.ncand, TRANSIENT);
     692             : 
     693          14 :         bn = COLnew(ci.hseq, TYPE_bte, ci.ncand, TRANSIENT);
     694          14 :         if (bn == NULL)
     695             :                 return NULL;
     696             : 
     697          14 :         BATiter bi = bat_iterator(b);
     698          28 :         switch (ATOMbasetype(bi.type)) {
     699           1 :         case TYPE_bte:
     700           9 :                 UNARY_2TYPE_FUNC(bte, bte, SIGN);
     701             :                 break;
     702           1 :         case TYPE_sht:
     703           9 :                 UNARY_2TYPE_FUNC(sht, bte, SIGN);
     704             :                 break;
     705           6 :         case TYPE_int:
     706          33 :                 UNARY_2TYPE_FUNC(int, bte, SIGN);
     707             :                 break;
     708           2 :         case TYPE_lng:
     709          18 :                 UNARY_2TYPE_FUNC(lng, bte, SIGN);
     710             :                 break;
     711             : #ifdef HAVE_HGE
     712           0 :         case TYPE_hge:
     713           0 :                 UNARY_2TYPE_FUNC(hge, bte, SIGN);
     714             :                 break;
     715             : #endif
     716           1 :         case TYPE_flt:
     717          10 :                 UNARY_2TYPE_FUNC(flt, bte, SIGN);
     718             :                 break;
     719           3 :         case TYPE_dbl:
     720          17 :                 UNARY_2TYPE_FUNC(dbl, bte, SIGN);
     721             :                 break;
     722           0 :         default:
     723           0 :                 GDKerror("bad input type %s.\n", ATOMname(bi.type));
     724           0 :                 goto bailout;
     725             :         }
     726             : 
     727          14 :         BATsetcount(bn, ci.ncand);
     728             : 
     729             :         /* SIGN is ordered if the input is ordered (negative comes
     730             :          * first, positive comes after) and NILs stay in the same
     731             :          * position */
     732          14 :         bn->tsorted = bi.sorted || ci.ncand <= 1 || nils == ci.ncand;
     733          14 :         bn->trevsorted = bi.revsorted || ci.ncand <= 1 || nils == ci.ncand;
     734          14 :         bn->tkey = ci.ncand <= 1;
     735          14 :         bn->tnil = nils != 0;
     736          14 :         bn->tnonil = nils == 0;
     737          14 :         bat_iterator_end(&bi);
     738             : 
     739          14 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
     740             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
     741             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
     742             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
     743             : 
     744             :         return bn;
     745           0 : bailout:
     746           0 :         bat_iterator_end(&bi);
     747           0 :         BBPunfix(bn->batCacheid);
     748           0 :         return NULL;
     749             : }
     750             : 
     751             : gdk_return
     752       22327 : VARcalcsign(ValPtr ret, const ValRecord *v)
     753             : {
     754       22327 :         ret->vtype = TYPE_bte;
     755       44654 :         switch (ATOMbasetype(v->vtype)) {
     756       18891 :         case TYPE_bte:
     757       18891 :                 if (is_bte_nil(v->val.btval))
     758           0 :                         ret->val.btval = bte_nil;
     759             :                 else
     760       18891 :                         ret->val.btval = SIGN(v->val.btval);
     761             :                 break;
     762        2189 :         case TYPE_sht:
     763        2189 :                 if (is_sht_nil(v->val.shval))
     764           0 :                         ret->val.btval = bte_nil;
     765             :                 else
     766        2189 :                         ret->val.btval = SIGN(v->val.shval);
     767             :                 break;
     768         120 :         case TYPE_int:
     769         120 :                 if (is_int_nil(v->val.ival))
     770           6 :                         ret->val.btval = bte_nil;
     771             :                 else
     772         114 :                         ret->val.btval = SIGN(v->val.ival);
     773             :                 break;
     774        1013 :         case TYPE_lng:
     775        1013 :                 if (is_lng_nil(v->val.lval))
     776           0 :                         ret->val.btval = bte_nil;
     777             :                 else
     778        1013 :                         ret->val.btval = SIGN(v->val.lval);
     779             :                 break;
     780             : #ifdef HAVE_HGE
     781          31 :         case TYPE_hge:
     782          31 :                 if (is_hge_nil(v->val.hval))
     783           0 :                         ret->val.btval = bte_nil;
     784             :                 else
     785          31 :                         ret->val.btval = SIGN(v->val.hval);
     786             :                 break;
     787             : #endif
     788           7 :         case TYPE_flt:
     789           7 :                 if (is_flt_nil(v->val.fval))
     790           1 :                         ret->val.btval = bte_nil;
     791             :                 else
     792           6 :                         ret->val.btval = SIGN(v->val.fval);
     793             :                 break;
     794          76 :         case TYPE_dbl:
     795          76 :                 if (is_dbl_nil(v->val.dval))
     796           0 :                         ret->val.btval = bte_nil;
     797             :                 else
     798          76 :                         ret->val.btval = SIGN(v->val.dval);
     799             :                 break;
     800           0 :         default:
     801           0 :                 GDKerror("bad input type %s.\n",
     802             :                          ATOMname(v->vtype));
     803           0 :                 return GDK_FAIL;
     804             :         }
     805             :         return GDK_SUCCEED;
     806             : }
     807             : 
     808             : /* ---------------------------------------------------------------------- */
     809             : /* is the value nil (any type) */
     810             : 
     811             : #define ISNIL_TYPE(TYPE, NOTNIL)                                        \
     812             :         do {                                                            \
     813             :                 const TYPE *restrict src = (const TYPE *) bi.base;      \
     814             :                 TIMEOUT_LOOP_IDX(i, ci.ncand, timeoffset) {             \
     815             :                         x = canditer_next(&ci) - bhseqbase;         \
     816             :                         dst[i] = (bit) (is_##TYPE##_nil(src[x]) ^ NOTNIL); \
     817             :                 }                                                       \
     818             :                 TIMEOUT_CHECK(timeoffset, GOTO_LABEL_TIMEOUT_HANDLER(bailout)); \
     819             :         } while (0)
     820             : 
     821             : static BAT *
     822        6540 : BATcalcisnil_implementation(BAT *b, BAT *s, bool notnil)
     823             : {
     824        6540 :         lng t0 = 0;
     825        6540 :         BAT *bn;
     826        6540 :         BUN i;
     827        6540 :         oid x;
     828        6540 :         struct canditer ci;
     829        6540 :         bit *restrict dst;
     830        6540 :         BUN nils = 0;
     831        6540 :         oid bhseqbase;
     832             : 
     833        6540 :         lng timeoffset = 0;
     834        6540 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     835        6540 :         if (qry_ctx != NULL) {
     836        6540 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
     837             :         }
     838             : 
     839        6540 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
     840             : 
     841        6540 :         BATcheck(b, NULL);
     842             : 
     843        6540 :         bhseqbase = b->hseqbase;
     844        6540 :         canditer_init(&ci, b, s);
     845             : 
     846        6541 :         if (b->tnonil || BATtdense(b)) {
     847        1593 :                 return BATconstant(ci.hseq, TYPE_bit, &(bit){notnil},
     848             :                                    ci.ncand, TRANSIENT);
     849        4948 :         } else if (b->ttype == TYPE_void) {
     850             :                 /* non-nil handled above */
     851          33 :                 assert(is_oid_nil(b->tseqbase));
     852          33 :                 return BATconstant(ci.hseq, TYPE_bit, &(bit){!notnil},
     853             :                                    ci.ncand, TRANSIENT);
     854             :         }
     855             : 
     856        4915 :         bn = COLnew(ci.hseq, TYPE_bit, ci.ncand, TRANSIENT);
     857        4915 :         if (bn == NULL)
     858             :                 return NULL;
     859             : 
     860        4915 :         dst = (bit *) Tloc(bn, 0);
     861             : 
     862        4915 :         BATiter bi = bat_iterator(b);
     863        9457 :         switch (ATOMbasetype(bi.type)) {
     864         715 :         case TYPE_bte:
     865    35733693 :                 ISNIL_TYPE(bte, notnil);
     866             :                 break;
     867          84 :         case TYPE_sht:
     868     8999800 :                 ISNIL_TYPE(sht, notnil);
     869             :                 break;
     870        1786 :         case TYPE_int:
     871    11357790 :                 ISNIL_TYPE(int, notnil);
     872             :                 break;
     873        1978 :         case TYPE_lng:
     874    24057830 :                 ISNIL_TYPE(lng, notnil);
     875             :                 break;
     876             : #ifdef HAVE_HGE
     877          71 :         case TYPE_hge:
     878     6069589 :                 ISNIL_TYPE(hge, notnil);
     879             :                 break;
     880             : #endif
     881           5 :         case TYPE_flt:
     882          30 :                 ISNIL_TYPE(flt, notnil);
     883             :                 break;
     884          27 :         case TYPE_dbl:
     885         325 :                 ISNIL_TYPE(dbl, notnil);
     886             :                 break;
     887           1 :         case TYPE_uuid:
     888           6 :                 ISNIL_TYPE(uuid, notnil);
     889             :                 break;
     890         248 :         default:
     891             :         {
     892         248 :                 int (*atomcmp)(const void *, const void *) = ATOMcompare(bi.type);
     893         248 :                 const void *nil = ATOMnilptr(bi.type);
     894             : 
     895     7506127 :                 TIMEOUT_LOOP_IDX(i, ci.ncand, timeoffset) {
     896     7504911 :                         x = canditer_next(&ci) - bhseqbase;
     897     7504930 :                         dst[i] = (bit) (((*atomcmp)(BUNtail(bi, x), nil) == 0) ^ notnil);
     898             :                 }
     899         248 :                 TIMEOUT_CHECK(timeoffset, GOTO_LABEL_TIMEOUT_HANDLER(bailout));
     900             :                 break;
     901             :         }
     902             :         }
     903             : 
     904        4912 :         BATsetcount(bn, ci.ncand);
     905             : 
     906             :         /* If b sorted, all nils are at the start, i.e. bn starts with
     907             :          * 1's and ends with 0's, hence bn is revsorted.  Similarly
     908             :          * for revsorted. At the notnil case, these properties remain the same */
     909        4912 :         if (notnil) {
     910        2420 :                 bn->tsorted = bi.sorted;
     911        2420 :                 bn->trevsorted = bi.revsorted;
     912             :         } else {
     913        2492 :                 bn->tsorted = bi.revsorted;
     914        2492 :                 bn->trevsorted = bi.sorted;
     915             :         }
     916        4912 :         bn->tnil = nils != 0;
     917        4912 :         bn->tnonil = nils == 0;
     918        4912 :         bn->tkey = ci.ncand <= 1;
     919        4912 :         bat_iterator_end(&bi);
     920             : 
     921        4915 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
     922             :                   ",notnil=%s -> " ALGOOPTBATFMT " " LLFMT "usec\n",
     923             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
     924             :                   notnil ? "true" : "false", ALGOOPTBATPAR(bn), GDKusec() - t0);
     925             : 
     926             :         return bn;
     927           0 : bailout:
     928           0 :         bat_iterator_end(&bi);
     929           0 :         BBPreclaim(bn);
     930           0 :         return NULL;
     931             : }
     932             : 
     933             : BAT *
     934        3674 : BATcalcisnil(BAT *b, BAT *s)
     935             : {
     936        3674 :         return BATcalcisnil_implementation(b, s, false);
     937             : }
     938             : 
     939             : BAT *
     940        2867 : BATcalcisnotnil(BAT *b, BAT *s)
     941             : {
     942        2867 :         return BATcalcisnil_implementation(b, s, true);
     943             : }
     944             : 
     945             : gdk_return
     946     1195963 : VARcalcisnil(ValPtr ret, const ValRecord *v)
     947             : {
     948     1195963 :         ret->vtype = TYPE_bit;
     949     1195963 :         ret->val.btval = (bit) VALisnil(v);
     950     1195963 :         return GDK_SUCCEED;
     951             : }
     952             : 
     953             : gdk_return
     954         383 : VARcalcisnotnil(ValPtr ret, const ValRecord *v)
     955             : {
     956         383 :         ret->vtype = TYPE_bit;
     957         383 :         ret->val.btval = (bit) !VALisnil(v);
     958         383 :         return GDK_SUCCEED;
     959             : }
     960             : 
     961             : #define MINMAX_TYPE(TYPE, OP)                                           \
     962             :         do {                                                            \
     963             :                 TYPE *tb1 = b1i.base, *tb2 = b2i.base, *restrict tbn = Tloc(bn, 0); \
     964             :                 if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {   \
     965             :                         TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) { \
     966             :                                 oid x1 = canditer_next_dense(&ci1) - b1hseqbase; \
     967             :                                 oid x2 = canditer_next_dense(&ci2) - b2hseqbase; \
     968             :                                 TYPE p1 = tb1[x1], p2 = tb2[x2];        \
     969             :                                 if (is_##TYPE##_nil(p1) || is_##TYPE##_nil(p2)) { \
     970             :                                         nils = true;                    \
     971             :                                         tbn[i] = TYPE##_nil;            \
     972             :                                 } else {                                \
     973             :                                         tbn[i] = p1 OP p2 ? p1 : p2;    \
     974             :                                 }                                       \
     975             :                         }                                               \
     976             :                         TIMEOUT_CHECK(timeoffset,                       \
     977             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout)); \
     978             :                 } else {                                                \
     979             :                         TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) { \
     980             :                                 oid x1 = canditer_next(&ci1) - b1hseqbase; \
     981             :                                 oid x2 = canditer_next(&ci2) - b2hseqbase; \
     982             :                                 TYPE p1 = tb1[x1], p2 = tb2[x2];        \
     983             :                                 if (is_##TYPE##_nil(p1) || is_##TYPE##_nil(p2)) { \
     984             :                                         nils = true;                    \
     985             :                                         tbn[i] = TYPE##_nil;            \
     986             :                                 } else {                                \
     987             :                                         tbn[i] = p1 OP p2 ? p1 : p2;    \
     988             :                                 }                                       \
     989             :                         }                                               \
     990             :                         TIMEOUT_CHECK(timeoffset,                       \
     991             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout)); \
     992             :                 }                                                       \
     993             :         } while (0)
     994             : 
     995             : BAT *
     996         382 : BATcalcmin(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
     997             : {
     998         382 :         lng t0 = 0;
     999         382 :         BAT *bn;
    1000         382 :         bool nils = false;
    1001         382 :         struct canditer ci1, ci2;
    1002         382 :         oid b1hseqbase, b2hseqbase;
    1003             : 
    1004         382 :         lng timeoffset = 0;
    1005         382 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    1006         382 :         if (qry_ctx != NULL) {
    1007         382 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    1008             :         }
    1009             : 
    1010         382 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    1011             : 
    1012         382 :         BATcheck(b1, NULL);
    1013         382 :         BATcheck(b2, NULL);
    1014             : 
    1015         382 :         b1hseqbase = b1->hseqbase;
    1016         382 :         b2hseqbase = b2->hseqbase;
    1017        1146 :         if (ATOMtype(b1->ttype) != ATOMtype(b2->ttype)) {
    1018           0 :                 GDKerror("inputs have incompatible types\n");
    1019           0 :                 return NULL;
    1020             :         }
    1021             : 
    1022         382 :         canditer_init(&ci1, b1, s1);
    1023         382 :         canditer_init(&ci2, b2, s2);
    1024         382 :         if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
    1025           0 :                 GDKerror("inputs not the same size.\n");
    1026           0 :                 return NULL;
    1027             :         }
    1028             : 
    1029         764 :         bn = COLnew(ci1.hseq, ATOMtype(b1->ttype), ci1.ncand, TRANSIENT);
    1030         382 :         if (bn == NULL)
    1031             :                 return NULL;
    1032             : 
    1033         382 :         BATiter b1i = bat_iterator(b1);
    1034         382 :         BATiter b2i = bat_iterator(b2);
    1035         762 :         switch (ATOMbasetype(b1i.type)) {
    1036           1 :         case TYPE_bte:
    1037           4 :                 MINMAX_TYPE(bte, <);
    1038             :                 break;
    1039           0 :         case TYPE_sht:
    1040           0 :                 MINMAX_TYPE(sht, <);
    1041             :                 break;
    1042           6 :         case TYPE_int:
    1043          28 :                 MINMAX_TYPE(int, <);
    1044             :                 break;
    1045         375 :         case TYPE_lng:
    1046       32532 :                 MINMAX_TYPE(lng, <);
    1047             :                 break;
    1048             : #ifdef HAVE_HGE
    1049           0 :         case TYPE_hge:
    1050           0 :                 MINMAX_TYPE(hge, <);
    1051             :                 break;
    1052             : #endif
    1053           0 :         case TYPE_flt:
    1054           0 :                 MINMAX_TYPE(flt, <);
    1055             :                 break;
    1056           0 :         case TYPE_dbl:
    1057           0 :                 MINMAX_TYPE(dbl, <);
    1058             :                 break;
    1059           0 :         default: {
    1060           0 :                 const void *restrict nil = ATOMnilptr(b1i.type);
    1061           0 :                 int (*cmp)(const void *, const void *) = ATOMcompare(b1i.type);
    1062             : 
    1063           0 :                 if (ATOMvarsized(b1i.type)) {
    1064           0 :                         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    1065           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    1066           0 :                                         oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
    1067           0 :                                         oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
    1068           0 :                                         const void *p1 = BUNtvar(b1i, x1);
    1069           0 :                                         const void *p2 = BUNtvar(b2i, x2);
    1070           0 :                                         if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
    1071             :                                                 nils = true;
    1072             :                                                 p1 = nil;
    1073             :                                         } else {
    1074           0 :                                                 p1 = cmp(p1, p2) < 0 ? p1 : p2;
    1075             :                                         }
    1076           0 :                                         if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    1077           0 :                                                 goto bailout;
    1078             :                                         }
    1079             :                                 }
    1080           0 :                                 TIMEOUT_CHECK(timeoffset,
    1081             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1082             :                         } else {
    1083           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    1084           0 :                                         oid x1 = canditer_next(&ci1) - b1hseqbase;
    1085           0 :                                         oid x2 = canditer_next(&ci2) - b2hseqbase;
    1086           0 :                                         const void *p1 = BUNtvar(b1i, x1);
    1087           0 :                                         const void *p2 = BUNtvar(b2i, x2);
    1088           0 :                                         if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
    1089             :                                                 nils = true;
    1090             :                                                 p1 = nil;
    1091             :                                         } else {
    1092           0 :                                                 p1 = cmp(p1, p2) < 0 ? p1 : p2;
    1093             :                                         }
    1094           0 :                                         if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    1095           0 :                                                 goto bailout;
    1096             :                                         }
    1097             :                                 }
    1098           0 :                                 TIMEOUT_CHECK(timeoffset,
    1099             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1100             :                         }
    1101             :                 } else {
    1102           0 :                         uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
    1103           0 :                         uint16_t width = bn->twidth;
    1104           0 :                         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    1105           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    1106           0 :                                         oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
    1107           0 :                                         oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
    1108           0 :                                         const void *p1 = BUNtloc(b1i, x1);
    1109           0 :                                         const void *p2 = BUNtloc(b2i, x2);
    1110           0 :                                         if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
    1111             :                                                 nils = true;
    1112             :                                                 p1 = nil;
    1113             :                                         } else {
    1114           0 :                                                 p1 = cmp(p1, p2) < 0 ? p1 : p2;
    1115             :                                         }
    1116           0 :                                         memcpy(bcast, p1, width);
    1117           0 :                                         bcast += width;
    1118             :                                 }
    1119           0 :                                 TIMEOUT_CHECK(timeoffset,
    1120             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1121             :                         } else {
    1122           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    1123           0 :                                         oid x1 = canditer_next(&ci1) - b1hseqbase;
    1124           0 :                                         oid x2 = canditer_next(&ci2) - b2hseqbase;
    1125           0 :                                         const void *p1 = BUNtloc(b1i, x1);
    1126           0 :                                         const void *p2 = BUNtloc(b2i, x2);
    1127           0 :                                         if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
    1128             :                                                 nils = true;
    1129             :                                                 p1 = nil;
    1130             :                                         } else {
    1131           0 :                                                 p1 = cmp(p1, p2) < 0 ? p1 : p2;
    1132             :                                         }
    1133           0 :                                         memcpy(bcast, p1, width);
    1134           0 :                                         bcast += width;
    1135             :                                 }
    1136           0 :                                 TIMEOUT_CHECK(timeoffset,
    1137             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1138             :                         }
    1139             :                 }
    1140             :         }
    1141             :         }
    1142             : 
    1143         382 :         bn->tnil = nils;
    1144         382 :         bn->tnonil = !nils;
    1145         382 :         BATsetcount(bn, ci1.ncand);
    1146         382 :         if (ci1.ncand <= 1) {
    1147         295 :                 bn->tsorted = true;
    1148         295 :                 bn->trevsorted = true;
    1149         295 :                 bn->tkey = true;
    1150         295 :                 bn->tseqbase = ATOMtype(b1i.type) == TYPE_oid ? ci1.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
    1151             :         } else {
    1152          87 :                 bn->tsorted = false;
    1153          87 :                 bn->trevsorted = false;
    1154          87 :                 bn->tkey = false;
    1155          87 :                 bn->tseqbase = oid_nil;
    1156             :         }
    1157         382 :         bat_iterator_end(&b1i);
    1158         382 :         bat_iterator_end(&b2i);
    1159             : 
    1160         382 :         TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
    1161             :                   ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
    1162             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    1163             :                   ALGOBATPAR(b1), ALGOBATPAR(b2),
    1164             :                   ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
    1165             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    1166             : 
    1167             :         return bn;
    1168           0 :   bailout:
    1169           0 :         bat_iterator_end(&b1i);
    1170           0 :         bat_iterator_end(&b2i);
    1171           0 :         BBPreclaim(bn);
    1172           0 :         return NULL;
    1173             : }
    1174             : 
    1175             : #define MINMAX_NONIL_TYPE(TYPE, OP)                                     \
    1176             :         do {                                                            \
    1177             :                 TYPE *tb1 = b1i.base, *tb2 = b2i.base, *restrict tbn = Tloc(bn, 0); \
    1178             :                 if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {   \
    1179             :                         TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) { \
    1180             :                                 oid x1 = canditer_next_dense(&ci1) - b1hseqbase; \
    1181             :                                 oid x2 = canditer_next_dense(&ci2) - b2hseqbase; \
    1182             :                                 TYPE p1 = tb1[x1], p2 = tb2[x2];        \
    1183             :                                 if (is_##TYPE##_nil(p1)) {              \
    1184             :                                         if (is_##TYPE##_nil(p2)) {      \
    1185             :                                                 tbn[i] = TYPE##_nil;    \
    1186             :                                                 nils = true;            \
    1187             :                                         } else {                        \
    1188             :                                                 tbn[i] = p2;            \
    1189             :                                         }                               \
    1190             :                                 } else {                                \
    1191             :                                         tbn[i] = !is_##TYPE##_nil(p2) && p2 OP p1 ? p2 : p1; \
    1192             :                                 }                                       \
    1193             :                         }                                               \
    1194             :                         TIMEOUT_CHECK(timeoffset,                       \
    1195             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout)); \
    1196             :                 } else {                                                \
    1197             :                         TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) { \
    1198             :                                 oid x1 = canditer_next(&ci1) - b1hseqbase; \
    1199             :                                 oid x2 = canditer_next(&ci2) - b2hseqbase; \
    1200             :                                 TYPE p1 = tb1[x1], p2 = tb2[x2];        \
    1201             :                                 if (is_##TYPE##_nil(p1)) {              \
    1202             :                                         if (is_##TYPE##_nil(p2)) {      \
    1203             :                                                 tbn[i] = TYPE##_nil;    \
    1204             :                                                 nils = true;            \
    1205             :                                         } else {                        \
    1206             :                                                 tbn[i] = p2;            \
    1207             :                                         }                               \
    1208             :                                 } else {                                \
    1209             :                                         tbn[i] = !is_##TYPE##_nil(p2) && p2 OP p1 ? p2 : p1; \
    1210             :                                 }                                       \
    1211             :                         }                                               \
    1212             :                         TIMEOUT_CHECK(timeoffset,                       \
    1213             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout)); \
    1214             :                 }                                                       \
    1215             :         } while (0)
    1216             : 
    1217             : BAT *
    1218          40 : BATcalcmin_no_nil(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
    1219             : {
    1220          40 :         lng t0 = 0;
    1221          40 :         BAT *bn;
    1222          40 :         bool nils = false;
    1223          40 :         struct canditer ci1, ci2;
    1224          40 :         oid b1hseqbase, b2hseqbase;
    1225             : 
    1226          40 :         lng timeoffset = 0;
    1227          40 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    1228          40 :         if (qry_ctx != NULL) {
    1229          40 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    1230             :         }
    1231             : 
    1232          40 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    1233             : 
    1234          40 :         BATcheck(b1, NULL);
    1235          40 :         BATcheck(b2, NULL);
    1236             : 
    1237          40 :         b1hseqbase = b1->hseqbase;
    1238          40 :         b2hseqbase = b2->hseqbase;
    1239         120 :         if (ATOMtype(b1->ttype) != ATOMtype(b2->ttype)) {
    1240           0 :                 GDKerror("inputs have incompatible types\n");
    1241           0 :                 return NULL;
    1242             :         }
    1243             : 
    1244          40 :         canditer_init(&ci1, b1, s1);
    1245          40 :         canditer_init(&ci2, b2, s2);
    1246          40 :         if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
    1247           0 :                 GDKerror("inputs not the same size.\n");
    1248           0 :                 return NULL;
    1249             :         }
    1250             : 
    1251          80 :         bn = COLnew(ci1.hseq, ATOMtype(b1->ttype), ci1.ncand, TRANSIENT);
    1252          40 :         if (bn == NULL)
    1253             :                 return NULL;
    1254             : 
    1255          40 :         BATiter b1i = bat_iterator(b1);
    1256          40 :         BATiter b2i = bat_iterator(b2);
    1257          69 :         switch (ATOMbasetype(b1i.type)) {
    1258          15 :         case TYPE_bte:
    1259        1069 :                 MINMAX_NONIL_TYPE(bte, <);
    1260             :                 break;
    1261           9 :         case TYPE_sht:
    1262         441 :                 MINMAX_NONIL_TYPE(sht, <);
    1263             :                 break;
    1264           0 :         case TYPE_int:
    1265           0 :                 MINMAX_NONIL_TYPE(int, <);
    1266             :                 break;
    1267           7 :         case TYPE_lng:
    1268         303 :                 MINMAX_NONIL_TYPE(lng, <);
    1269             :                 break;
    1270             : #ifdef HAVE_HGE
    1271           0 :         case TYPE_hge:
    1272           0 :                 MINMAX_NONIL_TYPE(hge, <);
    1273             :                 break;
    1274             : #endif
    1275           0 :         case TYPE_flt:
    1276           0 :                 MINMAX_NONIL_TYPE(flt, <);
    1277             :                 break;
    1278           0 :         case TYPE_dbl:
    1279           0 :                 MINMAX_NONIL_TYPE(dbl, <);
    1280             :                 break;
    1281           9 :         default: {
    1282           9 :                 const void *restrict nil = ATOMnilptr(b1i.type);
    1283           9 :                 int (*cmp)(const void *, const void *) = ATOMcompare(b1i.type);
    1284             : 
    1285           9 :                 if (ATOMvarsized(b1i.type)) {
    1286           9 :                         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    1287         141 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    1288         114 :                                         oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
    1289         114 :                                         oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
    1290         114 :                                         const void *p1 = BUNtvar(b1i, x1);
    1291         114 :                                         const void *p2 = BUNtvar(b2i, x2);
    1292         114 :                                         if (cmp(p1, nil) == 0) {
    1293          48 :                                                 if (cmp(p2, nil) == 0) {
    1294             :                                                         /* both values are nil */
    1295             :                                                         nils = true;
    1296             :                                                 } else {
    1297           0 :                                                         p1 = p2;
    1298             :                                                 }
    1299             :                                         } else {
    1300          66 :                                                 p1 = cmp(p2, nil) != 0 && cmp(p2, p1) < 0 ? p2 : p1;
    1301             :                                         }
    1302         114 :                                         if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    1303           0 :                                                 goto bailout;
    1304             :                                         }
    1305             :                                 }
    1306           9 :                                 TIMEOUT_CHECK(timeoffset,
    1307             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1308             :                         } else {
    1309           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    1310           0 :                                         oid x1 = canditer_next(&ci1) - b1hseqbase;
    1311           0 :                                         oid x2 = canditer_next(&ci2) - b2hseqbase;
    1312           0 :                                         const void *p1 = BUNtvar(b1i, x1);
    1313           0 :                                         const void *p2 = BUNtvar(b2i, x2);
    1314           0 :                                         if (cmp(p1, nil) == 0) {
    1315           0 :                                                 if (cmp(p2, nil) == 0) {
    1316             :                                                         /* both values are nil */
    1317             :                                                         nils = true;
    1318             :                                                 } else {
    1319           0 :                                                         p1 = p2;
    1320             :                                                 }
    1321             :                                         } else {
    1322           0 :                                                 p1 = cmp(p2, nil) != 0 && cmp(p2, p1) < 0 ? p2 : p1;
    1323             :                                         }
    1324           0 :                                         if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    1325           0 :                                                 goto bailout;
    1326             :                                         }
    1327             :                                 }
    1328           0 :                                 TIMEOUT_CHECK(timeoffset,
    1329             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1330             :                         }
    1331             :                 } else {
    1332           0 :                         uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
    1333           0 :                         uint16_t width = bn->twidth;
    1334           0 :                         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    1335           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    1336           0 :                                         oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
    1337           0 :                                         oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
    1338           0 :                                         const void *p1 = BUNtloc(b1i, x1);
    1339           0 :                                         const void *p2 = BUNtloc(b2i, x2);
    1340           0 :                                         if (cmp(p1, nil) == 0) {
    1341           0 :                                                 if (cmp(p2, nil) == 0) {
    1342             :                                                         /* both values are nil */
    1343             :                                                         nils = true;
    1344             :                                                 } else {
    1345           0 :                                                         p1 = p2;
    1346             :                                                 }
    1347             :                                         } else {
    1348           0 :                                                 p1 = cmp(p2, nil) != 0 && cmp(p2, p1) < 0 ? p2 : p1;
    1349             :                                         }
    1350           0 :                                         memcpy(bcast, p1, width);
    1351           0 :                                         bcast += width;
    1352             :                                 }
    1353           0 :                                 TIMEOUT_CHECK(timeoffset,
    1354             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1355             :                         } else {
    1356           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    1357           0 :                                         oid x1 = canditer_next(&ci1) - b1hseqbase;
    1358           0 :                                         oid x2 = canditer_next(&ci2) - b2hseqbase;
    1359           0 :                                         const void *p1 = BUNtloc(b1i, x1);
    1360           0 :                                         const void *p2 = BUNtloc(b2i, x2);
    1361           0 :                                         if (cmp(p1, nil) == 0) {
    1362           0 :                                                 if (cmp(p2, nil) == 0) {
    1363             :                                                         /* both values are nil */
    1364             :                                                         nils = true;
    1365             :                                                 } else {
    1366           0 :                                                         p1 = p2;
    1367             :                                                 }
    1368             :                                         } else {
    1369           0 :                                                 p1 = cmp(p2, nil) != 0 && cmp(p2, p1) < 0 ? p2 : p1;
    1370             :                                         }
    1371           0 :                                         memcpy(bcast, p1, width);
    1372           0 :                                         bcast += width;
    1373             :                                 }
    1374           0 :                                 TIMEOUT_CHECK(timeoffset,
    1375             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1376             :                         }
    1377             :                 }
    1378             :         }
    1379             :         }
    1380             : 
    1381          40 :         bn->tnil = nils;
    1382          40 :         bn->tnonil = !nils;
    1383          40 :         BATsetcount(bn, ci1.ncand);
    1384          40 :         if (ci1.ncand <= 1) {
    1385           2 :                 bn->tsorted = true;
    1386           2 :                 bn->trevsorted = true;
    1387           2 :                 bn->tkey = true;
    1388           2 :                 bn->tseqbase = ATOMtype(b1i.type) == TYPE_oid ? ci1.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
    1389             :         } else {
    1390          38 :                 bn->tsorted = false;
    1391          38 :                 bn->trevsorted = false;
    1392          38 :                 bn->tkey = false;
    1393          38 :                 bn->tseqbase = oid_nil;
    1394             :         }
    1395          40 :         bat_iterator_end(&b1i);
    1396          40 :         bat_iterator_end(&b2i);
    1397             : 
    1398          40 :         TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
    1399             :                   ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
    1400             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    1401             :                   ALGOBATPAR(b1), ALGOBATPAR(b2),
    1402             :                   ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
    1403             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    1404             : 
    1405             :         return bn;
    1406           0 :   bailout:
    1407           0 :         bat_iterator_end(&b1i);
    1408           0 :         bat_iterator_end(&b2i);
    1409           0 :         BBPreclaim(bn);
    1410           0 :         return NULL;
    1411             : }
    1412             : 
    1413             : #define MINMAX_CST_TYPE(TYPE, OP)                                       \
    1414             :         do {                                                            \
    1415             :                 TYPE *restrict tb = bi.base, *restrict tbn = Tloc(bn, 0), pp2 = *(TYPE*) p2; \
    1416             :                 TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {        \
    1417             :                         oid x = canditer_next(&ci) - bhseqbase;             \
    1418             :                         TYPE p1 = tb[x];                                \
    1419             :                         if (is_##TYPE##_nil(p1)) {                      \
    1420             :                                 nils = true;                            \
    1421             :                                 tbn[i] = TYPE##_nil;                    \
    1422             :                         } else {                                        \
    1423             :                                 tbn[i] = p1 OP pp2 ? p1 : pp2;          \
    1424             :                         }                                               \
    1425             :                 }                                                       \
    1426             :                 TIMEOUT_CHECK(timeoffset,                               \
    1427             :                               GOTO_LABEL_TIMEOUT_HANDLER(bailout)); \
    1428             :         } while (0)
    1429             : 
    1430             : BAT *
    1431           7 : BATcalcmincst(BAT *b, const ValRecord *v, BAT *s)
    1432             : {
    1433           7 :         lng t0 = 0;
    1434           7 :         BAT *bn;
    1435           7 :         bool nils = false;
    1436           7 :         struct canditer ci;
    1437           7 :         const void *p2;
    1438           7 :         const void *restrict nil;
    1439           7 :         int (*cmp)(const void *, const void *);
    1440           7 :         oid bhseqbase;
    1441             : 
    1442           7 :         lng timeoffset = 0;
    1443           7 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    1444           7 :         if (qry_ctx != NULL) {
    1445           7 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    1446             :         }
    1447             : 
    1448           7 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    1449             : 
    1450           7 :         BATcheck(b, NULL);
    1451             : 
    1452           7 :         nil = ATOMnilptr(b->ttype);
    1453           7 :         cmp = ATOMcompare(b->ttype);
    1454           7 :         bhseqbase = b->hseqbase;
    1455          14 :         if (ATOMtype(b->ttype) != v->vtype) {
    1456           0 :                 GDKerror("inputs have incompatible types\n");
    1457           0 :                 return NULL;
    1458             :         }
    1459             : 
    1460           7 :         canditer_init(&ci, b, s);
    1461           7 :         p2 = VALptr(v);
    1462          10 :         if (ci.ncand == 0 ||
    1463           3 :                 cmp(p2, nil) == 0 ||
    1464           3 :                 (b->ttype == TYPE_void && is_oid_nil(b->tseqbase)))
    1465           4 :                 return BATconstantV(ci.hseq, b->ttype, nil, ci.ncand, TRANSIENT);
    1466             : 
    1467           6 :         bn = COLnew(ci.hseq, ATOMtype(b->ttype), ci.ncand, TRANSIENT);
    1468           3 :         if (bn == NULL)
    1469             :                 return NULL;
    1470             : 
    1471           3 :         BATiter bi = bat_iterator(b);
    1472           6 :         switch (ATOMbasetype(bi.type)) {
    1473           0 :         case TYPE_bte:
    1474           0 :                 MINMAX_CST_TYPE(bte, <);
    1475             :                 break;
    1476           0 :         case TYPE_sht:
    1477           0 :                 MINMAX_CST_TYPE(sht, <);
    1478             :                 break;
    1479           0 :         case TYPE_int:
    1480           0 :                 MINMAX_CST_TYPE(int, <);
    1481             :                 break;
    1482           0 :         case TYPE_lng:
    1483           0 :                 MINMAX_CST_TYPE(lng, <);
    1484             :                 break;
    1485             : #ifdef HAVE_HGE
    1486           0 :         case TYPE_hge:
    1487           0 :                 MINMAX_CST_TYPE(hge, <);
    1488             :                 break;
    1489             : #endif
    1490           0 :         case TYPE_flt:
    1491           0 :                 MINMAX_CST_TYPE(flt, <);
    1492             :                 break;
    1493           0 :         case TYPE_dbl:
    1494           0 :                 MINMAX_CST_TYPE(dbl, <);
    1495             :                 break;
    1496           3 :         default:
    1497           3 :                 if (ATOMvarsized(bi.type)) {
    1498          18 :                         TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {
    1499          12 :                                 oid x = canditer_next(&ci) - bhseqbase;
    1500          12 :                                 const void *restrict p1 = BUNtvar(bi, x);
    1501          12 :                                 if (cmp(p1, nil) == 0) {
    1502             :                                         nils = true;
    1503             :                                         p1 = nil;
    1504             :                                 } else {
    1505          12 :                                         p1 = cmp(p1, p2) < 0 ? p1 : p2;
    1506             :                                 }
    1507          12 :                                 if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    1508           0 :                                         goto bailout;
    1509             :                                 }
    1510             :                         }
    1511           2 :                         TIMEOUT_CHECK(timeoffset,
    1512             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1513             :                 } else {
    1514           1 :                         uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
    1515           1 :                         uint16_t width = bn->twidth;
    1516           5 :                         TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {
    1517           2 :                                 oid x = canditer_next(&ci) - bhseqbase;
    1518           2 :                                 const void *restrict p1 = BUNtloc(bi, x);
    1519           2 :                                 if (cmp(p1, nil) == 0) {
    1520             :                                         nils = true;
    1521             :                                         p1 = nil;
    1522             :                                 } else {
    1523           2 :                                         p1 = cmp(p1, p2) < 0 ? p1 : p2;
    1524             :                                 }
    1525           2 :                                 memcpy(bcast, p1, width);
    1526           2 :                                 bcast += width;
    1527             :                         }
    1528           1 :                         TIMEOUT_CHECK(timeoffset,
    1529             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1530             :                 }
    1531             :         }
    1532           3 :         bat_iterator_end(&bi);
    1533             : 
    1534           3 :         bn->tnil = nils;
    1535           3 :         bn->tnonil = !nils;
    1536           3 :         BATsetcount(bn, ci.ncand);
    1537           3 :         if (ci.ncand <= 1) {
    1538           0 :                 bn->tsorted = true;
    1539           0 :                 bn->trevsorted = true;
    1540           0 :                 bn->tkey = true;
    1541           0 :                 bn->tseqbase = ATOMtype(bn->ttype) == TYPE_oid ? ci.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
    1542             :         } else {
    1543           3 :                 bn->tsorted = false;
    1544           3 :                 bn->trevsorted = false;
    1545           3 :                 bn->tkey = false;
    1546           3 :                 bn->tseqbase = oid_nil;
    1547             :         }
    1548             : 
    1549           3 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    1550             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    1551             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    1552             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    1553             : 
    1554             :         return bn;
    1555           0 :   bailout:
    1556           0 :         bat_iterator_end(&bi);
    1557           0 :         BBPreclaim(bn);
    1558           0 :         return NULL;
    1559             : }
    1560             : 
    1561             : BAT *
    1562           0 : BATcalccstmin(const ValRecord *v, BAT *b, BAT *s)
    1563             : {
    1564           0 :         return BATcalcmincst(b, v, s);
    1565             : }
    1566             : 
    1567             : #define MINMAX_NONIL_CST_TYPE(TYPE, OP)                                 \
    1568             :         do {                                                            \
    1569             :                 TYPE *restrict tb = bi.base, *restrict tbn = Tloc(bn, 0), pp2 = *(TYPE*) p2; \
    1570             :                 if (is_##TYPE##_nil(pp2)) {                             \
    1571             :                         TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) { \
    1572             :                                 oid x = canditer_next(&ci) - bhseqbase; \
    1573             :                                 TYPE p1 = tb[x];                        \
    1574             :                                 nils |= is_##TYPE##_nil(p1);            \
    1575             :                                 tbn[i] = p1;                            \
    1576             :                         }                                               \
    1577             :                         TIMEOUT_CHECK(timeoffset,                       \
    1578             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout)); \
    1579             :                 } else {                                                \
    1580             :                         TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) { \
    1581             :                                 oid x = canditer_next(&ci) - bhseqbase; \
    1582             :                                 TYPE p1 = tb[x];                        \
    1583             :                                 if (is_##TYPE##_nil(p1)) {              \
    1584             :                                         tbn[i] = pp2;                   \
    1585             :                                 } else {                                \
    1586             :                                         tbn[i] = p1 OP pp2 ? p1 : pp2;  \
    1587             :                                 }                                       \
    1588             :                         }                                               \
    1589             :                         TIMEOUT_CHECK(timeoffset,                       \
    1590             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout)); \
    1591             :                 }                                                       \
    1592             :         } while (0)
    1593             : 
    1594             : BAT *
    1595          47 : BATcalcmincst_no_nil(BAT *b, const ValRecord *v, BAT *s)
    1596             : {
    1597          47 :         lng t0 = 0;
    1598          47 :         BAT *bn;
    1599          47 :         bool nils = false;
    1600          47 :         struct canditer ci;
    1601          47 :         const void *p2;
    1602          47 :         const void *restrict nil;
    1603          47 :         int (*cmp)(const void *, const void *);
    1604          47 :         oid bhseqbase;
    1605             : 
    1606          47 :         lng timeoffset = 0;
    1607          47 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    1608          47 :         if (qry_ctx != NULL) {
    1609          47 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    1610             :         }
    1611             : 
    1612          47 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    1613             : 
    1614          47 :         BATcheck(b, NULL);
    1615             : 
    1616          47 :         nil = ATOMnilptr(b->ttype);
    1617          47 :         cmp = ATOMcompare(b->ttype);
    1618          47 :         bhseqbase = b->hseqbase;
    1619          94 :         if (ATOMtype(b->ttype) != v->vtype) {
    1620           0 :                 GDKerror("inputs have incompatible types\n");
    1621           0 :                 return NULL;
    1622             :         }
    1623             : 
    1624          47 :         canditer_init(&ci, b, s);
    1625          47 :         if (ci.ncand == 0)
    1626           5 :                 return BATconstantV(ci.hseq, b->ttype, nil, ci.ncand, TRANSIENT);
    1627             : 
    1628          42 :         p2 = VALptr(v);
    1629          42 :         if (b->ttype == TYPE_void &&
    1630           0 :                 is_oid_nil(b->tseqbase) &&
    1631           0 :                 is_oid_nil(* (const oid *) p2))
    1632           0 :                 return BATconstant(ci.hseq, TYPE_void, &oid_nil, ci.ncand, TRANSIENT);
    1633             : 
    1634          84 :         bn = COLnew(ci.hseq, ATOMtype(b->ttype), ci.ncand, TRANSIENT);
    1635          42 :         if (bn == NULL)
    1636             :                 return NULL;
    1637             : 
    1638          42 :         BATiter bi = bat_iterator(b);
    1639          79 :         switch (ATOMbasetype(bi.type)) {
    1640           5 :         case TYPE_bte:
    1641          45 :                 MINMAX_NONIL_CST_TYPE(bte, <);
    1642             :                 break;
    1643           5 :         case TYPE_sht:
    1644          27 :                 MINMAX_NONIL_CST_TYPE(sht, <);
    1645             :                 break;
    1646           8 :         case TYPE_int:
    1647         474 :                 MINMAX_NONIL_CST_TYPE(int, <);
    1648             :                 break;
    1649           2 :         case TYPE_lng:
    1650          42 :                 MINMAX_NONIL_CST_TYPE(lng, <);
    1651             :                 break;
    1652             : #ifdef HAVE_HGE
    1653           8 :         case TYPE_hge:
    1654          32 :                 MINMAX_NONIL_CST_TYPE(hge, <);
    1655             :                 break;
    1656             : #endif
    1657           0 :         case TYPE_flt:
    1658           0 :                 MINMAX_NONIL_CST_TYPE(flt, <);
    1659             :                 break;
    1660           9 :         case TYPE_dbl:
    1661          66 :                 MINMAX_NONIL_CST_TYPE(dbl, <);
    1662             :                 break;
    1663           5 :         default:
    1664           5 :                 if (ATOMvarsized(bi.type)) {
    1665           4 :                         if (cmp(p2, nil) == 0) {
    1666           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {
    1667           0 :                                         oid x = canditer_next(&ci) - bhseqbase;
    1668           0 :                                         const void *restrict p1 = BUNtvar(bi, x);
    1669           0 :                                         nils |= cmp(p1, nil) == 0;
    1670           0 :                                         if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    1671           0 :                                                 goto bailout;
    1672             :                                         }
    1673             :                                 }
    1674           0 :                                 TIMEOUT_CHECK(timeoffset,
    1675             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1676             :                         } else {
    1677          66 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {
    1678          54 :                                         oid x = canditer_next(&ci) - bhseqbase;
    1679          54 :                                         const void *restrict p1 = BUNtvar(bi, x);
    1680          54 :                                         p1 = cmp(p1, nil) == 0 || cmp(p2, p1) < 0 ? p2 : p1;
    1681          54 :                                         if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    1682           0 :                                                 goto bailout;
    1683             :                                         }
    1684             :                                 }
    1685           4 :                                 TIMEOUT_CHECK(timeoffset,
    1686             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1687             :                         }
    1688             :                 } else {
    1689           1 :                         uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
    1690           1 :                         uint16_t width = bn->twidth;
    1691           1 :                         if (cmp(p2, nil) == 0) {
    1692           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {
    1693           0 :                                         oid x = canditer_next(&ci) - bhseqbase;
    1694           0 :                                         const void *restrict p1 = BUNtloc(bi, x);
    1695           0 :                                         nils |= cmp(p1, nil) == 0;
    1696           0 :                                         memcpy(bcast, p1, width);
    1697           0 :                                         bcast += width;
    1698             :                                 }
    1699           0 :                                 TIMEOUT_CHECK(timeoffset,
    1700             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1701             :                         } else {
    1702           7 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {
    1703           4 :                                         oid x = canditer_next(&ci) - bhseqbase;
    1704           4 :                                         const void *restrict p1 = BUNtloc(bi, x);
    1705           4 :                                         p1 = cmp(p1, nil) == 0 || cmp(p2, p1) < 0 ? p2 : p1;
    1706           4 :                                         memcpy(bcast, p1, width);
    1707           4 :                                         bcast += width;
    1708             :                                 }
    1709           1 :                                 TIMEOUT_CHECK(timeoffset,
    1710             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1711             :                         }
    1712             :                 }
    1713             :         }
    1714          42 :         bat_iterator_end(&bi);
    1715             : 
    1716          42 :         bn->tnil = nils;
    1717          42 :         bn->tnonil = !nils;
    1718          42 :         BATsetcount(bn, ci.ncand);
    1719          42 :         if (ci.ncand <= 1) {
    1720          13 :                 bn->tsorted = true;
    1721          13 :                 bn->trevsorted = true;
    1722          13 :                 bn->tkey = true;
    1723          13 :                 bn->tseqbase = ATOMtype(bn->ttype) == TYPE_oid ? ci.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
    1724             :         } else {
    1725          29 :                 bn->tsorted = false;
    1726          29 :                 bn->trevsorted = false;
    1727          29 :                 bn->tkey = false;
    1728          29 :                 bn->tseqbase = oid_nil;
    1729             :         }
    1730             : 
    1731          42 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    1732             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    1733             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    1734             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    1735             : 
    1736             :         return bn;
    1737           0 :   bailout:
    1738           0 :         bat_iterator_end(&bi);
    1739           0 :         BBPreclaim(bn);
    1740           0 :         return NULL;
    1741             : }
    1742             : 
    1743             : BAT *
    1744          32 : BATcalccstmin_no_nil(const ValRecord *v, BAT *b, BAT *s)
    1745             : {
    1746          32 :         return BATcalcmincst_no_nil(b, v, s);
    1747             : }
    1748             : 
    1749             : BAT *
    1750           6 : BATcalcmax(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
    1751             : {
    1752           6 :         lng t0 = 0;
    1753           6 :         BAT *bn;
    1754           6 :         bool nils = false;
    1755           6 :         struct canditer ci1, ci2;
    1756           6 :         oid b1hseqbase, b2hseqbase;
    1757             : 
    1758           6 :         lng timeoffset = 0;
    1759           6 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    1760           6 :         if (qry_ctx != NULL) {
    1761           6 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    1762             :         }
    1763             : 
    1764           6 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    1765             : 
    1766           6 :         BATcheck(b1, NULL);
    1767           6 :         BATcheck(b2, NULL);
    1768             : 
    1769           6 :         b1hseqbase = b1->hseqbase;
    1770           6 :         b2hseqbase = b2->hseqbase;
    1771          18 :         if (ATOMtype(b1->ttype) != ATOMtype(b2->ttype)) {
    1772           0 :                 GDKerror("inputs have incompatible types\n");
    1773           0 :                 return NULL;
    1774             :         }
    1775             : 
    1776           6 :         canditer_init(&ci1, b1, s1);
    1777           6 :         canditer_init(&ci2, b2, s2);
    1778           6 :         if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
    1779           0 :                 GDKerror("inputs not the same size.\n");
    1780           0 :                 return NULL;
    1781             :         }
    1782             : 
    1783          12 :         bn = COLnew(ci1.hseq, ATOMtype(b1->ttype), ci1.ncand, TRANSIENT);
    1784           6 :         if (bn == NULL)
    1785             :                 return NULL;
    1786             : 
    1787           6 :         BATiter b1i = bat_iterator(b1);
    1788           6 :         BATiter b2i = bat_iterator(b2);
    1789          12 :         switch (ATOMbasetype(b1i.type)) {
    1790           0 :         case TYPE_bte:
    1791           0 :                 MINMAX_TYPE(bte, >);
    1792             :                 break;
    1793           0 :         case TYPE_sht:
    1794           0 :                 MINMAX_TYPE(sht, >);
    1795             :                 break;
    1796           1 :         case TYPE_int:
    1797          10 :                 MINMAX_TYPE(int, >);
    1798             :                 break;
    1799           0 :         case TYPE_lng:
    1800           0 :                 MINMAX_TYPE(lng, >);
    1801             :                 break;
    1802             : #ifdef HAVE_HGE
    1803           0 :         case TYPE_hge:
    1804           0 :                 MINMAX_TYPE(hge, >);
    1805             :                 break;
    1806             : #endif
    1807           0 :         case TYPE_flt:
    1808           0 :                 MINMAX_TYPE(flt, >);
    1809             :                 break;
    1810           0 :         case TYPE_dbl:
    1811           0 :                 MINMAX_TYPE(dbl, >);
    1812             :                 break;
    1813           5 :         default: {
    1814           5 :                 const void *restrict nil = ATOMnilptr(b1i.type);
    1815           5 :                 int (*cmp)(const void *, const void *) = ATOMcompare(b1i.type);
    1816             : 
    1817           5 :                 if (ATOMvarsized(b1i.type)) {
    1818           4 :                         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    1819          74 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    1820          62 :                                         oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
    1821          62 :                                         oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
    1822          62 :                                         const void *p1 = BUNtvar(b1i, x1);
    1823          62 :                                         const void *p2 = BUNtvar(b2i, x2);
    1824          61 :                                         if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
    1825             :                                                 nils = true;
    1826             :                                                 p1 = nil;
    1827             :                                         } else {
    1828          21 :                                                 p1 = cmp(p1, p2) > 0 ? p1 : p2;
    1829             :                                         }
    1830          62 :                                         if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    1831           0 :                                                 goto bailout;
    1832             :                                         }
    1833             :                                 }
    1834           4 :                                 TIMEOUT_CHECK(timeoffset,
    1835             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1836             :                         } else {
    1837           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    1838           0 :                                         oid x1 = canditer_next(&ci1) - b1hseqbase;
    1839           0 :                                         oid x2 = canditer_next(&ci2) - b2hseqbase;
    1840           0 :                                         const void *p1 = BUNtvar(b1i, x1);
    1841           0 :                                         const void *p2 = BUNtvar(b2i, x2);
    1842           0 :                                         if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
    1843             :                                                 nils = true;
    1844             :                                                 p1 = nil;
    1845             :                                         } else {
    1846           0 :                                                 p1 = cmp(p1, p2) > 0 ? p1 : p2;
    1847             :                                         }
    1848           0 :                                         if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    1849           0 :                                                 goto bailout;
    1850             :                                         }
    1851             :                                 }
    1852           0 :                                 TIMEOUT_CHECK(timeoffset,
    1853             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1854             :                         }
    1855             :                 } else {
    1856           1 :                         uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
    1857           1 :                         uint16_t width = bn->twidth;
    1858           1 :                         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    1859           5 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    1860           2 :                                         oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
    1861           2 :                                         oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
    1862           2 :                                         const void *p1 = BUNtloc(b1i, x1);
    1863           2 :                                         const void *p2 = BUNtloc(b2i, x2);
    1864           2 :                                         if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
    1865             :                                                 nils = true;
    1866             :                                                 p1 = nil;
    1867             :                                         } else {
    1868           2 :                                                 p1 = cmp(p1, p2) > 0 ? p1 : p2;
    1869             :                                         }
    1870           2 :                                         memcpy(bcast, p1, width);
    1871           2 :                                         bcast += width;
    1872             :                                 }
    1873           1 :                                 TIMEOUT_CHECK(timeoffset,
    1874             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1875             :                         } else {
    1876           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    1877           0 :                                         oid x1 = canditer_next(&ci1) - b1hseqbase;
    1878           0 :                                         oid x2 = canditer_next(&ci2) - b2hseqbase;
    1879           0 :                                         const void *p1 = BUNtloc(b1i, x1);
    1880           0 :                                         const void *p2 = BUNtloc(b2i, x2);
    1881           0 :                                         if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
    1882             :                                                 nils = true;
    1883             :                                                 p1 = nil;
    1884             :                                         } else {
    1885           0 :                                                 p1 = cmp(p1, p2) > 0 ? p1 : p2;
    1886             :                                         }
    1887           0 :                                         memcpy(bcast, p1, width);
    1888           0 :                                         bcast += width;
    1889             :                                 }
    1890           0 :                                 TIMEOUT_CHECK(timeoffset,
    1891             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    1892             :                         }
    1893             :                 }
    1894             :         }
    1895             :         }
    1896             : 
    1897           6 :         bn->tnil = nils;
    1898           6 :         bn->tnonil = !nils;
    1899           6 :         BATsetcount(bn, ci1.ncand);
    1900           6 :         if (ci1.ncand <= 1) {
    1901           0 :                 bn->tsorted = true;
    1902           0 :                 bn->trevsorted = true;
    1903           0 :                 bn->tkey = true;
    1904           0 :                 bn->tseqbase = ATOMtype(b1i.type) == TYPE_oid ? ci1.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
    1905             :         } else {
    1906           6 :                 bn->tsorted = false;
    1907           6 :                 bn->trevsorted = false;
    1908           6 :                 bn->tkey = false;
    1909           6 :                 bn->tseqbase = oid_nil;
    1910             :         }
    1911           6 :         bat_iterator_end(&b1i);
    1912           6 :         bat_iterator_end(&b2i);
    1913             : 
    1914           6 :         TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
    1915             :                   ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
    1916             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    1917             :                   ALGOBATPAR(b1), ALGOBATPAR(b2),
    1918             :                   ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
    1919             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    1920             : 
    1921             :         return bn;
    1922           0 :   bailout:
    1923           0 :         bat_iterator_end(&b1i);
    1924           0 :         bat_iterator_end(&b2i);
    1925           0 :         BBPreclaim(bn);
    1926           0 :         return NULL;
    1927             : }
    1928             : 
    1929             : BAT *
    1930           8 : BATcalcmax_no_nil(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
    1931             : {
    1932           8 :         lng t0 = 0;
    1933           8 :         BAT *bn;
    1934           8 :         bool nils = false;
    1935           8 :         struct canditer ci1, ci2;
    1936           8 :         oid b1hseqbase, b2hseqbase;
    1937             : 
    1938           8 :         lng timeoffset = 0;
    1939           8 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    1940           8 :         if (qry_ctx != NULL) {
    1941           8 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    1942             :         }
    1943             : 
    1944           8 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    1945             : 
    1946           8 :         BATcheck(b1, NULL);
    1947           8 :         BATcheck(b2, NULL);
    1948             : 
    1949           8 :         b1hseqbase = b1->hseqbase;
    1950           8 :         b2hseqbase = b2->hseqbase;
    1951          24 :         if (ATOMtype(b1->ttype) != ATOMtype(b2->ttype)) {
    1952           0 :                 GDKerror("inputs have incompatible types\n");
    1953           0 :                 return NULL;
    1954             :         }
    1955             : 
    1956           8 :         canditer_init(&ci1, b1, s1);
    1957           8 :         canditer_init(&ci2, b2, s2);
    1958           8 :         if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
    1959           0 :                 GDKerror("inputs not the same size.\n");
    1960           0 :                 return NULL;
    1961             :         }
    1962             : 
    1963          16 :         bn = COLnew(ci1.hseq, ATOMtype(b1->ttype), ci1.ncand, TRANSIENT);
    1964           8 :         if (bn == NULL)
    1965             :                 return NULL;
    1966             : 
    1967           8 :         BATiter b1i = bat_iterator(b1);
    1968           8 :         BATiter b2i = bat_iterator(b2);
    1969          16 :         switch (ATOMbasetype(b1i.type)) {
    1970           0 :         case TYPE_bte:
    1971           0 :                 MINMAX_NONIL_TYPE(bte, >);
    1972             :                 break;
    1973           0 :         case TYPE_sht:
    1974           0 :                 MINMAX_NONIL_TYPE(sht, >);
    1975             :                 break;
    1976           0 :         case TYPE_int:
    1977           0 :                 MINMAX_NONIL_TYPE(int, >);
    1978             :                 break;
    1979           2 :         case TYPE_lng:
    1980          20 :                 MINMAX_NONIL_TYPE(lng, >);
    1981             :                 break;
    1982             : #ifdef HAVE_HGE
    1983           0 :         case TYPE_hge:
    1984           0 :                 MINMAX_NONIL_TYPE(hge, >);
    1985             :                 break;
    1986             : #endif
    1987           0 :         case TYPE_flt:
    1988           0 :                 MINMAX_NONIL_TYPE(flt, >);
    1989             :                 break;
    1990           2 :         case TYPE_dbl:
    1991        6086 :                 MINMAX_NONIL_TYPE(dbl, >);
    1992             :                 break;
    1993           4 :         default: {
    1994           4 :                 const void *restrict nil = ATOMnilptr(b1i.type);
    1995           4 :                 int (*cmp)(const void *, const void *) = ATOMcompare(b1i.type);
    1996             : 
    1997           4 :                 if (ATOMvarsized(b1i.type)) {
    1998           3 :                         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    1999          18 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    2000           9 :                                         oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
    2001           9 :                                         oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
    2002           9 :                                         const void *p1, *p2;
    2003           9 :                                         p1 = BUNtvar(b1i, x1);
    2004           9 :                                         p2 = BUNtvar(b2i, x2);
    2005           9 :                                         if (cmp(p1, nil) == 0) {
    2006           0 :                                                 if (cmp(p2, nil) == 0) {
    2007             :                                                         /* both values are nil */
    2008             :                                                         nils = true;
    2009             :                                                 } else {
    2010           0 :                                                         p1 = p2;
    2011             :                                                 }
    2012             :                                         } else {
    2013           9 :                                                 p1 = cmp(p2, nil) != 0 && cmp(p2, p1) > 0 ? p2 : p1;
    2014             :                                         }
    2015           9 :                                         if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    2016           0 :                                                 goto bailout;
    2017             :                                         }
    2018             :                                 }
    2019           3 :                                 TIMEOUT_CHECK(timeoffset,
    2020             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    2021             :                         } else {
    2022           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    2023           0 :                                         oid x1 = canditer_next(&ci1) - b1hseqbase;
    2024           0 :                                         oid x2 = canditer_next(&ci2) - b2hseqbase;
    2025           0 :                                         const void *p1, *p2;
    2026           0 :                                         p1 = BUNtvar(b1i, x1);
    2027           0 :                                         p2 = BUNtvar(b2i, x2);
    2028           0 :                                         if (cmp(p1, nil) == 0) {
    2029           0 :                                                 if (cmp(p2, nil) == 0) {
    2030             :                                                         /* both values are nil */
    2031             :                                                         nils = true;
    2032             :                                                 } else {
    2033           0 :                                                         p1 = p2;
    2034             :                                                 }
    2035             :                                         } else {
    2036           0 :                                                 p1 = cmp(p2, nil) != 0 && cmp(p2, p1) > 0 ? p2 : p1;
    2037             :                                         }
    2038           0 :                                         if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    2039           0 :                                                 goto bailout;
    2040             :                                         }
    2041             :                                 }
    2042           0 :                                 TIMEOUT_CHECK(timeoffset,
    2043             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    2044             :                         }
    2045             :                 } else {
    2046           1 :                         uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
    2047           1 :                         uint16_t width = bn->twidth;
    2048           1 :                         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
    2049           4 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    2050           1 :                                         oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
    2051           1 :                                         oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
    2052           1 :                                         const void *p1, *p2;
    2053           1 :                                         p1 = BUNtloc(b1i, x1);
    2054           1 :                                         p2 = BUNtloc(b2i, x2);
    2055           1 :                                         if (cmp(p1, nil) == 0) {
    2056           0 :                                                 if (cmp(p2, nil) == 0) {
    2057             :                                                         /* both values are nil */
    2058             :                                                         nils = true;
    2059             :                                                 } else {
    2060           0 :                                                         p1 = p2;
    2061             :                                                 }
    2062             :                                         } else {
    2063           1 :                                                 p1 = cmp(p2, nil) != 0 && cmp(p2, p1) > 0 ? p2 : p1;
    2064             :                                         }
    2065           1 :                                         memcpy(bcast, p1, width);
    2066           1 :                                         bcast += width;
    2067             :                                 }
    2068           1 :                                 TIMEOUT_CHECK(timeoffset,
    2069             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    2070             :                         } else {
    2071           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, timeoffset) {
    2072           0 :                                         oid x1 = canditer_next(&ci1) - b1hseqbase;
    2073           0 :                                         oid x2 = canditer_next(&ci2) - b2hseqbase;
    2074           0 :                                         const void *p1, *p2;
    2075           0 :                                         p1 = BUNtloc(b1i, x1);
    2076           0 :                                         p2 = BUNtloc(b2i, x2);
    2077           0 :                                         if (cmp(p1, nil) == 0) {
    2078           0 :                                                 if (cmp(p2, nil) == 0) {
    2079             :                                                         /* both values are nil */
    2080             :                                                         nils = true;
    2081             :                                                 } else {
    2082           0 :                                                         p1 = p2;
    2083             :                                                 }
    2084             :                                         } else {
    2085           0 :                                                 p1 = cmp(p2, nil) != 0 && cmp(p2, p1) > 0 ? p2 : p1;
    2086             :                                         }
    2087           0 :                                         memcpy(bcast, p1, width);
    2088           0 :                                         bcast += width;
    2089             :                                 }
    2090           0 :                                 TIMEOUT_CHECK(timeoffset,
    2091             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    2092             :                         }
    2093             :                 }
    2094             :         }
    2095             :         }
    2096             : 
    2097           8 :         bn->tnil = nils;
    2098           8 :         bn->tnonil = !nils;
    2099           8 :         BATsetcount(bn, ci1.ncand);
    2100           8 :         if (ci1.ncand <= 1) {
    2101           2 :                 bn->tsorted = true;
    2102           2 :                 bn->trevsorted = true;
    2103           2 :                 bn->tkey = true;
    2104           2 :                 bn->tseqbase = ATOMtype(b1i.type) == TYPE_oid ? ci1.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
    2105             :         } else {
    2106           6 :                 bn->tsorted = false;
    2107           6 :                 bn->trevsorted = false;
    2108           6 :                 bn->tkey = false;
    2109           6 :                 bn->tseqbase = oid_nil;
    2110             :         }
    2111           8 :         bat_iterator_end(&b1i);
    2112           8 :         bat_iterator_end(&b2i);
    2113             : 
    2114           8 :         TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
    2115             :                   ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
    2116             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    2117             :                   ALGOBATPAR(b1), ALGOBATPAR(b2),
    2118             :                   ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
    2119             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    2120             : 
    2121             :         return bn;
    2122           0 :   bailout:
    2123           0 :         bat_iterator_end(&b1i);
    2124           0 :         bat_iterator_end(&b2i);
    2125           0 :         BBPreclaim(bn);
    2126           0 :         return NULL;
    2127             : }
    2128             : 
    2129             : BAT *
    2130           4 : BATcalcmaxcst(BAT *b, const ValRecord *v, BAT *s)
    2131             : {
    2132           4 :         lng t0 = 0;
    2133           4 :         BAT *bn;
    2134           4 :         bool nils = false;
    2135           4 :         struct canditer ci;
    2136           4 :         const void *p2;
    2137           4 :         const void *restrict nil;
    2138           4 :         int (*cmp)(const void *, const void *);
    2139           4 :         oid bhseqbase;
    2140             : 
    2141           4 :         lng timeoffset = 0;
    2142           4 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    2143           4 :         if (qry_ctx != NULL) {
    2144           4 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    2145             :         }
    2146             : 
    2147           4 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    2148             : 
    2149           4 :         BATcheck(b, NULL);
    2150             : 
    2151           4 :         nil = ATOMnilptr(b->ttype);
    2152           4 :         cmp = ATOMcompare(b->ttype);
    2153           4 :         bhseqbase = b->hseqbase;
    2154           8 :         if (ATOMtype(b->ttype) != v->vtype) {
    2155           0 :                 GDKerror("inputs have incompatible types\n");
    2156           0 :                 return NULL;
    2157             :         }
    2158             : 
    2159           4 :         canditer_init(&ci, b, s);
    2160           4 :         p2 = VALptr(v);
    2161           8 :         if (ci.ncand == 0 ||
    2162           4 :                 cmp(p2, nil) == 0 ||
    2163           4 :                 (b->ttype == TYPE_void && is_oid_nil(b->tseqbase)))
    2164           0 :                 return BATconstantV(ci.hseq, b->ttype, nil, ci.ncand, TRANSIENT);
    2165             : 
    2166           8 :         bn = COLnew(ci.hseq, ATOMtype(b->ttype), ci.ncand, TRANSIENT);
    2167           4 :         if (bn == NULL)
    2168             :                 return NULL;
    2169             : 
    2170           4 :         BATiter bi = bat_iterator(b);
    2171           6 :         switch (ATOMbasetype(bi.type)) {
    2172           2 :         case TYPE_bte:
    2173           8 :                 MINMAX_CST_TYPE(bte, >);
    2174             :                 break;
    2175           0 :         case TYPE_sht:
    2176           0 :                 MINMAX_CST_TYPE(sht, >);
    2177             :                 break;
    2178           0 :         case TYPE_int:
    2179           0 :                 MINMAX_CST_TYPE(int, >);
    2180             :                 break;
    2181           1 :         case TYPE_lng:
    2182          16 :                 MINMAX_CST_TYPE(lng, >);
    2183             :                 break;
    2184             : #ifdef HAVE_HGE
    2185           0 :         case TYPE_hge:
    2186           0 :                 MINMAX_CST_TYPE(hge, >);
    2187             :                 break;
    2188             : #endif
    2189           0 :         case TYPE_flt:
    2190           0 :                 MINMAX_CST_TYPE(flt, >);
    2191             :                 break;
    2192           0 :         case TYPE_dbl:
    2193           0 :                 MINMAX_CST_TYPE(dbl, >);
    2194             :                 break;
    2195           1 :         default:
    2196           1 :                 if (ATOMvarsized(bi.type)) {
    2197           4 :                         TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {
    2198           1 :                                 oid x = canditer_next(&ci) - bhseqbase;
    2199           1 :                                 const void *restrict p1 = BUNtvar(bi, x);
    2200           1 :                                 if (cmp(p1, nil) == 0) {
    2201             :                                         nils = true;
    2202             :                                         p1 = nil;
    2203             :                                 } else {
    2204           0 :                                         p1 = cmp(p1, p2) > 0 ? p1 : p2;
    2205             :                                 }
    2206           1 :                                 if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    2207           0 :                                         goto bailout;
    2208             :                                 }
    2209             :                         }
    2210           1 :                         TIMEOUT_CHECK(timeoffset,
    2211             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    2212             :                 } else {
    2213           0 :                         uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
    2214           0 :                         uint16_t width = bn->twidth;
    2215           0 :                         TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {
    2216           0 :                                 oid x = canditer_next(&ci) - bhseqbase;
    2217           0 :                                 const void *restrict p1 = BUNtloc(bi, x);
    2218           0 :                                 if (cmp(p1, nil) == 0) {
    2219             :                                         nils = true;
    2220             :                                         p1 = nil;
    2221             :                                 } else {
    2222           0 :                                         p1 = cmp(p1, p2) > 0 ? p1 : p2;
    2223             :                                 }
    2224           0 :                                 memcpy(bcast, p1, width);
    2225           0 :                                 bcast += width;
    2226             :                         }
    2227           0 :                         TIMEOUT_CHECK(timeoffset,
    2228             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    2229             :                 }
    2230             :         }
    2231           4 :         bat_iterator_end(&bi);
    2232             : 
    2233           4 :         bn->tnil = nils;
    2234           4 :         bn->tnonil = !nils;
    2235           4 :         BATsetcount(bn, ci.ncand);
    2236           4 :         if (ci.ncand <= 1) {
    2237           3 :                 bn->tsorted = true;
    2238           3 :                 bn->trevsorted = true;
    2239           3 :                 bn->tkey = true;
    2240           3 :                 bn->tseqbase = ATOMtype(bn->ttype) == TYPE_oid ? ci.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
    2241             :         } else {
    2242           1 :                 bn->tsorted = false;
    2243           1 :                 bn->trevsorted = false;
    2244           1 :                 bn->tkey = false;
    2245           1 :                 bn->tseqbase = oid_nil;
    2246             :         }
    2247             : 
    2248           4 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    2249             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    2250             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    2251             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    2252             : 
    2253             :         return bn;
    2254           0 :   bailout:
    2255           0 :         bat_iterator_end(&bi);
    2256           0 :         BBPreclaim(bn);
    2257           0 :         return NULL;
    2258             : }
    2259             : 
    2260             : BAT *
    2261           4 : BATcalccstmax(const ValRecord *v, BAT *b, BAT *s)
    2262             : {
    2263           4 :         return BATcalcmaxcst(b, v, s);
    2264             : }
    2265             : 
    2266             : BAT *
    2267           9 : BATcalcmaxcst_no_nil(BAT *b, const ValRecord *v, BAT *s)
    2268             : {
    2269           9 :         lng t0 = 0;
    2270           9 :         BAT *bn;
    2271           9 :         bool nils = false;
    2272           9 :         struct canditer ci;
    2273           9 :         const void *p2;
    2274           9 :         const void *restrict nil;
    2275           9 :         int (*cmp)(const void *, const void *);
    2276           9 :         oid bhseqbase;
    2277             : 
    2278           9 :         lng timeoffset = 0;
    2279           9 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    2280           9 :         if (qry_ctx != NULL) {
    2281           9 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    2282             :         }
    2283             : 
    2284           9 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    2285             : 
    2286           9 :         BATcheck(b, NULL);
    2287             : 
    2288           9 :         nil = ATOMnilptr(b->ttype);
    2289           9 :         cmp = ATOMcompare(b->ttype);
    2290           9 :         bhseqbase = b->hseqbase;
    2291          18 :         if (ATOMtype(b->ttype) != v->vtype) {
    2292           0 :                 GDKerror("inputs have incompatible types\n");
    2293           0 :                 return NULL;
    2294             :         }
    2295             : 
    2296           9 :         canditer_init(&ci, b, s);
    2297           9 :         if (ci.ncand == 0)
    2298           1 :                 return BATconstantV(ci.hseq, b->ttype, nil, ci.ncand, TRANSIENT);
    2299             : 
    2300           8 :         cmp = ATOMcompare(b->ttype);
    2301           8 :         p2 = VALptr(v);
    2302           8 :         if (b->ttype == TYPE_void &&
    2303           0 :                 is_oid_nil(b->tseqbase) &&
    2304           0 :                 is_oid_nil(* (const oid *) p2))
    2305           0 :                 return BATconstant(ci.hseq, TYPE_void, &oid_nil, ci.ncand, TRANSIENT);
    2306             : 
    2307          16 :         bn = COLnew(ci.hseq, ATOMtype(b->ttype), ci.ncand, TRANSIENT);
    2308           8 :         if (bn == NULL)
    2309             :                 return NULL;
    2310             : 
    2311           8 :         BATiter bi = bat_iterator(b);
    2312          12 :         switch (ATOMbasetype(bi.type)) {
    2313           4 :         case TYPE_bte:
    2314          16 :                 MINMAX_NONIL_CST_TYPE(bte, >);
    2315             :                 break;
    2316           0 :         case TYPE_sht:
    2317           0 :                 MINMAX_NONIL_CST_TYPE(sht, >);
    2318             :                 break;
    2319           2 :         case TYPE_int:
    2320          10 :                 MINMAX_NONIL_CST_TYPE(int, >);
    2321             :                 break;
    2322           2 :         case TYPE_lng:
    2323          68 :                 MINMAX_NONIL_CST_TYPE(lng, >);
    2324             :                 break;
    2325             : #ifdef HAVE_HGE
    2326           0 :         case TYPE_hge:
    2327           0 :                 MINMAX_NONIL_CST_TYPE(hge, >);
    2328             :                 break;
    2329             : #endif
    2330           0 :         case TYPE_flt:
    2331           0 :                 MINMAX_NONIL_CST_TYPE(flt, >);
    2332             :                 break;
    2333           0 :         case TYPE_dbl:
    2334           0 :                 MINMAX_NONIL_CST_TYPE(dbl, >);
    2335             :                 break;
    2336           0 :         default:
    2337           0 :                 if (ATOMvarsized(bi.type)) {
    2338           0 :                         if (cmp(p2, nil) == 0) {
    2339           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {
    2340           0 :                                         oid x = canditer_next(&ci) - bhseqbase;
    2341           0 :                                         const void *restrict p1 = BUNtvar(bi, x);
    2342           0 :                                         nils |= cmp(p1, nil) == 0;
    2343           0 :                                         if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    2344           0 :                                                 goto bailout;
    2345             :                                         }
    2346             :                                 }
    2347           0 :                                 TIMEOUT_CHECK(timeoffset,
    2348             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    2349             :                         } else {
    2350           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {
    2351           0 :                                         oid x = canditer_next(&ci) - bhseqbase;
    2352           0 :                                         const void *restrict p1 = BUNtvar(bi, x);
    2353           0 :                                         p1 = cmp(p1, nil) == 0 || cmp(p2, p1) > 0 ? p2 : p1;
    2354           0 :                                         if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
    2355           0 :                                                 goto bailout;
    2356             :                                         }
    2357             :                                 }
    2358           0 :                                 TIMEOUT_CHECK(timeoffset,
    2359             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    2360             :                         }
    2361             :                 } else {
    2362           0 :                         uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
    2363           0 :                         uint16_t width = bn->twidth;
    2364           0 :                         if (cmp(p2, nil) == 0) {
    2365           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {
    2366           0 :                                         oid x = canditer_next(&ci) - bhseqbase;
    2367           0 :                                         const void *restrict p1 = BUNtloc(bi, x);
    2368           0 :                                         nils |= cmp(p1, nil) == 0;
    2369           0 :                                         memcpy(bcast, p1, width);
    2370           0 :                                         bcast += width;
    2371             :                                 }
    2372           0 :                                 TIMEOUT_CHECK(timeoffset,
    2373             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    2374             :                         } else {
    2375           0 :                                 TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, timeoffset) {
    2376           0 :                                         oid x = canditer_next(&ci) - bhseqbase;
    2377           0 :                                         const void *restrict p1 = BUNtloc(bi, x);
    2378           0 :                                         p1 = cmp(p1, nil) == 0 || cmp(p2, p1) > 0 ? p2 : p1;
    2379           0 :                                         memcpy(bcast, p1, width);
    2380           0 :                                         bcast += width;
    2381             :                                 }
    2382           0 :                                 TIMEOUT_CHECK(timeoffset,
    2383             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    2384             :                         }
    2385             :                 }
    2386             :         }
    2387           8 :         bat_iterator_end(&bi);
    2388             : 
    2389           8 :         bn->tnil = nils;
    2390           8 :         bn->tnonil = !nils;
    2391           8 :         BATsetcount(bn, ci.ncand);
    2392           8 :         if (ci.ncand <= 1) {
    2393           4 :                 bn->tsorted = true;
    2394           4 :                 bn->trevsorted = true;
    2395           4 :                 bn->tkey = true;
    2396           4 :                 bn->tseqbase = ATOMtype(bn->ttype) == TYPE_oid ? ci.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
    2397             :         } else {
    2398           4 :                 bn->tsorted = false;
    2399           4 :                 bn->trevsorted = false;
    2400           4 :                 bn->tkey = false;
    2401           4 :                 bn->tseqbase = oid_nil;
    2402             :         }
    2403             : 
    2404           8 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    2405             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    2406             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    2407             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    2408             : 
    2409             :         return bn;
    2410           0 :   bailout:
    2411           0 :         bat_iterator_end(&bi);
    2412           0 :         BBPreclaim(bn);
    2413           0 :         return NULL;
    2414             : }
    2415             : 
    2416             : BAT *
    2417           0 : BATcalccstmax_no_nil(const ValRecord *v, BAT *b, BAT *s)
    2418             : {
    2419           0 :         return BATcalcmaxcst_no_nil(b, v, s);
    2420             : }
    2421             : 
    2422             : /* ---------------------------------------------------------------------- */
    2423             : /* logical (for type bit) or bitwise (for integral types) exclusive OR */
    2424             : 
    2425             : #define XOR(a, b)       ((a) ^ (b))
    2426             : #define XORBIT(a, b)    (((a) == 0) != ((b) == 0))
    2427             : 
    2428             : static BUN
    2429          33 : xor_typeswitchloop(const void *lft, bool incr1,
    2430             :                    const void *rgt, bool incr2,
    2431             :                    void *restrict dst, int tp,
    2432             :                    struct canditer *restrict ci1,
    2433             :                    struct canditer *restrict ci2,
    2434             :                    oid candoff1, oid candoff2,
    2435             :                    bool nonil, const char *func)
    2436             : {
    2437          33 :         BUN i, j, k;
    2438          33 :         BUN nils = 0;
    2439             : 
    2440          33 :         lng timeoffset = 0;
    2441          33 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    2442          33 :         if (qry_ctx != NULL) {
    2443          33 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    2444             :         }
    2445             : 
    2446          65 :         switch (ATOMbasetype(tp)) {
    2447           8 :         case TYPE_bte:
    2448           8 :                 if (tp == TYPE_bit) {
    2449           1 :                         if (nonil)
    2450           0 :                                 BINARY_3TYPE_FUNC_nonil(bit, bit, bit, XORBIT);
    2451             :                         else
    2452          12 :                                 BINARY_3TYPE_FUNC(bit, bit, bit, XORBIT);
    2453             :                 } else {
    2454           7 :                         if (nonil)
    2455           0 :                                 BINARY_3TYPE_FUNC_nonil_nilcheck(bte, bte, bte, XOR, ON_OVERFLOW(bte, bte, "XOR"));
    2456             :                         else
    2457          37 :                                 BINARY_3TYPE_FUNC_nilcheck(bte, bte, bte, XOR, ON_OVERFLOW(bte, bte, "XOR"));
    2458             :                 }
    2459             :                 break;
    2460           1 :         case TYPE_sht:
    2461           1 :                 if (nonil)
    2462           0 :                         BINARY_3TYPE_FUNC_nonil_nilcheck(sht, sht, sht, XOR, ON_OVERFLOW(sht, sht, "XOR"));
    2463             :                 else
    2464           4 :                         BINARY_3TYPE_FUNC_nilcheck(sht, sht, sht, XOR, ON_OVERFLOW(sht, sht, "XOR"));
    2465             :                 break;
    2466           8 :         case TYPE_int:
    2467           8 :                 if (nonil)
    2468           0 :                         BINARY_3TYPE_FUNC_nonil_nilcheck(int, int, int, XOR, ON_OVERFLOW(int, int, "XOR"));
    2469             :                 else
    2470          32 :                         BINARY_3TYPE_FUNC_nilcheck(int, int, int, XOR, ON_OVERFLOW(int, int, "XOR"));
    2471             :                 break;
    2472           2 :         case TYPE_lng:
    2473           2 :                 if (nonil)
    2474           1 :                         BINARY_3TYPE_FUNC_nonil_nilcheck(lng, lng, lng, XOR, ON_OVERFLOW(lng, lng, "XOR"));
    2475             :                 else
    2476           1 :                         BINARY_3TYPE_FUNC_nilcheck(lng, lng, lng, XOR, ON_OVERFLOW(lng, lng, "XOR"));
    2477             :                 break;
    2478             : #ifdef HAVE_HGE
    2479          14 :         case TYPE_hge:
    2480          14 :                 if (nonil)
    2481       75866 :                         BINARY_3TYPE_FUNC_nonil_nilcheck(hge, hge, hge, XOR, ON_OVERFLOW(hge, hge, "XOR"));
    2482             :                 else
    2483       33862 :                         BINARY_3TYPE_FUNC_nilcheck(hge, hge, hge, XOR, ON_OVERFLOW(hge, hge, "XOR"));
    2484             :                 break;
    2485             : #endif
    2486           0 :         default:
    2487           0 :                 GDKerror("%s: bad input type %s.\n", func, ATOMname(tp));
    2488           0 :                 return BUN_NONE;
    2489             :         }
    2490             : 
    2491             :         return nils;
    2492             : }
    2493             : 
    2494             : BAT *
    2495          12 : BATcalcxor(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
    2496             : {
    2497          12 :         lng t0 = 0;
    2498          12 :         BAT *bn;
    2499          12 :         BUN nils;
    2500          12 :         struct canditer ci1, ci2;
    2501             : 
    2502          12 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    2503             : 
    2504          12 :         BATcheck(b1, NULL);
    2505          12 :         BATcheck(b2, NULL);
    2506             : 
    2507          34 :         if (ATOMbasetype(b1->ttype) != ATOMbasetype(b2->ttype)) {
    2508           0 :                 GDKerror("incompatible input types.\n");
    2509           0 :                 return NULL;
    2510             :         }
    2511             : 
    2512          12 :         canditer_init(&ci1, b1, s1);
    2513          12 :         canditer_init(&ci2, b2, s2);
    2514          12 :         if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
    2515           0 :                 GDKerror("inputs not the same size.\n");
    2516           0 :                 return NULL;
    2517             :         }
    2518             : 
    2519          12 :         bn = COLnew(ci1.hseq, b1->ttype, ci1.ncand, TRANSIENT);
    2520          12 :         if (bn == NULL)
    2521             :                 return NULL;
    2522          12 :         if (ci1.ncand == 0)
    2523             :                 return bn;
    2524             : 
    2525           2 :         BATiter b1i = bat_iterator(b1);
    2526           2 :         BATiter b2i = bat_iterator(b2);
    2527           6 :         nils = xor_typeswitchloop(b1i.base, true,
    2528           2 :                                   b2i.base, true,
    2529           2 :                                   Tloc(bn, 0),
    2530           2 :                                   b1i.type,
    2531             :                                   &ci1, &ci2,
    2532             :                                   b1->hseqbase, b2->hseqbase,
    2533           2 :                                   b1i.nonil && b2i.nonil,
    2534             :                                   __func__);
    2535           2 :         bat_iterator_end(&b1i);
    2536           2 :         bat_iterator_end(&b2i);
    2537             : 
    2538           2 :         if (nils == BUN_NONE) {
    2539           0 :                 BBPunfix(bn->batCacheid);
    2540           0 :                 return NULL;
    2541             :         }
    2542             : 
    2543           2 :         BATsetcount(bn, ci1.ncand);
    2544             : 
    2545           2 :         bn->tsorted = ci1.ncand <= 1 || nils == ci1.ncand;
    2546           2 :         bn->trevsorted = ci1.ncand <= 1 || nils == ci1.ncand;
    2547           2 :         bn->tkey = ci1.ncand <= 1;
    2548           2 :         bn->tnil = nils != 0;
    2549           2 :         bn->tnonil = nils == 0;
    2550             : 
    2551           2 :         TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
    2552             :                   ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
    2553             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    2554             :                   ALGOBATPAR(b1), ALGOBATPAR(b2),
    2555             :                   ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
    2556             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    2557             : 
    2558             :         return bn;
    2559             : }
    2560             : 
    2561             : BAT *
    2562           9 : BATcalcxorcst(BAT *b, const ValRecord *v, BAT *s)
    2563             : {
    2564           9 :         lng t0 = 0;
    2565           9 :         BAT *bn;
    2566           9 :         BUN nils;
    2567           9 :         struct canditer ci;
    2568             : 
    2569           9 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    2570             : 
    2571           9 :         BATcheck(b, NULL);
    2572             : 
    2573          27 :         if (ATOMbasetype(b->ttype) != ATOMbasetype(v->vtype)) {
    2574           0 :                 GDKerror("incompatible input types.\n");
    2575           0 :                 return NULL;
    2576             :         }
    2577             : 
    2578           9 :         canditer_init(&ci, b, s);
    2579             : 
    2580           9 :         bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
    2581           9 :         if (bn == NULL)
    2582             :                 return NULL;
    2583           9 :         if (ci.ncand == 0)
    2584             :                 return bn;
    2585             : 
    2586           8 :         BATiter bi = bat_iterator(b);
    2587          24 :         nils = xor_typeswitchloop(bi.base, true,
    2588             :                                   VALptr(v), false,
    2589           8 :                                   Tloc(bn, 0), bi.type,
    2590             :                                   &ci,
    2591           8 :                                   &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
    2592             :                                   b->hseqbase, 0,
    2593           8 :                                   bi.nonil && ATOMcmp(v->vtype, VALptr(v), ATOMnilptr(v->vtype)) != 0,
    2594             :                                   __func__);
    2595           8 :         bat_iterator_end(&bi);
    2596             : 
    2597           8 :         if (nils == BUN_NONE) {
    2598           2 :                 BBPunfix(bn->batCacheid);
    2599           2 :                 return NULL;
    2600             :         }
    2601             : 
    2602           6 :         BATsetcount(bn, ci.ncand);
    2603             : 
    2604           6 :         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
    2605           6 :         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
    2606           6 :         bn->tkey = ci.ncand <= 1;
    2607           6 :         bn->tnil = nils != 0;
    2608           6 :         bn->tnonil = nils == 0;
    2609             : 
    2610           6 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    2611             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    2612             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    2613             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    2614             : 
    2615             :         return bn;
    2616             : }
    2617             : 
    2618             : BAT *
    2619           0 : BATcalccstxor(const ValRecord *v, BAT *b, BAT *s)
    2620             : {
    2621           0 :         return BATcalcxorcst(b, v, s);
    2622             : }
    2623             : 
    2624             : gdk_return
    2625          23 : VARcalcxor(ValPtr ret, const ValRecord *lft, const ValRecord *rgt)
    2626             : {
    2627          69 :         if (ATOMbasetype(lft->vtype) != ATOMbasetype(rgt->vtype)) {
    2628           0 :                 GDKerror("incompatible input types.\n");
    2629           0 :                 return GDK_FAIL;
    2630             :         }
    2631             : 
    2632          23 :         if (xor_typeswitchloop(VALptr(lft), false,
    2633             :                                VALptr(rgt), false,
    2634             :                                VALget(ret), lft->vtype,
    2635          23 :                                &(struct canditer){.tpe=cand_dense, .ncand=1},
    2636          23 :                                &(struct canditer){.tpe=cand_dense, .ncand=1},
    2637             :                                0, 0, false, __func__) == BUN_NONE)
    2638           0 :                 return GDK_FAIL;
    2639          23 :         return GDK_SUCCEED;
    2640             : }
    2641             : 
    2642             : /* ---------------------------------------------------------------------- */
    2643             : /* logical (for type bit) or bitwise (for integral types) OR */
    2644             : 
    2645             : #define or3(a,b)        ((a) == 1 || (b) == 1 ? 1 : is_bit_nil(a) || is_bit_nil(b) ? bit_nil : 0)
    2646             : 
    2647             : #define OR(a, b)        ((a) | (b))
    2648             : 
    2649             : static BUN
    2650     1197070 : or_typeswitchloop(const void *lft, bool incr1,
    2651             :                   const void *rgt, bool incr2,
    2652             :                   void *restrict dst, int tp,
    2653             :                   struct canditer *restrict ci1,
    2654             :                   struct canditer *restrict ci2,
    2655             :                   oid candoff1, oid candoff2,
    2656             :                   bool nonil, const char *func)
    2657             : {
    2658     1197070 :         BUN i = 0, j = 0, k;
    2659     1197070 :         BUN nils = 0;
    2660             : 
    2661     1197070 :         lng timeoffset = 0;
    2662     1197070 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    2663     1197069 :         if (qry_ctx != NULL) {
    2664     1193296 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    2665             :         }
    2666             : 
    2667             :         /* note, we don't have to check whether the result is equal to
    2668             :          * NIL when using bitwise OR: there is only a single bit set in
    2669             :          * NIL, which means that at least one of the operands must have
    2670             :          * only that single bit set (and the other either also or
    2671             :          * no bits set), so that that operand is already NIL */
    2672     1197083 :         switch (ATOMbasetype(tp)) {
    2673     1197058 :         case TYPE_bte:
    2674     1197058 :                 if (tp == TYPE_bit) {
    2675             :                         /* implement tri-Boolean algebra */
    2676    19811192 :                         TIMEOUT_LOOP_IDX(k, ci1->ncand, timeoffset) {
    2677    16219071 :                                 if (incr1)
    2678    15023661 :                                         i = canditer_next(ci1) - candoff1;
    2679    16218271 :                                 if (incr2)
    2680    15023362 :                                         j = canditer_next(ci2) - candoff2;
    2681    16219069 :                                 bit v1 = ((const bit *) lft)[i];
    2682    16219069 :                                 bit v2 = ((const bit *) rgt)[j];
    2683    16219069 :                                 ((bit *) dst)[k] = or3(v1, v2);
    2684    16219069 :                                 nils += is_bit_nil(((bit *) dst)[k]);
    2685             :                         }
    2686     1197052 :                         TIMEOUT_CHECK(timeoffset, TIMEOUT_HANDLER(BUN_NONE));
    2687             :                 } else {
    2688           4 :                         if (nonil)
    2689           0 :                                 BINARY_3TYPE_FUNC_nonil(bte, bte, bte, OR);
    2690             :                         else
    2691          16 :                                 BINARY_3TYPE_FUNC(bte, bte, bte, OR);
    2692             :                 }
    2693             :                 break;
    2694           0 :         case TYPE_sht:
    2695           0 :                 if (nonil)
    2696           0 :                         BINARY_3TYPE_FUNC_nonil(sht, sht, sht, OR);
    2697             :                 else
    2698           0 :                         BINARY_3TYPE_FUNC(sht, sht, sht, OR);
    2699             :                 break;
    2700           8 :         case TYPE_int:
    2701           8 :                 if (nonil)
    2702          14 :                         BINARY_3TYPE_FUNC_nonil(int, int, int, OR);
    2703             :                 else
    2704         136 :                         BINARY_3TYPE_FUNC(int, int, int, OR);
    2705             :                 break;
    2706           2 :         case TYPE_lng:
    2707           2 :                 if (nonil)
    2708          39 :                         BINARY_3TYPE_FUNC_nonil(lng, lng, lng, OR);
    2709             :                 else
    2710           4 :                         BINARY_3TYPE_FUNC(lng, lng, lng, OR);
    2711             :                 break;
    2712             : #ifdef HAVE_HGE
    2713           1 :         case TYPE_hge:
    2714           1 :                 if (nonil)
    2715           0 :                         BINARY_3TYPE_FUNC_nonil(hge, hge, hge, OR);
    2716             :                 else
    2717           4 :                         BINARY_3TYPE_FUNC(hge, hge, hge, OR);
    2718             :                 break;
    2719             : #endif
    2720           0 :         default:
    2721           0 :                 GDKerror("%s: bad input type %s.\n", func, ATOMname(tp));
    2722           0 :                 return BUN_NONE;
    2723             :         }
    2724             : 
    2725             :         return nils;
    2726             : }
    2727             : 
    2728             : BAT *
    2729        1562 : BATcalcor(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
    2730             : {
    2731        1562 :         lng t0 = 0;
    2732        1562 :         BAT *bn;
    2733        1562 :         BUN nils;
    2734        1562 :         struct canditer ci1, ci2;
    2735             : 
    2736        1562 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    2737             : 
    2738        1562 :         BATcheck(b1, NULL);
    2739        1562 :         BATcheck(b2, NULL);
    2740             : 
    2741        1590 :         if (ATOMbasetype(b1->ttype) != ATOMbasetype(b2->ttype)) {
    2742           0 :                 GDKerror("incompatible input types.\n");
    2743           0 :                 return NULL;
    2744             :         }
    2745             : 
    2746        1562 :         canditer_init(&ci1, b1, s1);
    2747        1562 :         canditer_init(&ci2, b2, s2);
    2748        1561 :         if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
    2749           0 :                 GDKerror("inputs not the same size.\n");
    2750           0 :                 return NULL;
    2751             :         }
    2752             : 
    2753        1561 :         bn = COLnew(ci1.hseq, b1->ttype, ci1.ncand, TRANSIENT);
    2754        1562 :         if (bn == NULL)
    2755             :                 return NULL;
    2756        1562 :         if (ci1.ncand == 0)
    2757             :                 return bn;
    2758             : 
    2759        1310 :         BATiter b1i = bat_iterator(b1);
    2760        1310 :         BATiter b2i = bat_iterator(b2);
    2761        3927 :         nils = or_typeswitchloop(b1i.base, true,
    2762        1310 :                                  b2i.base, true,
    2763        1310 :                                  Tloc(bn, 0),
    2764        1310 :                                  b1i.type,
    2765             :                                  &ci1, &ci2, b1->hseqbase, b2->hseqbase,
    2766        1310 :                                  b1i.nonil && b2i.nonil,
    2767             :                                  __func__);
    2768        1307 :         bat_iterator_end(&b1i);
    2769        1310 :         bat_iterator_end(&b2i);
    2770             : 
    2771        1310 :         if (nils == BUN_NONE) {
    2772           0 :                 BBPunfix(bn->batCacheid);
    2773           0 :                 return NULL;
    2774             :         }
    2775             : 
    2776        1310 :         BATsetcount(bn, ci1.ncand);
    2777             : 
    2778        1309 :         bn->tsorted = ci1.ncand <= 1 || nils == ci1.ncand;
    2779        1309 :         bn->trevsorted = ci1.ncand <= 1 || nils == ci1.ncand;
    2780        1309 :         bn->tkey = ci1.ncand <= 1;
    2781        1309 :         bn->tnil = nils != 0;
    2782        1309 :         bn->tnonil = nils == 0;
    2783             : 
    2784        1309 :         TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
    2785             :                   ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
    2786             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    2787             :                   ALGOBATPAR(b1), ALGOBATPAR(b2),
    2788             :                   ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
    2789             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    2790             : 
    2791             :         return bn;
    2792             : }
    2793             : 
    2794             : BAT *
    2795          62 : BATcalcorcst(BAT *b, const ValRecord *v, BAT *s)
    2796             : {
    2797          62 :         lng t0 = 0;
    2798          62 :         BAT *bn;
    2799          62 :         BUN nils;
    2800          62 :         struct canditer ci;
    2801             : 
    2802          62 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    2803             : 
    2804          62 :         BATcheck(b, NULL);
    2805             : 
    2806          64 :         if (ATOMbasetype(b->ttype) != ATOMbasetype(v->vtype)) {
    2807           0 :                 GDKerror("incompatible input types.\n");
    2808           0 :                 return NULL;
    2809             :         }
    2810             : 
    2811          62 :         canditer_init(&ci, b, s);
    2812             : 
    2813          62 :         if (b->ttype == TYPE_bit && v->vtype == TYPE_bit && v->val.btval == 1) {
    2814             :                 /* true OR anything (including NIL) equals true */
    2815          27 :                 return BATconstant(ci.hseq, TYPE_bit, &(bit){1},
    2816             :                                    ci.ncand, TRANSIENT);
    2817             :         }
    2818             : 
    2819          35 :         bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
    2820          35 :         if (bn == NULL)
    2821             :                 return NULL;
    2822          35 :         if (ci.ncand == 0)
    2823             :                 return bn;
    2824             : 
    2825          30 :         BATiter bi = bat_iterator(b);
    2826          90 :         nils = or_typeswitchloop(bi.base, true,
    2827             :                                  VALptr(v), false,
    2828          30 :                                  Tloc(bn, 0), bi.type,
    2829             :                                  &ci,
    2830          30 :                                  &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
    2831             :                                  b->hseqbase, 0,
    2832          30 :                                  bi.nonil && ATOMcmp(v->vtype, VALptr(v), ATOMnilptr(v->vtype)) != 0,
    2833             :                                  __func__);
    2834          30 :         bat_iterator_end(&bi);
    2835             : 
    2836          30 :         if (nils == BUN_NONE) {
    2837           0 :                 BBPunfix(bn->batCacheid);
    2838           0 :                 return NULL;
    2839             :         }
    2840             : 
    2841          30 :         BATsetcount(bn, ci.ncand);
    2842             : 
    2843          30 :         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
    2844          30 :         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
    2845          30 :         bn->tkey = ci.ncand <= 1;
    2846          30 :         bn->tnil = nils != 0;
    2847          30 :         bn->tnonil = nils == 0;
    2848             : 
    2849          30 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    2850             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    2851             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    2852             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    2853             : 
    2854             :         return bn;
    2855             : }
    2856             : 
    2857             : BAT *
    2858          21 : BATcalccstor(const ValRecord *v, BAT *b, BAT *s)
    2859             : {
    2860          21 :         return BATcalcorcst(b, v, s);
    2861             : }
    2862             : 
    2863             : gdk_return
    2864     1195730 : VARcalcor(ValPtr ret, const ValRecord *lft, const ValRecord *rgt)
    2865             : {
    2866     1195746 :         if (ATOMbasetype(lft->vtype) != ATOMbasetype(rgt->vtype)) {
    2867           0 :                 GDKerror("incompatible input types.\n");
    2868           0 :                 return GDK_FAIL;
    2869             :         }
    2870             : 
    2871     1195730 :         if (or_typeswitchloop(VALptr(lft), false,
    2872             :                               VALptr(rgt), false,
    2873             :                               VALget(ret), lft->vtype,
    2874     1195730 :                               &(struct canditer){.tpe=cand_dense, .ncand=1},
    2875     1195730 :                               &(struct canditer){.tpe=cand_dense, .ncand=1},
    2876             :                               0, 0, false, __func__) == BUN_NONE)
    2877           0 :                 return GDK_FAIL;
    2878     1195730 :         return GDK_SUCCEED;
    2879             : }
    2880             : 
    2881             : /* ---------------------------------------------------------------------- */
    2882             : /* logical (for type bit) or bitwise (for integral types) exclusive AND */
    2883             : 
    2884             : #define and3(a,b)       ((a) == 0 || (b) == 0 ? 0 : is_bit_nil(a) || is_bit_nil(b) ? bit_nil : 1)
    2885             : 
    2886             : #define AND(a, b)       ((a) & (b))
    2887             : 
    2888             : static BUN
    2889     2223613 : and_typeswitchloop(const void *lft, bool incr1,
    2890             :                    const void *rgt, bool incr2,
    2891             :                    void *restrict dst, int tp,
    2892             :                    struct canditer *restrict ci1,
    2893             :                    struct canditer *restrict ci2,
    2894             :                    oid candoff1, oid candoff2,
    2895             :                    bool nonil, const char *func)
    2896             : {
    2897     2223613 :         BUN i = 0, j = 0, k;
    2898     2223613 :         BUN nils = 0;
    2899             : 
    2900     2223613 :         lng timeoffset = 0;
    2901     2223613 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    2902     2223613 :         if (qry_ctx != NULL) {
    2903     2223613 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    2904             :         }
    2905             : 
    2906     2223675 :         switch (ATOMbasetype(tp)) {
    2907     2223563 :         case TYPE_bte:
    2908     2223563 :                 if (tp == TYPE_bit) {
    2909             :                         /* implement tri-Boolean algebra */
    2910    10733556 :                         TIMEOUT_LOOP_IDX(k, ci1->ncand, timeoffset) {
    2911     4062680 :                                 if (incr1)
    2912     1837729 :                                         i = canditer_next(ci1) - candoff1;
    2913     4061785 :                                 if (incr2)
    2914     1837061 :                                         j = canditer_next(ci2) - candoff2;
    2915     4062680 :                                 bit v1 = ((const bit *) lft)[i];
    2916     4062680 :                                 bit v2 = ((const bit *) rgt)[j];
    2917     4062680 :                                 ((bit *) dst)[k] = and3(v1, v2);
    2918     4062680 :                                 nils += is_bit_nil(((bit *) dst)[k]);
    2919             :                         }
    2920     2223550 :                         TIMEOUT_CHECK(timeoffset, TIMEOUT_HANDLER(BUN_NONE));
    2921             :                 } else {
    2922          12 :                         if (nonil)
    2923           0 :                                 BINARY_3TYPE_FUNC_nonil_nilcheck(bte, bte, bte, AND, ON_OVERFLOW(bte, bte, "AND"));
    2924             :                         else
    2925          49 :                                 BINARY_3TYPE_FUNC_nilcheck(bte, bte, bte, AND, ON_OVERFLOW(bte, bte, "AND"));
    2926             :                 }
    2927             :                 break;
    2928           6 :         case TYPE_sht:
    2929           6 :                 if (nonil)
    2930          14 :                         BINARY_3TYPE_FUNC_nonil_nilcheck(sht, sht, sht, AND, ON_OVERFLOW(sht, sht, "AND"));
    2931             :                 else
    2932          12 :                         BINARY_3TYPE_FUNC_nilcheck(sht, sht, sht, AND, ON_OVERFLOW(sht, sht, "AND"));
    2933             :                 break;
    2934          37 :         case TYPE_int:
    2935          37 :                 if (nonil)
    2936         198 :                         BINARY_3TYPE_FUNC_nonil_nilcheck(int, int, int, AND, ON_OVERFLOW(int, int, "AND"));
    2937             :                 else
    2938         108 :                         BINARY_3TYPE_FUNC_nilcheck(int, int, int, AND, ON_OVERFLOW(int, int, "AND"));
    2939             :                 break;
    2940           2 :         case TYPE_lng:
    2941           2 :                 if (nonil)
    2942           0 :                         BINARY_3TYPE_FUNC_nonil_nilcheck(lng, lng, lng, AND, ON_OVERFLOW(lng, lng, "AND"));
    2943             :                 else
    2944           8 :                         BINARY_3TYPE_FUNC_nilcheck(lng, lng, lng, AND, ON_OVERFLOW(lng, lng, "AND"));
    2945             :                 break;
    2946             : #ifdef HAVE_HGE
    2947           5 :         case TYPE_hge:
    2948           5 :                 if (nonil)
    2949           6 :                         BINARY_3TYPE_FUNC_nonil_nilcheck(hge, hge, hge, AND, ON_OVERFLOW(hge, hge, "AND"));
    2950             :                 else
    2951          16 :                         BINARY_3TYPE_FUNC_nilcheck(hge, hge, hge, AND, ON_OVERFLOW(hge, hge, "AND"));
    2952             :                 break;
    2953             : #endif
    2954           0 :         default:
    2955           0 :                 GDKerror("%s: bad input type %s.\n", func, ATOMname(tp));
    2956           0 :                 return BUN_NONE;
    2957             :         }
    2958             : 
    2959             :         return nils;
    2960             : }
    2961             : 
    2962             : BAT *
    2963        1747 : BATcalcand(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
    2964             : {
    2965        1747 :         lng t0 = 0;
    2966        1747 :         BAT *bn;
    2967        1747 :         BUN nils;
    2968        1747 :         struct canditer ci1, ci2;
    2969             : 
    2970        1747 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    2971             : 
    2972        1747 :         BATcheck(b1, NULL);
    2973        1747 :         BATcheck(b2, NULL);
    2974             : 
    2975        1769 :         if (ATOMbasetype(b1->ttype) != ATOMbasetype(b2->ttype)) {
    2976           0 :                 GDKerror("incompatible input types.\n");
    2977           0 :                 return NULL;
    2978             :         }
    2979             : 
    2980        1747 :         canditer_init(&ci1, b1, s1);
    2981        1746 :         canditer_init(&ci2, b2, s2);
    2982        1747 :         if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
    2983           0 :                 GDKerror("inputs not the same size.\n");
    2984           0 :                 return NULL;
    2985             :         }
    2986             : 
    2987        1747 :         bn = COLnew(ci1.hseq, b1->ttype, ci1.ncand, TRANSIENT);
    2988        1746 :         if (bn == NULL)
    2989             :                 return NULL;
    2990        1746 :         if (ci1.ncand == 0)
    2991             :                 return bn;
    2992             : 
    2993         741 :         BATiter b1i = bat_iterator(b1);
    2994         741 :         BATiter b2i = bat_iterator(b2);
    2995        2222 :         nils = and_typeswitchloop(b1i.base, true,
    2996         741 :                                   b2i.base, true,
    2997         741 :                                   Tloc(bn, 0),
    2998         741 :                                   b1i.type,
    2999             :                                   &ci1, &ci2, b1->hseqbase, b2->hseqbase,
    3000         741 :                                   b1i.nonil && b2i.nonil,
    3001             :                                   __func__);
    3002         740 :         bat_iterator_end(&b1i);
    3003         741 :         bat_iterator_end(&b2i);
    3004             : 
    3005         741 :         if (nils == BUN_NONE) {
    3006           0 :                 BBPunfix(bn->batCacheid);
    3007           0 :                 return NULL;
    3008             :         }
    3009             : 
    3010         741 :         BATsetcount(bn, ci1.ncand);
    3011             : 
    3012         741 :         bn->tsorted = ci1.ncand <= 1 || nils == ci1.ncand;
    3013         741 :         bn->trevsorted = ci1.ncand <= 1 || nils == ci1.ncand;
    3014         741 :         bn->tkey = ci1.ncand <= 1;
    3015         741 :         bn->tnil = nils != 0;
    3016         741 :         bn->tnonil = nils == 0;
    3017             : 
    3018         741 :         TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
    3019             :                   ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
    3020             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    3021             :                   ALGOBATPAR(b1), ALGOBATPAR(b2),
    3022             :                   ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
    3023             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    3024             : 
    3025             :         return bn;
    3026             : }
    3027             : 
    3028             : BAT *
    3029         609 : BATcalcandcst(BAT *b, const ValRecord *v, BAT *s)
    3030             : {
    3031         609 :         lng t0 = 0;
    3032         609 :         BAT *bn;
    3033         609 :         BUN nils;
    3034         609 :         struct canditer ci;
    3035             : 
    3036         609 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    3037             : 
    3038         609 :         BATcheck(b, NULL);
    3039             : 
    3040        1745 :         if (ATOMbasetype(b->ttype) != ATOMbasetype(v->vtype)) {
    3041           0 :                 GDKerror("incompatible input types.\n");
    3042           0 :                 return NULL;
    3043             :         }
    3044             : 
    3045         609 :         canditer_init(&ci, b, s);
    3046             : 
    3047         609 :         if (b->ttype == TYPE_bit && v->vtype == TYPE_bit && v->val.btval == 0) {
    3048             :                 /* false AND anything (including NIL) equals false */
    3049          27 :                 return BATconstant(ci.hseq, TYPE_bit, &(bit){0},
    3050             :                                    ci.ncand, TRANSIENT);
    3051             :         }
    3052             : 
    3053         582 :         bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
    3054         583 :         if (bn == NULL)
    3055             :                 return NULL;
    3056         583 :         if (ci.ncand == 0)
    3057             :                 return bn;
    3058             : 
    3059          39 :         BATiter bi = bat_iterator(b);
    3060         117 :         nils = and_typeswitchloop(bi.base, true,
    3061             :                                   VALptr(v), false,
    3062          39 :                                   Tloc(bn, 0), bi.type,
    3063             :                                   &ci,
    3064          39 :                                   &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
    3065             :                                   b->hseqbase, 0,
    3066          39 :                                   bi.nonil && ATOMcmp(v->vtype, VALptr(v), ATOMnilptr(v->vtype)) != 0,
    3067             :                                   __func__);
    3068          39 :         bat_iterator_end(&bi);
    3069             : 
    3070          39 :         if (nils == BUN_NONE) {
    3071           0 :                 BBPunfix(bn->batCacheid);
    3072           0 :                 return NULL;
    3073             :         }
    3074             : 
    3075          39 :         BATsetcount(bn, ci.ncand);
    3076             : 
    3077          39 :         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
    3078          39 :         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
    3079          39 :         bn->tkey = ci.ncand <= 1;
    3080          39 :         bn->tnil = nils != 0;
    3081          39 :         bn->tnonil = nils == 0;
    3082             : 
    3083          39 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    3084             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    3085             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    3086             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    3087             : 
    3088             :         return bn;
    3089             : }
    3090             : 
    3091             : BAT *
    3092          13 : BATcalccstand(const ValRecord *v, BAT *b, BAT *s)
    3093             : {
    3094          13 :         return BATcalcandcst(b, v, s);
    3095             : }
    3096             : 
    3097             : gdk_return
    3098     2222833 : VARcalcand(ValPtr ret, const ValRecord *lft, const ValRecord *rgt)
    3099             : {
    3100     2222887 :         if (ATOMbasetype(lft->vtype) != ATOMbasetype(rgt->vtype)) {
    3101           0 :                 GDKerror("incompatible input types.\n");
    3102           0 :                 return GDK_FAIL;
    3103             :         }
    3104             : 
    3105     2222833 :         if (and_typeswitchloop(VALptr(lft), false,
    3106             :                                VALptr(rgt), false,
    3107             :                                VALget(ret), lft->vtype,
    3108     2222833 :                                &(struct canditer){.tpe=cand_dense, .ncand=1},
    3109     2222833 :                                &(struct canditer){.tpe=cand_dense, .ncand=1},
    3110             :                                0, 0, false, __func__) == BUN_NONE)
    3111           0 :                 return GDK_FAIL;
    3112     2222833 :         return GDK_SUCCEED;
    3113             : }
    3114             : 
    3115             : /* ---------------------------------------------------------------------- */
    3116             : /* left shift (any integral type) */
    3117             : 
    3118             : #define LSH(a, b)               ((a) << (b))
    3119             : 
    3120             : #define SHIFT_CHECK(a, b)       ((b) < 0 || (b) >= 8 * (int) sizeof(a))
    3121             : #define NO_SHIFT_CHECK(a, b)    0
    3122             : 
    3123             : /* In standard C, left shift is undefined if any of the following
    3124             :  * conditions hold:
    3125             :  * - right operand is negative or larger or equal to the width of the
    3126             :  *   left operand;
    3127             :  * - left operand is negative;
    3128             :  * - left operand times two-to-the-power of the right operand is not
    3129             :  *   representable in the (promoted) type of the left operand. */
    3130             : #define LSH_CHECK(a, b, TYPE)   (SHIFT_CHECK(a, b) || (a) < 0 || (a) > (GDK_##TYPE##_max >> (b)))
    3131             : #define LSH_CHECK_bte(a, b)     LSH_CHECK(a, b, bte)
    3132             : #define LSH_CHECK_sht(a, b)     LSH_CHECK(a, b, sht)
    3133             : #define LSH_CHECK_int(a, b)     LSH_CHECK(a, b, int)
    3134             : #define LSH_CHECK_lng(a, b)     LSH_CHECK(a, b, lng)
    3135             : 
    3136             : static BUN
    3137          17 : lsh_typeswitchloop(const void *lft, int tp1, bool incr1,
    3138             :                    const void *rgt, int tp2, bool incr2,
    3139             :                    void *restrict dst,
    3140             :                    struct canditer *restrict ci1,
    3141             :                    struct canditer *restrict ci2,
    3142             :                    oid candoff1, oid candoff2,
    3143             :                    const char *func)
    3144             : {
    3145          17 :         BUN i, j, k;
    3146          17 :         BUN nils = 0;
    3147             : 
    3148          17 :         lng timeoffset = 0;
    3149          17 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    3150          17 :         if (qry_ctx != NULL) {
    3151          17 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    3152             :         }
    3153             : 
    3154          17 :         tp1 = ATOMbasetype(tp1);
    3155          17 :         tp2 = ATOMbasetype(tp2);
    3156          17 :         switch (tp1) {
    3157           8 :         case TYPE_bte:
    3158           8 :                 switch (tp2) {
    3159           0 :                 case TYPE_bte:
    3160           0 :                         BINARY_3TYPE_FUNC_CHECK(bte, bte, bte, LSH,
    3161             :                                                 LSH_CHECK_bte);
    3162             :                         break;
    3163           0 :                 case TYPE_sht:
    3164           0 :                         BINARY_3TYPE_FUNC_CHECK(bte, sht, bte, LSH,
    3165             :                                                 LSH_CHECK_bte);
    3166             :                         break;
    3167           8 :                 case TYPE_int:
    3168          32 :                         BINARY_3TYPE_FUNC_CHECK(bte, int, bte, LSH,
    3169             :                                                 LSH_CHECK_bte);
    3170             :                         break;
    3171           0 :                 case TYPE_lng:
    3172           0 :                         BINARY_3TYPE_FUNC_CHECK(bte, lng, bte, LSH,
    3173             :                                                 LSH_CHECK_bte);
    3174             :                         break;
    3175             : #ifdef HAVE_HGE
    3176           0 :                 case TYPE_hge:
    3177           0 :                         BINARY_3TYPE_FUNC_CHECK(bte, hge, bte, LSH,
    3178             :                                                 SHIFT_CHECK);
    3179             :                         break;
    3180             : #endif
    3181           0 :                 default:
    3182           0 :                         goto unsupported;
    3183             :                 }
    3184             :                 break;
    3185           0 :         case TYPE_sht:
    3186           0 :                 switch (tp2) {
    3187           0 :                 case TYPE_bte:
    3188           0 :                         BINARY_3TYPE_FUNC_CHECK(sht, bte, sht, LSH,
    3189             :                                                 LSH_CHECK_sht);
    3190             :                         break;
    3191           0 :                 case TYPE_sht:
    3192           0 :                         BINARY_3TYPE_FUNC_CHECK(sht, sht, sht, LSH,
    3193             :                                                 LSH_CHECK_sht);
    3194             :                         break;
    3195           0 :                 case TYPE_int:
    3196           0 :                         BINARY_3TYPE_FUNC_CHECK(sht, int, sht, LSH,
    3197             :                                                 LSH_CHECK_sht);
    3198             :                         break;
    3199           0 :                 case TYPE_lng:
    3200           0 :                         BINARY_3TYPE_FUNC_CHECK(sht, lng, sht, LSH,
    3201             :                                                 LSH_CHECK_sht);
    3202             :                         break;
    3203             : #ifdef HAVE_HGE
    3204           0 :                 case TYPE_hge:
    3205           0 :                         BINARY_3TYPE_FUNC_CHECK(sht, hge, sht, LSH,
    3206             :                                                 SHIFT_CHECK);
    3207             :                         break;
    3208             : #endif
    3209           0 :                 default:
    3210           0 :                         goto unsupported;
    3211             :                 }
    3212             :                 break;
    3213           4 :         case TYPE_int:
    3214           4 :                 switch (tp2) {
    3215           0 :                 case TYPE_bte:
    3216           0 :                         BINARY_3TYPE_FUNC_CHECK(int, bte, int, LSH,
    3217             :                                                 LSH_CHECK_int);
    3218             :                         break;
    3219           0 :                 case TYPE_sht:
    3220           0 :                         BINARY_3TYPE_FUNC_CHECK(int, sht, int, LSH,
    3221             :                                                 LSH_CHECK_int);
    3222             :                         break;
    3223           4 :                 case TYPE_int:
    3224          16 :                         BINARY_3TYPE_FUNC_CHECK(int, int, int, LSH,
    3225             :                                                 LSH_CHECK_int);
    3226             :                         break;
    3227           0 :                 case TYPE_lng:
    3228           0 :                         BINARY_3TYPE_FUNC_CHECK(int, lng, int, LSH,
    3229             :                                                 LSH_CHECK_int);
    3230             :                         break;
    3231             : #ifdef HAVE_HGE
    3232           0 :                 case TYPE_hge:
    3233           0 :                         BINARY_3TYPE_FUNC_CHECK(int, hge, int, LSH,
    3234             :                                                 SHIFT_CHECK);
    3235             :                         break;
    3236             : #endif
    3237           0 :                 default:
    3238           0 :                         goto unsupported;
    3239             :                 }
    3240             :                 break;
    3241           2 :         case TYPE_lng:
    3242           2 :                 switch (tp2) {
    3243           0 :                 case TYPE_bte:
    3244           0 :                         BINARY_3TYPE_FUNC_CHECK(lng, bte, lng, LSH,
    3245             :                                                 LSH_CHECK_lng);
    3246             :                         break;
    3247           0 :                 case TYPE_sht:
    3248           0 :                         BINARY_3TYPE_FUNC_CHECK(lng, sht, lng, LSH,
    3249             :                                                 LSH_CHECK_lng);
    3250             :                         break;
    3251           2 :                 case TYPE_int:
    3252           8 :                         BINARY_3TYPE_FUNC_CHECK(lng, int, lng, LSH,
    3253             :                                                 LSH_CHECK_lng);
    3254             :                         break;
    3255           0 :                 case TYPE_lng:
    3256           0 :                         BINARY_3TYPE_FUNC_CHECK(lng, lng, lng, LSH,
    3257             :                                                 LSH_CHECK_lng);
    3258             :                         break;
    3259             : #ifdef HAVE_HGE
    3260           0 :                 case TYPE_hge:
    3261           0 :                         BINARY_3TYPE_FUNC_CHECK(lng, hge, lng, LSH,
    3262             :                                                 SHIFT_CHECK);
    3263             :                         break;
    3264             : #endif
    3265           0 :                 default:
    3266           0 :                         goto unsupported;
    3267             :                 }
    3268             :                 break;
    3269             : #ifdef HAVE_HGE
    3270           3 :         case TYPE_hge:
    3271           3 :                 switch (tp2) {
    3272           0 :                 case TYPE_bte:
    3273           0 :                         BINARY_3TYPE_FUNC_CHECK(hge, bte, hge, LSH,
    3274             :                                                 NO_SHIFT_CHECK);
    3275             :                         break;
    3276           0 :                 case TYPE_sht:
    3277           0 :                         BINARY_3TYPE_FUNC_CHECK(hge, sht, hge, LSH,
    3278             :                                                 SHIFT_CHECK);
    3279             :                         break;
    3280           3 :                 case TYPE_int:
    3281          12 :                         BINARY_3TYPE_FUNC_CHECK(hge, int, hge, LSH,
    3282             :                                                 SHIFT_CHECK);
    3283             :                         break;
    3284           0 :                 case TYPE_lng:
    3285           0 :                         BINARY_3TYPE_FUNC_CHECK(hge, lng, hge, LSH,
    3286             :                                                 SHIFT_CHECK);
    3287             :                         break;
    3288           0 :                 case TYPE_hge:
    3289           0 :                         BINARY_3TYPE_FUNC_CHECK(hge, hge, hge, LSH,
    3290             :                                                 SHIFT_CHECK);
    3291             :                         break;
    3292           0 :                 default:
    3293           0 :                         goto unsupported;
    3294             :                 }
    3295             :                 break;
    3296             : #endif
    3297           0 :         default:
    3298           0 :                 goto unsupported;
    3299             :         }
    3300             : 
    3301             :         return nils;
    3302             : 
    3303           0 :   unsupported:
    3304           0 :         GDKerror("%s: bad input types %s,%s.\n", func,
    3305             :                  ATOMname(tp1), ATOMname(tp2));
    3306             :   checkfail:
    3307             :         return BUN_NONE;
    3308             : }
    3309             : 
    3310             : BAT *
    3311           8 : BATcalclsh(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
    3312             : {
    3313           8 :         lng t0 = 0;
    3314           8 :         BAT *bn;
    3315           8 :         BUN nils;
    3316           8 :         struct canditer ci1, ci2;
    3317             : 
    3318           8 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    3319             : 
    3320           8 :         BATcheck(b1, NULL);
    3321           8 :         BATcheck(b2, NULL);
    3322             : 
    3323           8 :         canditer_init(&ci1, b1, s1);
    3324           8 :         canditer_init(&ci2, b2, s2);
    3325           8 :         if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
    3326           0 :                 GDKerror("inputs not the same size.\n");
    3327           0 :                 return NULL;
    3328             :         }
    3329             : 
    3330           8 :         bn = COLnew(ci1.hseq, b1->ttype, ci1.ncand, TRANSIENT);
    3331           8 :         if (bn == NULL)
    3332             :                 return NULL;
    3333           8 :         if (ci1.ncand == 0)
    3334             :                 return bn;
    3335             : 
    3336           6 :         BATiter b1i = bat_iterator(b1);
    3337           6 :         BATiter b2i = bat_iterator(b2);
    3338          12 :         nils = lsh_typeswitchloop(b1i.base, b1i.type, true,
    3339           6 :                                   b2i.base, b2i.type, true,
    3340           6 :                                   Tloc(bn, 0),
    3341             :                                   &ci1, &ci2, b1->hseqbase, b2->hseqbase,
    3342             :                                   __func__);
    3343           6 :         bat_iterator_end(&b1i);
    3344           6 :         bat_iterator_end(&b2i);
    3345             : 
    3346           6 :         if (nils == BUN_NONE) {
    3347           0 :                 BBPunfix(bn->batCacheid);
    3348           0 :                 return NULL;
    3349             :         }
    3350             : 
    3351           6 :         BATsetcount(bn, ci1.ncand);
    3352             : 
    3353           6 :         bn->tsorted = ci1.ncand <= 1 || nils == ci1.ncand;
    3354           6 :         bn->trevsorted = ci1.ncand <= 1 || nils == ci1.ncand;
    3355           6 :         bn->tkey = ci1.ncand <= 1;
    3356           6 :         bn->tnil = nils != 0;
    3357           6 :         bn->tnonil = nils == 0;
    3358             : 
    3359           6 :         TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
    3360             :                   ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
    3361             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    3362             :                   ALGOBATPAR(b1), ALGOBATPAR(b2),
    3363             :                   ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
    3364             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    3365             : 
    3366             :         return bn;
    3367             : }
    3368             : 
    3369             : BAT *
    3370           3 : BATcalclshcst(BAT *b, const ValRecord *v, BAT *s)
    3371             : {
    3372           3 :         lng t0 = 0;
    3373           3 :         BAT *bn;
    3374           3 :         BUN nils;
    3375           3 :         struct canditer ci;
    3376             : 
    3377           3 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    3378             : 
    3379           3 :         BATcheck(b, NULL);
    3380             : 
    3381           3 :         canditer_init(&ci, b, s);
    3382             : 
    3383           3 :         bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
    3384           3 :         if (bn == NULL)
    3385             :                 return NULL;
    3386           3 :         if (ci.ncand == 0)
    3387             :                 return bn;
    3388             : 
    3389           0 :         BATiter bi = bat_iterator(b);
    3390           0 :         nils = lsh_typeswitchloop(bi.base, bi.type, true,
    3391           0 :                                   VALptr(v), v->vtype, false,
    3392           0 :                                   Tloc(bn, 0),
    3393             :                                   &ci,
    3394           0 :                                   &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
    3395             :                                   b->hseqbase, 0,
    3396             :                                   __func__);
    3397           0 :         bat_iterator_end(&bi);
    3398             : 
    3399           0 :         if (nils == BUN_NONE) {
    3400           0 :                 BBPunfix(bn->batCacheid);
    3401           0 :                 return NULL;
    3402             :         }
    3403             : 
    3404           0 :         BATsetcount(bn, ci.ncand);
    3405             : 
    3406           0 :         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
    3407           0 :         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
    3408           0 :         bn->tkey = ci.ncand <= 1;
    3409           0 :         bn->tnil = nils != 0;
    3410           0 :         bn->tnonil = nils == 0;
    3411             : 
    3412           0 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    3413             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    3414             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    3415             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    3416             : 
    3417             :         return bn;
    3418             : }
    3419             : 
    3420             : BAT *
    3421           0 : BATcalccstlsh(const ValRecord *v, BAT *b, BAT *s)
    3422             : {
    3423           0 :         lng t0 = 0;
    3424           0 :         BAT *bn;
    3425           0 :         BUN nils;
    3426           0 :         struct canditer ci;
    3427             : 
    3428           0 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    3429             : 
    3430           0 :         BATcheck(b, NULL);
    3431             : 
    3432           0 :         canditer_init(&ci, b, s);
    3433             : 
    3434           0 :         bn = COLnew(ci.hseq, v->vtype, ci.ncand, TRANSIENT);
    3435           0 :         if (bn == NULL)
    3436             :                 return NULL;
    3437           0 :         if (ci.ncand == 0)
    3438             :                 return bn;
    3439             : 
    3440           0 :         BATiter bi = bat_iterator(b);
    3441           0 :         nils = lsh_typeswitchloop(VALptr(v), v->vtype, false,
    3442           0 :                                   bi.base, bi.type, true,
    3443           0 :                                   Tloc(bn, 0),
    3444           0 :                                   &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
    3445             :                                   &ci,
    3446             :                                   0, b->hseqbase,
    3447             :                                   __func__);
    3448           0 :         bat_iterator_end(&bi);
    3449             : 
    3450           0 :         if (nils == BUN_NONE) {
    3451           0 :                 BBPunfix(bn->batCacheid);
    3452           0 :                 return NULL;
    3453             :         }
    3454             : 
    3455           0 :         BATsetcount(bn, ci.ncand);
    3456             : 
    3457           0 :         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
    3458           0 :         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
    3459           0 :         bn->tkey = ci.ncand <= 1;
    3460           0 :         bn->tnil = nils != 0;
    3461           0 :         bn->tnonil = nils == 0;
    3462             : 
    3463           0 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    3464             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    3465             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    3466             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    3467             : 
    3468             :         return bn;
    3469             : }
    3470             : 
    3471             : gdk_return
    3472          11 : VARcalclsh(ValPtr ret, const ValRecord *lft, const ValRecord *rgt)
    3473             : {
    3474          11 :         ret->vtype = lft->vtype;
    3475          11 :         if (lsh_typeswitchloop(VALptr(lft), lft->vtype, false,
    3476          11 :                                VALptr(rgt), rgt->vtype, false,
    3477             :                                VALget(ret),
    3478          11 :                                &(struct canditer){.tpe=cand_dense, .ncand=1},
    3479          11 :                                &(struct canditer){.tpe=cand_dense, .ncand=1},
    3480             :                                0, 0, __func__) == BUN_NONE)
    3481           0 :                 return GDK_FAIL;
    3482          11 :         return GDK_SUCCEED;
    3483             : }
    3484             : 
    3485             : /* ---------------------------------------------------------------------- */
    3486             : /* right shift (any integral type) */
    3487             : 
    3488             : #define RSH(a, b)       ((a) >> (b))
    3489             : 
    3490             : static BUN
    3491          22 : rsh_typeswitchloop(const void *lft, int tp1, bool incr1,
    3492             :                    const void *rgt, int tp2, bool incr2,
    3493             :                    void *restrict dst,
    3494             :                    struct canditer *restrict ci1,
    3495             :                    struct canditer *restrict ci2,
    3496             :                    oid candoff1, oid candoff2,
    3497             :                    const char *restrict func)
    3498             : {
    3499          22 :         BUN i, j, k;
    3500          22 :         BUN nils = 0;
    3501             : 
    3502          22 :         lng timeoffset = 0;
    3503          22 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    3504          22 :         if (qry_ctx != NULL) {
    3505          22 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    3506             :         }
    3507             : 
    3508          22 :         tp1 = ATOMbasetype(tp1);
    3509          22 :         tp2 = ATOMbasetype(tp2);
    3510          22 :         switch (tp1) {
    3511           6 :         case TYPE_bte:
    3512           6 :                 switch (tp2) {
    3513           0 :                 case TYPE_bte:
    3514           0 :                         BINARY_3TYPE_FUNC_CHECK(bte, bte, bte, RSH,
    3515             :                                                 SHIFT_CHECK);
    3516             :                         break;
    3517           0 :                 case TYPE_sht:
    3518           0 :                         BINARY_3TYPE_FUNC_CHECK(bte, sht, bte, RSH,
    3519             :                                                 SHIFT_CHECK);
    3520             :                         break;
    3521           6 :                 case TYPE_int:
    3522          24 :                         BINARY_3TYPE_FUNC_CHECK(bte, int, bte, RSH,
    3523             :                                                 SHIFT_CHECK);
    3524             :                         break;
    3525           0 :                 case TYPE_lng:
    3526           0 :                         BINARY_3TYPE_FUNC_CHECK(bte, lng, bte, RSH,
    3527             :                                                 SHIFT_CHECK);
    3528             :                         break;
    3529             : #ifdef HAVE_HGE
    3530           0 :                 case TYPE_hge:
    3531           0 :                         BINARY_3TYPE_FUNC_CHECK(bte, hge, bte, RSH,
    3532             :                                                 SHIFT_CHECK);
    3533             :                         break;
    3534             : #endif
    3535           0 :                 default:
    3536           0 :                         goto unsupported;
    3537             :                 }
    3538             :                 break;
    3539           0 :         case TYPE_sht:
    3540           0 :                 switch (tp2) {
    3541           0 :                 case TYPE_bte:
    3542           0 :                         BINARY_3TYPE_FUNC_CHECK(sht, bte, sht, RSH,
    3543             :                                                 SHIFT_CHECK);
    3544             :                         break;
    3545           0 :                 case TYPE_sht:
    3546           0 :                         BINARY_3TYPE_FUNC_CHECK(sht, sht, sht, RSH,
    3547             :                                                 SHIFT_CHECK);
    3548             :                         break;
    3549           0 :                 case TYPE_int:
    3550           0 :                         BINARY_3TYPE_FUNC_CHECK(sht, int, sht, RSH,
    3551             :                                                 SHIFT_CHECK);
    3552             :                         break;
    3553           0 :                 case TYPE_lng:
    3554           0 :                         BINARY_3TYPE_FUNC_CHECK(sht, lng, sht, RSH,
    3555             :                                                 SHIFT_CHECK);
    3556             :                         break;
    3557             : #ifdef HAVE_HGE
    3558           0 :                 case TYPE_hge:
    3559           0 :                         BINARY_3TYPE_FUNC_CHECK(sht, hge, sht, RSH,
    3560             :                                                 SHIFT_CHECK);
    3561             :                         break;
    3562             : #endif
    3563           0 :                 default:
    3564           0 :                         goto unsupported;
    3565             :                 }
    3566             :                 break;
    3567          12 :         case TYPE_int:
    3568          12 :                 switch (tp2) {
    3569           0 :                 case TYPE_bte:
    3570           0 :                         BINARY_3TYPE_FUNC_CHECK(int, bte, int, RSH,
    3571             :                                                 SHIFT_CHECK);
    3572             :                         break;
    3573           0 :                 case TYPE_sht:
    3574           0 :                         BINARY_3TYPE_FUNC_CHECK(int, sht, int, RSH,
    3575             :                                                 SHIFT_CHECK);
    3576             :                         break;
    3577          12 :                 case TYPE_int:
    3578          68 :                         BINARY_3TYPE_FUNC_CHECK(int, int, int, RSH,
    3579             :                                                 SHIFT_CHECK);
    3580             :                         break;
    3581           0 :                 case TYPE_lng:
    3582           0 :                         BINARY_3TYPE_FUNC_CHECK(int, lng, int, RSH,
    3583             :                                                 SHIFT_CHECK);
    3584             :                         break;
    3585             : #ifdef HAVE_HGE
    3586           0 :                 case TYPE_hge:
    3587           0 :                         BINARY_3TYPE_FUNC_CHECK(int, hge, int, RSH,
    3588             :                                                 SHIFT_CHECK);
    3589             :                         break;
    3590             : #endif
    3591           0 :                 default:
    3592           0 :                         goto unsupported;
    3593             :                 }
    3594             :                 break;
    3595           1 :         case TYPE_lng:
    3596           1 :                 switch (tp2) {
    3597           0 :                 case TYPE_bte:
    3598           0 :                         BINARY_3TYPE_FUNC_CHECK(lng, bte, lng, RSH,
    3599             :                                                 SHIFT_CHECK);
    3600             :                         break;
    3601           0 :                 case TYPE_sht:
    3602           0 :                         BINARY_3TYPE_FUNC_CHECK(lng, sht, lng, RSH,
    3603             :                                                 SHIFT_CHECK);
    3604             :                         break;
    3605           1 :                 case TYPE_int:
    3606           4 :                         BINARY_3TYPE_FUNC_CHECK(lng, int, lng, RSH,
    3607             :                                                 SHIFT_CHECK);
    3608             :                         break;
    3609           0 :                 case TYPE_lng:
    3610           0 :                         BINARY_3TYPE_FUNC_CHECK(lng, lng, lng, RSH,
    3611             :                                                 SHIFT_CHECK);
    3612             :                         break;
    3613             : #ifdef HAVE_HGE
    3614           0 :                 case TYPE_hge:
    3615           0 :                         BINARY_3TYPE_FUNC_CHECK(lng, hge, lng, RSH,
    3616             :                                                 SHIFT_CHECK);
    3617             :                         break;
    3618             : #endif
    3619           0 :                 default:
    3620           0 :                         goto unsupported;
    3621             :                 }
    3622             :                 break;
    3623             : #ifdef HAVE_HGE
    3624           3 :         case TYPE_hge:
    3625           3 :                 switch (tp2) {
    3626           0 :                 case TYPE_bte:
    3627           0 :                         BINARY_3TYPE_FUNC_CHECK(hge, bte, hge, RSH,
    3628             :                                                 NO_SHIFT_CHECK);
    3629             :                         break;
    3630           0 :                 case TYPE_sht:
    3631           0 :                         BINARY_3TYPE_FUNC_CHECK(hge, sht, hge, RSH,
    3632             :                                                 SHIFT_CHECK);
    3633             :                         break;
    3634           3 :                 case TYPE_int:
    3635          12 :                         BINARY_3TYPE_FUNC_CHECK(hge, int, hge, RSH,
    3636             :                                                 SHIFT_CHECK);
    3637             :                         break;
    3638           0 :                 case TYPE_lng:
    3639           0 :                         BINARY_3TYPE_FUNC_CHECK(hge, lng, hge, RSH,
    3640             :                                                 SHIFT_CHECK);
    3641             :                         break;
    3642           0 :                 case TYPE_hge:
    3643           0 :                         BINARY_3TYPE_FUNC_CHECK(hge, hge, hge, RSH,
    3644             :                                                 SHIFT_CHECK);
    3645             :                         break;
    3646           0 :                 default:
    3647           0 :                         goto unsupported;
    3648             :                 }
    3649             :                 break;
    3650             : #endif
    3651           0 :         default:
    3652           0 :                 goto unsupported;
    3653             :         }
    3654             : 
    3655             :         return nils;
    3656             : 
    3657           0 :   unsupported:
    3658           0 :         GDKerror("%s: bad input types %s,%s.\n", func,
    3659             :                  ATOMname(tp1), ATOMname(tp2));
    3660             :   checkfail:
    3661             :         return BUN_NONE;
    3662             : }
    3663             : 
    3664             : BAT *
    3665           2 : BATcalcrsh(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
    3666             : {
    3667           2 :         lng t0 = 0;
    3668           2 :         BAT *bn;
    3669           2 :         BUN nils;
    3670           2 :         struct canditer ci1, ci2;
    3671             : 
    3672           2 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    3673             : 
    3674           2 :         BATcheck(b1, NULL);
    3675           2 :         BATcheck(b2, NULL);
    3676             : 
    3677           2 :         canditer_init(&ci1, b1, s1);
    3678           2 :         canditer_init(&ci2, b2, s2);
    3679           2 :         if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
    3680           0 :                 GDKerror("inputs not the same size.\n");
    3681           0 :                 return NULL;
    3682             :         }
    3683             : 
    3684           2 :         bn = COLnew(ci1.hseq, b1->ttype, ci1.ncand, TRANSIENT);
    3685           2 :         if (bn == NULL)
    3686             :                 return NULL;
    3687           2 :         if (ci1.ncand == 0)
    3688             :                 return bn;
    3689             : 
    3690           0 :         BATiter b1i = bat_iterator(b1);
    3691           0 :         BATiter b2i = bat_iterator(b2);
    3692           0 :         nils = rsh_typeswitchloop(b1i.base, b1i.type, true,
    3693           0 :                                   b2i.base, b2i.type, true,
    3694           0 :                                   Tloc(bn, 0),
    3695             :                                   &ci1, &ci2, b1->hseqbase, b2->hseqbase,
    3696             :                                   __func__);
    3697           0 :         bat_iterator_end(&b1i);
    3698           0 :         bat_iterator_end(&b2i);
    3699             : 
    3700           0 :         if (nils == BUN_NONE) {
    3701           0 :                 BBPunfix(bn->batCacheid);
    3702           0 :                 return NULL;
    3703             :         }
    3704             : 
    3705           0 :         BATsetcount(bn, ci1.ncand);
    3706             : 
    3707           0 :         bn->tsorted = ci1.ncand <= 1 || nils == ci1.ncand;
    3708           0 :         bn->trevsorted = ci1.ncand <= 1 || nils == ci1.ncand;
    3709           0 :         bn->tkey = ci1.ncand <= 1;
    3710           0 :         bn->tnil = nils != 0;
    3711           0 :         bn->tnonil = nils == 0;
    3712             : 
    3713           0 :         TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
    3714             :                   ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
    3715             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    3716             :                   ALGOBATPAR(b1), ALGOBATPAR(b2),
    3717             :                   ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
    3718             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    3719             : 
    3720             :         return bn;
    3721             : }
    3722             : 
    3723             : BAT *
    3724         220 : BATcalcrshcst(BAT *b, const ValRecord *v, BAT *s)
    3725             : {
    3726         220 :         lng t0 = 0;
    3727         220 :         BAT *bn;
    3728         220 :         BUN nils;
    3729         220 :         struct canditer ci;
    3730             : 
    3731         220 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    3732             : 
    3733         220 :         BATcheck(b, NULL);
    3734             : 
    3735         220 :         canditer_init(&ci, b, s);
    3736             : 
    3737         220 :         bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
    3738         220 :         if (bn == NULL)
    3739             :                 return NULL;
    3740         220 :         if (ci.ncand == 0)
    3741             :                 return bn;
    3742             : 
    3743          10 :         BATiter bi = bat_iterator(b);
    3744          20 :         nils = rsh_typeswitchloop(bi.base, bi.type, true,
    3745          10 :                                   VALptr(v), v->vtype, false,
    3746          10 :                                   Tloc(bn, 0),
    3747             :                                   &ci,
    3748          10 :                                   &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
    3749             :                                   b->hseqbase, 0,
    3750             :                                   __func__);
    3751          10 :         bat_iterator_end(&bi);
    3752             : 
    3753          10 :         if (nils == BUN_NONE) {
    3754           0 :                 BBPunfix(bn->batCacheid);
    3755           0 :                 return NULL;
    3756             :         }
    3757             : 
    3758          10 :         BATsetcount(bn, ci.ncand);
    3759             : 
    3760          10 :         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
    3761          10 :         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
    3762          10 :         bn->tkey = ci.ncand <= 1;
    3763          10 :         bn->tnil = nils != 0;
    3764          10 :         bn->tnonil = nils == 0;
    3765             : 
    3766          10 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    3767             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    3768             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    3769             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    3770             : 
    3771             :         return bn;
    3772             : }
    3773             : 
    3774             : BAT *
    3775           1 : BATcalccstrsh(const ValRecord *v, BAT *b, BAT *s)
    3776             : {
    3777           1 :         lng t0 = 0;
    3778           1 :         BAT *bn;
    3779           1 :         BUN nils;
    3780           1 :         struct canditer ci;
    3781             : 
    3782           1 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    3783             : 
    3784           1 :         BATcheck(b, NULL);
    3785             : 
    3786           1 :         canditer_init(&ci, b, s);
    3787             : 
    3788           1 :         bn = COLnew(ci.hseq, v->vtype, ci.ncand, TRANSIENT);
    3789           1 :         if (bn == NULL)
    3790             :                 return NULL;
    3791           1 :         if (ci.ncand == 0)
    3792             :                 return bn;
    3793             : 
    3794           1 :         BATiter bi = bat_iterator(b);
    3795           2 :         nils = rsh_typeswitchloop(VALptr(v), v->vtype, false,
    3796           1 :                                   bi.base, bi.type, true,
    3797           1 :                                   Tloc(bn, 0),
    3798           1 :                                   &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
    3799             :                                   &ci,
    3800             :                                   0, b->hseqbase,
    3801             :                                   __func__);
    3802           1 :         bat_iterator_end(&bi);
    3803             : 
    3804           1 :         if (nils == BUN_NONE) {
    3805           0 :                 BBPunfix(bn->batCacheid);
    3806           0 :                 return NULL;
    3807             :         }
    3808             : 
    3809           1 :         BATsetcount(bn, ci.ncand);
    3810             : 
    3811           1 :         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
    3812           1 :         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
    3813           1 :         bn->tkey = ci.ncand <= 1;
    3814           1 :         bn->tnil = nils != 0;
    3815           1 :         bn->tnonil = nils == 0;
    3816             : 
    3817           1 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    3818             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    3819             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    3820             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    3821             : 
    3822             :         return bn;
    3823             : }
    3824             : 
    3825             : gdk_return
    3826          11 : VARcalcrsh(ValPtr ret, const ValRecord *lft, const ValRecord *rgt)
    3827             : {
    3828          11 :         ret->vtype = lft->vtype;
    3829          11 :         if (rsh_typeswitchloop(VALptr(lft), lft->vtype, false,
    3830          11 :                                VALptr(rgt), rgt->vtype, false,
    3831             :                                VALget(ret),
    3832          11 :                                &(struct canditer){.tpe=cand_dense, .ncand=1},
    3833          11 :                                &(struct canditer){.tpe=cand_dense, .ncand=1},
    3834             :                                0, 0, __func__) == BUN_NONE)
    3835           1 :                 return GDK_FAIL;
    3836          10 :         return GDK_SUCCEED;
    3837             : }
    3838             : 
    3839             : /* ---------------------------------------------------------------------- */
    3840             : /* between (any "linear" type) */
    3841             : 
    3842             : #define LTbte(a,b)      ((a) < (b))
    3843             : #define LTsht(a,b)      ((a) < (b))
    3844             : #define LTint(a,b)      ((a) < (b))
    3845             : #define LTlng(a,b)      ((a) < (b))
    3846             : #define LThge(a,b)      ((a) < (b))
    3847             : #define LToid(a,b)      ((a) < (b))
    3848             : #define LTflt(a,b)      ((a) < (b))
    3849             : #define LTdbl(a,b)      ((a) < (b))
    3850             : #define LTany(a,b)      ((*atomcmp)(a, b) < 0)
    3851             : #define EQbte(a,b)      ((a) == (b))
    3852             : #define EQsht(a,b)      ((a) == (b))
    3853             : #define EQint(a,b)      ((a) == (b))
    3854             : #define EQlng(a,b)      ((a) == (b))
    3855             : #define EQhge(a,b)      ((a) == (b))
    3856             : #define EQoid(a,b)      ((a) == (b))
    3857             : #define EQflt(a,b)      ((a) == (b))
    3858             : #define EQdbl(a,b)      ((a) == (b))
    3859             : #define EQany(a,b)      ((*atomcmp)(a, b) == 0)
    3860             : 
    3861             : #define is_any_nil(v)   ((v) == NULL || (*atomcmp)((v), nil) == 0)
    3862             : 
    3863             : #define less3(a,b,i,t)  (is_##t##_nil(a) || is_##t##_nil(b) ? bit_nil : LT##t(a, b) || (i && EQ##t(a, b)))
    3864             : #define grtr3(a,b,i,t)  (is_##t##_nil(a) || is_##t##_nil(b) ? bit_nil : LT##t(b, a) || (i && EQ##t(a, b)))
    3865             : #define not3(a)         (is_bit_nil(a) ? bit_nil : !(a))
    3866             : 
    3867             : #define between3(v, lo, linc, hi, hinc, TYPE)                           \
    3868             :         and3(grtr3(v, lo, linc, TYPE), less3(v, hi, hinc, TYPE))
    3869             : 
    3870             : #define BETWEEN(v, lo, hi, TYPE)                                        \
    3871             :         (is_##TYPE##_nil(v)                                             \
    3872             :          ? nils_false ? 0 : bit_nil                                     \
    3873             :          : (bit) (anti                                                  \
    3874             :                   ? (symmetric                                          \
    3875             :                      ? not3(or3(between3(v, lo, linc, hi, hinc, TYPE),  \
    3876             :                                 between3(v, hi, hinc, lo, linc, TYPE))) \
    3877             :                      : not3(between3(v, lo, linc, hi, hinc, TYPE)))     \
    3878             :                   : (symmetric                                          \
    3879             :                      ? or3(between3(v, lo, linc, hi, hinc, TYPE),       \
    3880             :                            between3(v, hi, hinc, lo, linc, TYPE))       \
    3881             :                      : between3(v, lo, linc, hi, hinc, TYPE))))
    3882             : 
    3883             : #define BETWEEN_LOOP_TYPE(TYPE, canditer_next)                          \
    3884             :         do {                                                            \
    3885             :                 i = j = k = 0;                                          \
    3886             :                 TIMEOUT_LOOP_IDX(l, ncand, timeoffset) {                \
    3887             :                         if (incr1)                                      \
    3888             :                                 i = canditer_next(ci) - seqbase1;       \
    3889             :                         if (incr2)                                      \
    3890             :                                 j = canditer_next(cilo) - seqbase2;     \
    3891             :                         if (incr3)                                      \
    3892             :                                 k = canditer_next(cihi) - seqbase3;     \
    3893             :                         dst[l] = BETWEEN(((const TYPE *) src)[i],       \
    3894             :                                          ((const TYPE *) lo)[j],        \
    3895             :                                          ((const TYPE *) hi)[k],        \
    3896             :                                          TYPE);                         \
    3897             :                         nils += is_bit_nil(dst[l]);                     \
    3898             :                 }                                                       \
    3899             :                 TIMEOUT_CHECK(timeoffset,                               \
    3900             :                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));     \
    3901             :         } while (0)
    3902             : 
    3903             : static BAT *
    3904       13008 : BATcalcbetween_intern(const void *src, bool incr1, const char *hp1, int wd1,
    3905             :                       const void *lo, bool incr2, const char *hp2, int wd2,
    3906             :                       const void *hi, bool incr3, const char *hp3, int wd3,
    3907             :                       int tp,
    3908             :                       struct canditer *restrict ci,
    3909             :                       struct canditer *restrict cilo,
    3910             :                       struct canditer *restrict cihi,
    3911             :                       oid seqbase1, oid seqbase2, oid seqbase3,
    3912             :                       bool symmetric, bool anti,
    3913             :                       bool linc, bool hinc, bool nils_false, const char *func)
    3914             : {
    3915       13008 :         BAT *bn;
    3916       13008 :         BUN nils = 0;
    3917       13008 :         BUN i, j, k, l, ncand = ci->ncand;
    3918       13008 :         bit *restrict dst;
    3919       13008 :         const void *nil;
    3920       13008 :         int (*atomcmp)(const void *, const void *);
    3921             : 
    3922       13008 :         lng timeoffset = 0;
    3923       13008 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    3924       13008 :         if (qry_ctx != NULL) {
    3925       13008 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    3926             :         }
    3927             : 
    3928       13008 :         bn = COLnew(ci->hseq, TYPE_bit, ncand, TRANSIENT);
    3929       13008 :         if (bn == NULL)
    3930             :                 return NULL;
    3931       13008 :         if (ncand == 0)
    3932             :                 return bn;
    3933             : 
    3934       12302 :         dst = (bit *) Tloc(bn, 0);
    3935             : 
    3936       12302 :         tp = ATOMbasetype(tp);
    3937             : 
    3938       12302 :         switch (tp) {
    3939          41 :         case TYPE_bte:
    3940          41 :                 if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
    3941         299 :                         BETWEEN_LOOP_TYPE(bte, canditer_next_dense);
    3942             :                 else
    3943           8 :                         BETWEEN_LOOP_TYPE(bte, canditer_next);
    3944             :                 break;
    3945           4 :         case TYPE_sht:
    3946           4 :                 if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
    3947         112 :                         BETWEEN_LOOP_TYPE(sht, canditer_next_dense);
    3948             :                 else
    3949           0 :                         BETWEEN_LOOP_TYPE(sht, canditer_next);
    3950             :                 break;
    3951        3511 :         case TYPE_int:
    3952        3511 :                 if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
    3953       99940 :                         BETWEEN_LOOP_TYPE(int, canditer_next_dense);
    3954             :                 else
    3955          16 :                         BETWEEN_LOOP_TYPE(int, canditer_next);
    3956             :                 break;
    3957        6006 :         case TYPE_lng:
    3958        6006 :                 if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
    3959    59555273 :                         BETWEEN_LOOP_TYPE(lng, canditer_next_dense);
    3960             :                 else
    3961        1151 :                         BETWEEN_LOOP_TYPE(lng, canditer_next);
    3962             :                 break;
    3963             : #ifdef HAVE_HGE
    3964        2629 :         case TYPE_hge:
    3965        2629 :                 if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
    3966       27925 :                         BETWEEN_LOOP_TYPE(hge, canditer_next_dense);
    3967             :                 else
    3968        1096 :                         BETWEEN_LOOP_TYPE(hge, canditer_next);
    3969             :                 break;
    3970             : #endif
    3971           2 :         case TYPE_flt:
    3972           2 :                 if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
    3973          30 :                         BETWEEN_LOOP_TYPE(flt, canditer_next_dense);
    3974             :                 else
    3975           0 :                         BETWEEN_LOOP_TYPE(flt, canditer_next);
    3976             :                 break;
    3977          65 :         case TYPE_dbl:
    3978          65 :                 if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
    3979       13107 :                         BETWEEN_LOOP_TYPE(dbl, canditer_next_dense);
    3980             :                 else
    3981           4 :                         BETWEEN_LOOP_TYPE(dbl, canditer_next);
    3982             :                 break;
    3983          44 :         default:
    3984          44 :                 assert(tp != TYPE_oid);
    3985          44 :                 if (!ATOMlinear(tp) ||
    3986          44 :                     (atomcmp = ATOMcompare(tp)) == NULL) {
    3987           0 :                         BBPunfix(bn->batCacheid);
    3988           0 :                         GDKerror("%s: bad input type %s.\n",
    3989             :                                  func, ATOMname(tp));
    3990           0 :                         return NULL;
    3991             :                 }
    3992          44 :                 nil = ATOMnilptr(tp);
    3993          44 :                 i = j = k = 0;
    3994         296 :                 TIMEOUT_LOOP_IDX(l, ncand, timeoffset) {
    3995         167 :                         if (incr1)
    3996         167 :                                 i = canditer_next(ci) - seqbase1;
    3997         167 :                         if (incr2)
    3998         152 :                                 j = canditer_next(cilo) - seqbase2;
    3999         167 :                         if (incr3)
    4000         157 :                                 k = canditer_next(cihi) - seqbase3;
    4001         167 :                         const void *p1, *p2, *p3;
    4002         333 :                         p1 = hp1
    4003         163 :                                 ? (const void *) (hp1 + VarHeapVal(src, i, wd1))
    4004         329 :                                 : (const void *) ((const char *) src + i * wd1);
    4005         332 :                         p2 = hp2
    4006         148 :                                 ? (const void *) (hp2 + VarHeapVal(lo, j, wd2))
    4007         314 :                                 : (const void *) ((const char *) lo + j * wd2);
    4008         332 :                         p3 = hp3
    4009         152 :                                 ? (const void *) (hp3 + VarHeapVal(hi, k, wd3))
    4010         318 :                                 : (const void *) ((const char *) hi + k * wd3);
    4011         166 :                         dst[l] = BETWEEN(p1, p2, p3, any);
    4012         166 :                         nils += is_bit_nil(dst[l]);
    4013             :                 }
    4014          43 :                 TIMEOUT_CHECK(timeoffset,
    4015             :                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    4016             :                 break;
    4017             :         }
    4018             : 
    4019       12294 :         BATsetcount(bn, ncand);
    4020             : 
    4021       12299 :         bn->tsorted = ncand <= 1 || nils == ncand;
    4022       12299 :         bn->trevsorted = ncand <= 1 || nils == ncand;
    4023       12299 :         bn->tkey = ncand <= 1;
    4024       12299 :         bn->tnil = nils != 0;
    4025       12299 :         bn->tnonil = nils == 0;
    4026             : 
    4027       12299 :         return bn;
    4028           0 : bailout:
    4029           0 :         BBPunfix(bn->batCacheid);
    4030           0 :         return NULL;
    4031             : }
    4032             : 
    4033             : #define HANDLE_TIMEOUT                                                  \
    4034             :         do {                                                            \
    4035             :                 GDKerror("%s\n", GDKexiting() ? EXITING_MSG : TIMEOUT_MSG); \
    4036             :                 BBPreclaim(bn);                                         \
    4037             :                 bn = NULL;                                              \
    4038             :         } while (0)
    4039             : 
    4040             : BAT *
    4041       12751 : BATcalcbetween(BAT *b, BAT *lo, BAT *hi, BAT *s, BAT *slo, BAT *shi,
    4042             :                bool symmetric, bool linc, bool hinc, bool nils_false, bool anti)
    4043             : {
    4044       12751 :         lng t0 = 0;
    4045       12751 :         BAT *bn;
    4046       12751 :         struct canditer ci, cilo, cihi;
    4047             : 
    4048       12751 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4049             : 
    4050       12751 :         BATcheck(b, NULL);
    4051       12751 :         BATcheck(lo, NULL);
    4052       12751 :         BATcheck(hi, NULL);
    4053             : 
    4054       12751 :         canditer_init(&ci, b, s);
    4055       12750 :         canditer_init(&cilo, lo, slo);
    4056       12749 :         canditer_init(&cihi, hi, shi);
    4057       12750 :         if (ci.ncand != cilo.ncand || ci.hseq != cilo.hseq ||
    4058       12750 :             ci.ncand != cihi.ncand || ci.hseq != cihi.hseq) {
    4059           0 :                 GDKerror("inputs not the same size.\n");
    4060           0 :                 return NULL;
    4061             :         }
    4062             : 
    4063       12750 :         if (BATtvoid(b) &&
    4064           0 :             BATtvoid(lo) &&
    4065           0 :             BATtvoid(hi)) {
    4066           0 :                 bit res;
    4067             : 
    4068           0 :                 res = BETWEEN(b->tseqbase, lo->tseqbase, hi->tseqbase, oid);
    4069           0 :                 return BATconstant(ci.hseq, TYPE_bit, &res, ci.ncand,
    4070             :                                    TRANSIENT);
    4071             :         }
    4072             : 
    4073       12750 :         BATiter bi = bat_iterator(b);
    4074       12750 :         BATiter loi = bat_iterator(lo);
    4075       12751 :         BATiter hii = bat_iterator(hi);
    4076       12750 :         if (b->ttype == TYPE_void || lo->ttype == TYPE_void || hi->ttype == TYPE_void) {
    4077           0 :                 lng timeoffset = 0;
    4078           0 :                 QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    4079           0 :                 if (qry_ctx != NULL) {
    4080           0 :                         timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    4081             :                 }
    4082           0 :                 bn = COLnew(ci.seq, TYPE_bit, ci.ncand, TRANSIENT);
    4083           0 :                 if (bn) {
    4084           0 :                         bit *restrict dst = (bit *) Tloc(bn, 0);
    4085           0 :                         BUN i, j, k, l;
    4086           0 :                         BUN nils = 0;
    4087           0 :                         TIMEOUT_LOOP_IDX(l, ci.ncand, timeoffset) {
    4088           0 :                                 i = canditer_next(&ci) - b->hseqbase;
    4089           0 :                                 j = canditer_next(&cilo) - lo->hseqbase;
    4090           0 :                                 k = canditer_next(&cihi) - hi->hseqbase;
    4091           0 :                                 dst[l] = BETWEEN(BUNtoid(b, i),
    4092             :                                                  BUNtoid(lo, j),
    4093             :                                                  BUNtoid(hi, k), oid);
    4094           0 :                                 nils += is_bit_nil(dst[l]);
    4095             :                         }
    4096           0 :                         BATsetcount(bn, ci.ncand);
    4097           0 :                         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
    4098           0 :                         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
    4099           0 :                         bn->tkey = ci.ncand <= 1;
    4100           0 :                         bn->tnil = nils != 0;
    4101           0 :                         bn->tnonil = nils == 0;
    4102           0 :                         TIMEOUT_CHECK(timeoffset, HANDLE_TIMEOUT);
    4103             :                 }
    4104             :         } else {
    4105       12836 :                 bn = BATcalcbetween_intern(bi.base, 1,
    4106       12750 :                                            bi.vh ? bi.vh->base : NULL,
    4107       12750 :                                            bi.width,
    4108       12750 :                                            loi.base, 1,
    4109       12750 :                                            loi.vh ? loi.vh->base : NULL,
    4110       12750 :                                            loi.width,
    4111       12750 :                                            hii.base, 1,
    4112       12750 :                                            hii.vh ? hii.vh->base : NULL,
    4113       12750 :                                            hii.width,
    4114       12750 :                                            bi.type,
    4115             :                                            &ci, &cilo, &cihi,
    4116             :                                            b->hseqbase, lo->hseqbase, hi->hseqbase,
    4117             :                                            symmetric, anti, linc, hinc,
    4118             :                                            nils_false, __func__);
    4119             :         }
    4120       12749 :         bat_iterator_end(&bi);
    4121       12750 :         bat_iterator_end(&loi);
    4122       12748 :         bat_iterator_end(&hii);
    4123             : 
    4124       12750 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",lo=" ALGOBATFMT ",hi=" ALGOBATFMT
    4125             :                   ",s=" ALGOOPTBATFMT ",slo=" ALGOOPTBATFMT ",shi=" ALGOOPTBATFMT
    4126             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    4127             :                   ALGOBATPAR(b), ALGOBATPAR(lo), ALGOBATPAR(hi),
    4128             :                   ALGOOPTBATPAR(s), ALGOOPTBATPAR(slo), ALGOOPTBATPAR(shi),
    4129             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    4130             : 
    4131             :         return bn;
    4132             : }
    4133             : 
    4134             : BAT *
    4135         167 : BATcalcbetweencstcst(BAT *b, const ValRecord *lo, const ValRecord *hi,
    4136             :                      BAT *s,
    4137             :                      bool symmetric, bool linc, bool hinc, bool nils_false,
    4138             :                      bool anti)
    4139             : {
    4140         167 :         lng t0 = 0;
    4141         167 :         BAT *bn;
    4142         167 :         struct canditer ci;
    4143             : 
    4144         167 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4145             : 
    4146         167 :         BATcheck(b, NULL);
    4147             : 
    4148         470 :         if (ATOMbasetype(b->ttype) != ATOMbasetype(lo->vtype) ||
    4149         235 :             ATOMbasetype(b->ttype) != ATOMbasetype(hi->vtype)) {
    4150           0 :                 GDKerror("incompatible input types.\n");
    4151           0 :                 return NULL;
    4152             :         }
    4153             : 
    4154         167 :         canditer_init(&ci, b, s);
    4155             : 
    4156         167 :         BATiter bi = bat_iterator(b);
    4157         167 :         if (b->ttype == TYPE_void) {
    4158           0 :                 lng timeoffset = 0;
    4159           0 :                 QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    4160           0 :                 if (qry_ctx != NULL) {
    4161           0 :                         timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    4162             :                 }
    4163           0 :                 bn = COLnew(ci.seq, TYPE_bit, ci.ncand, TRANSIENT);
    4164           0 :                 if (bn) {
    4165           0 :                         bit *restrict dst = (bit *) Tloc(bn, 0);
    4166           0 :                         BUN i, l;
    4167           0 :                         BUN nils = 0;
    4168           0 :                         TIMEOUT_LOOP_IDX(l, ci.ncand, timeoffset) {
    4169           0 :                                 i = canditer_next(&ci) - b->hseqbase;
    4170           0 :                                 dst[l] = BETWEEN(BUNtoid(b, i), lo->val.oval,
    4171             :                                                  hi->val.oval, oid);
    4172           0 :                                 nils += is_bit_nil(dst[l]);
    4173             :                         }
    4174           0 :                         BATsetcount(bn, ci.ncand);
    4175           0 :                         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
    4176           0 :                         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
    4177           0 :                         bn->tkey = ci.ncand <= 1;
    4178           0 :                         bn->tnil = nils != 0;
    4179           0 :                         bn->tnonil = nils == 0;
    4180           0 :                         TIMEOUT_CHECK(timeoffset, HANDLE_TIMEOUT);
    4181             :                 }
    4182             :         } else {
    4183         167 :                 bn = BATcalcbetween_intern(bi.base, 1,
    4184         167 :                                            bi.vh ? bi.vh->base : NULL,
    4185         167 :                                            bi.width,
    4186             :                                            VALptr(lo), 0, NULL, 0,
    4187             :                                            VALptr(hi), 0, NULL, 0,
    4188         167 :                                            bi.type,
    4189             :                                            &ci,
    4190         167 :                                            &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
    4191         167 :                                            &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
    4192             :                                            b->hseqbase, 0, 0, symmetric, anti,
    4193             :                                            linc, hinc, nils_false,
    4194             :                                            __func__);
    4195             :         }
    4196         167 :         bat_iterator_end(&bi);
    4197             : 
    4198         167 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    4199             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    4200             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    4201             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    4202             : 
    4203             :         return bn;
    4204             : }
    4205             : 
    4206             : BAT *
    4207          48 : BATcalcbetweenbatcst(BAT *b, BAT *lo, const ValRecord *hi, BAT *s, BAT *slo,
    4208             :                      bool symmetric, bool linc, bool hinc, bool nils_false,
    4209             :                      bool anti)
    4210             : {
    4211          48 :         lng t0 = 0;
    4212          48 :         BAT *bn;
    4213          48 :         struct canditer ci, cilo;
    4214             : 
    4215          48 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4216             : 
    4217          48 :         BATcheck(b, NULL);
    4218          48 :         BATcheck(lo, NULL);
    4219             : 
    4220         132 :         if (ATOMbasetype(b->ttype) != ATOMbasetype(hi->vtype)) {
    4221           0 :                 GDKerror("incompatible input types.\n");
    4222           0 :                 return NULL;
    4223             :         }
    4224             : 
    4225          48 :         canditer_init(&ci, b, s);
    4226          48 :         canditer_init(&cilo, lo, slo);
    4227          48 :         if (ci.ncand != cilo.ncand || ci.hseq != cilo.hseq) {
    4228           0 :                 GDKerror("inputs not the same size.\n");
    4229           0 :                 return NULL;
    4230             :         }
    4231             : 
    4232          48 :         BATiter bi = bat_iterator(b);
    4233          48 :         BATiter loi = bat_iterator(lo);
    4234          48 :         if (b->ttype == TYPE_void || lo->ttype == TYPE_void) {
    4235           0 :                 lng timeoffset = 0;
    4236           0 :                 QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    4237           0 :                 if (qry_ctx != NULL) {
    4238           0 :                         timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    4239             :                 }
    4240           0 :                 bn = COLnew(ci.seq, TYPE_bit, ci.ncand, TRANSIENT);
    4241           0 :                 if (bn) {
    4242           0 :                         bit *restrict dst = (bit *) Tloc(bn, 0);
    4243           0 :                         BUN i, j, l;
    4244           0 :                         BUN nils = 0;
    4245           0 :                         TIMEOUT_LOOP_IDX(l, ci.ncand, timeoffset) {
    4246           0 :                                 i = canditer_next(&ci) - b->hseqbase;
    4247           0 :                                 j = canditer_next(&cilo) - lo->hseqbase;
    4248           0 :                                 dst[l] = BETWEEN(BUNtoid(b, i), BUNtoid(lo, j),
    4249             :                                                  hi->val.oval, oid);
    4250           0 :                                 nils += is_bit_nil(dst[l]);
    4251             :                         }
    4252           0 :                         BATsetcount(bn, ci.ncand);
    4253           0 :                         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
    4254           0 :                         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
    4255           0 :                         bn->tkey = ci.ncand <= 1;
    4256           0 :                         bn->tnil = nils != 0;
    4257           0 :                         bn->tnonil = nils == 0;
    4258           0 :                         TIMEOUT_CHECK(timeoffset, HANDLE_TIMEOUT);
    4259             :                 }
    4260             :         } else {
    4261          52 :                 bn = BATcalcbetween_intern(bi.base, 1,
    4262          48 :                                            bi.vh ? bi.vh->base : NULL,
    4263          48 :                                            bi.width,
    4264          48 :                                            loi.base, 1,
    4265          48 :                                            loi.vh ? loi.vh->base : NULL,
    4266          48 :                                            loi.width,
    4267             :                                            VALptr(hi), 0, NULL, 0,
    4268          48 :                                            bi.type,
    4269             :                                            &ci,
    4270             :                                            &cilo,
    4271          48 :                                            &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
    4272             :                                            b->hseqbase, lo->hseqbase, 0,
    4273             :                                            symmetric, anti,
    4274             :                                            linc, hinc, nils_false,
    4275             :                                            __func__);
    4276             :         }
    4277          48 :         bat_iterator_end(&bi);
    4278          48 :         bat_iterator_end(&loi);
    4279             : 
    4280          48 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",lo=" ALGOBATFMT
    4281             :                   ",s=" ALGOOPTBATFMT ",slo=" ALGOOPTBATFMT
    4282             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    4283             :                   ALGOBATPAR(b), ALGOBATPAR(lo),
    4284             :                   ALGOOPTBATPAR(s), ALGOOPTBATPAR(slo),
    4285             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    4286             : 
    4287             :         return bn;
    4288             : }
    4289             : 
    4290             : BAT *
    4291          43 : BATcalcbetweencstbat(BAT *b, const ValRecord *lo, BAT *hi, BAT *s, BAT *shi,
    4292             :                      bool symmetric, bool linc, bool hinc, bool nils_false,
    4293             :                      bool anti)
    4294             : {
    4295          43 :         lng t0 = 0;
    4296          43 :         BAT *bn;
    4297          43 :         struct canditer ci, cihi;
    4298             : 
    4299          43 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4300             : 
    4301          43 :         BATcheck(b, NULL);
    4302          43 :         BATcheck(hi, NULL);
    4303             : 
    4304         107 :         if (ATOMbasetype(b->ttype) != ATOMbasetype(lo->vtype)) {
    4305           0 :                 GDKerror("incompatible input types.\n");
    4306           0 :                 return NULL;
    4307             :         }
    4308             : 
    4309          43 :         canditer_init(&ci, b, s);
    4310          42 :         canditer_init(&cihi, hi, shi);
    4311          43 :         if (ci.ncand != cihi.ncand || ci.hseq != cihi.hseq) {
    4312           0 :                 GDKerror("inputs not the same size.\n");
    4313           0 :                 return NULL;
    4314             :         }
    4315             : 
    4316          43 :         BATiter bi = bat_iterator(b);
    4317          43 :         BATiter hii = bat_iterator(hi);
    4318          43 :         if (b->ttype == TYPE_void || hi->ttype == TYPE_void) {
    4319           1 :                 lng timeoffset = 0;
    4320           1 :                 QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    4321           1 :                 if (qry_ctx != NULL) {
    4322           1 :                         timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    4323             :                 }
    4324           1 :                 bn = COLnew(ci.seq, TYPE_bit, ci.ncand, TRANSIENT);
    4325           1 :                 if (bn) {
    4326           1 :                         bit *restrict dst = (bit *) Tloc(bn, 0);
    4327           1 :                         BUN i, k, l;
    4328           1 :                         BUN nils = 0;
    4329           4 :                         TIMEOUT_LOOP_IDX(l, ci.ncand, timeoffset) {
    4330           1 :                                 i = canditer_next(&ci) - b->hseqbase;
    4331           1 :                                 k = canditer_next(&cihi) - hi->hseqbase;
    4332           1 :                                 dst[l] = BETWEEN(BUNtoid(b, i), lo->val.oval,
    4333             :                                                  BUNtoid(hi, k), oid);
    4334           1 :                                 nils += is_bit_nil(dst[l]);
    4335             :                         }
    4336           1 :                         BATsetcount(bn, ci.ncand);
    4337           1 :                         bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
    4338           1 :                         bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
    4339           1 :                         bn->tkey = ci.ncand <= 1;
    4340           1 :                         bn->tnil = nils != 0;
    4341           1 :                         bn->tnonil = nils == 0;
    4342           1 :                         TIMEOUT_CHECK(timeoffset, HANDLE_TIMEOUT);
    4343             :                 }
    4344             :         } else {
    4345          49 :                 bn = BATcalcbetween_intern(bi.base, 1,
    4346          42 :                                            bi.vh ? bi.vh->base : NULL,
    4347          42 :                                            bi.width,
    4348             :                                            VALptr(lo), 0, NULL, 0,
    4349          42 :                                            hii.base, 1,
    4350          42 :                                            hii.vh ? hii.vh->base : NULL,
    4351          42 :                                            hii.width,
    4352          42 :                                            bi.type,
    4353             :                                            &ci,
    4354          42 :                                            &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
    4355             :                                            &cihi,
    4356             :                                            b->hseqbase, 0, hi->hseqbase,
    4357             :                                            symmetric, anti,
    4358             :                                            linc, hinc, nils_false,
    4359             :                                            __func__);
    4360             :         }
    4361          43 :         bat_iterator_end(&bi);
    4362          43 :         bat_iterator_end(&hii);
    4363             : 
    4364          43 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",hi=" ALGOBATFMT
    4365             :                   ",s=" ALGOOPTBATFMT ",shi=" ALGOOPTBATFMT
    4366             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    4367             :                   ALGOBATPAR(b), ALGOBATPAR(hi),
    4368             :                   ALGOOPTBATPAR(s), ALGOOPTBATPAR(shi),
    4369             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    4370             : 
    4371             :         return bn;
    4372             : }
    4373             : 
    4374             : gdk_return
    4375          38 : VARcalcbetween(ValPtr ret, const ValRecord *v, const ValRecord *lo,
    4376             :                const ValRecord *hi, bool symmetric, bool linc, bool hinc,
    4377             :                bool nils_false, bool anti)
    4378             : {
    4379          38 :         int t;
    4380          38 :         int (*atomcmp)(const void *, const void *);
    4381          38 :         const void *nil;
    4382             : 
    4383          38 :         t = v->vtype;
    4384          38 :         if (t != lo->vtype || t != hi->vtype) {
    4385           0 :                 GDKerror("incompatible input types.\n");
    4386           0 :                 return GDK_FAIL;
    4387             :         }
    4388          38 :         if (!ATOMlinear(t)) {
    4389           0 :                 GDKerror("non-linear input type.\n");
    4390           0 :                 return GDK_FAIL;
    4391             :         }
    4392             : 
    4393          38 :         t = ATOMbasetype(t);
    4394             : 
    4395          38 :         ret->vtype = TYPE_bit;
    4396          38 :         switch (t) {
    4397          14 :         case TYPE_bte:
    4398          14 :                 ret->val.btval = BETWEEN(v->val.btval, lo->val.btval, hi->val.btval, bte);
    4399          14 :                 break;
    4400           2 :         case TYPE_sht:
    4401           2 :                 ret->val.btval = BETWEEN(v->val.shval, lo->val.shval, hi->val.shval, sht);
    4402           2 :                 break;
    4403           3 :         case TYPE_int:
    4404           3 :                 ret->val.btval = BETWEEN(v->val.ival, lo->val.ival, hi->val.ival, int);
    4405           3 :                 break;
    4406           8 :         case TYPE_lng:
    4407           8 :                 ret->val.btval = BETWEEN(v->val.lval, lo->val.lval, hi->val.lval, lng);
    4408           8 :                 break;
    4409             : #ifdef HAVE_HGE
    4410           0 :         case TYPE_hge:
    4411           0 :                 ret->val.btval = BETWEEN(v->val.hval, lo->val.hval, hi->val.hval, hge);
    4412           0 :                 break;
    4413             : #endif
    4414           0 :         case TYPE_flt:
    4415           0 :                 ret->val.btval = BETWEEN(v->val.fval, lo->val.fval, hi->val.fval, flt);
    4416           0 :                 break;
    4417           0 :         case TYPE_dbl:
    4418           0 :                 ret->val.btval = BETWEEN(v->val.dval, lo->val.dval, hi->val.dval, dbl);
    4419           0 :                 break;
    4420          11 :         default:
    4421          11 :                 nil = ATOMnilptr(t);
    4422          11 :                 atomcmp = ATOMcompare(t);
    4423          11 :                 ret->val.btval = BETWEEN(VALptr(v), VALptr(lo), VALptr(hi), any);
    4424          11 :                 break;
    4425             :         }
    4426             :         return GDK_SUCCEED;
    4427             : }
    4428             : 
    4429             : /* ---------------------------------------------------------------------- */
    4430             : /* if-then-else (any type) */
    4431             : 
    4432             : #define IFTHENELSELOOP(TYPE)                                            \
    4433             :         do {                                                            \
    4434             :                 TIMEOUT_LOOP_IDX(i, cnt, timeoffset) {                  \
    4435             :                         if (src[i] && !is_bit_nil(src[i])) {            \
    4436             :                                 ((TYPE *) dst)[i] = ((TYPE *) col1)[k]; \
    4437             :                         } else {                                        \
    4438             :                                 ((TYPE *) dst)[i] = ((TYPE *) col2)[l]; \
    4439             :                         }                                               \
    4440             :                         k += incr1;                                     \
    4441             :                         l += incr2;                                     \
    4442             :                 }                                                       \
    4443             :                 TIMEOUT_CHECK(timeoffset,                               \
    4444             :                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));     \
    4445             :         } while (0)
    4446             : #define IFTHENELSELOOP_msk(TYPE)                                        \
    4447             :         do {                                                            \
    4448             :                 TIMEOUT_LOOP_IDX(i, cnt, timeoffset) {                  \
    4449             :                         if (n == 32) {                                  \
    4450             :                                 n = 0;                                  \
    4451             :                                 mask = src[i / 32];                     \
    4452             :                         }                                               \
    4453             :                         ((TYPE *) dst)[i] = mask & (1U << n) ?                \
    4454             :                                 ((TYPE *) col1)[k] :                    \
    4455             :                                 ((TYPE *) col2)[l];                     \
    4456             :                         k += incr1;                                     \
    4457             :                         l += incr2;                                     \
    4458             :                         n++;                                            \
    4459             :                 }                                                       \
    4460             :                 TIMEOUT_CHECK(timeoffset,                               \
    4461             :                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));     \
    4462             :         } while (0)
    4463             : 
    4464             : static BAT *
    4465        4210 : BATcalcifthenelse_intern(BATiter *bi,
    4466             :                          const void *col1, bool incr1, const char *heap1,
    4467             :                          int width1, bool nonil1, oid seq1,
    4468             :                          const void *col2, bool incr2, const char *heap2,
    4469             :                          int width2, bool nonil2, oid seq2,
    4470             :                          int tpe)
    4471             : {
    4472        4210 :         BAT *bn;
    4473        4210 :         void *restrict dst;
    4474        4210 :         BUN i, k, l;
    4475        4210 :         const void *p;
    4476        4210 :         BUN cnt = bi->count;
    4477             : 
    4478        4210 :         lng timeoffset = 0;
    4479        4210 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    4480        4210 :         if (qry_ctx != NULL) {
    4481        4210 :                 timeoffset = (qry_ctx->starttime && qry_ctx->querytimeout) ? (qry_ctx->starttime + qry_ctx->querytimeout) : 0;
    4482             :         }
    4483             : 
    4484             :         /* col1 and col2 can only be NULL for void columns */
    4485        4210 :         assert(col1 != NULL || ATOMtype(tpe) == TYPE_oid);
    4486        4210 :         assert(col2 != NULL || ATOMtype(tpe) == TYPE_oid);
    4487        4210 :         assert(col1 != NULL || heap1 == NULL);
    4488        4210 :         assert(col2 != NULL || heap2 == NULL);
    4489        4210 :         assert(col1 != NULL || incr1 == true);
    4490        4210 :         assert(col2 != NULL || incr2 == true);
    4491             : 
    4492        4210 :         bn = COLnew(bi->b->hseqbase, ATOMtype(tpe), cnt, TRANSIENT);
    4493        4209 :         if (bn == NULL)
    4494             :                 return NULL;
    4495        4209 :         if (cnt == 0)
    4496             :                 return bn;
    4497             : 
    4498        3509 :         dst = (void *) Tloc(bn, 0);
    4499        3509 :         k = l = 0;
    4500        3509 :         if (bn->tvheap) {
    4501         262 :                 assert((heap1 != NULL && width1 > 0) || (width1 == 0 && incr1 == 0));
    4502         262 :                 assert((heap2 != NULL && width2 > 0) || (width2 == 0 && incr2 == 0));
    4503         262 :                 if (ATOMstorage(bi->type) == TYPE_msk) {
    4504           0 :                         const uint32_t *src = bi->base;
    4505           0 :                         BUN n = cnt / 32;
    4506           0 :                         TIMEOUT_LOOP_IDX(i, n + 1, timeoffset) {
    4507           0 :                                 BUN rem = i == n ? cnt % 32 : 32;
    4508           0 :                                 uint32_t mask = rem != 0 ? src[i] : 0;
    4509           0 :                                 for (BUN j = 0; j < rem; j++) {
    4510           0 :                                         if (mask & (1U << j)) {
    4511           0 :                                                 if (heap1)
    4512           0 :                                                         p = heap1 + VarHeapVal(col1, k, width1);
    4513             :                                                 else
    4514             :                                                         p = col1;
    4515             :                                         } else {
    4516           0 :                                                 if (heap2)
    4517           0 :                                                         p = heap2 + VarHeapVal(col2, l, width2);
    4518             :                                                 else
    4519             :                                                         p = col2;
    4520             :                                         }
    4521           0 :                                         if (tfastins_nocheckVAR(bn, i, p) != GDK_SUCCEED) {
    4522           0 :                                                 goto bailout;
    4523             :                                         }
    4524           0 :                                         k += incr1;
    4525           0 :                                         l += incr2;
    4526             :                                 }
    4527             :                         }
    4528           0 :                         TIMEOUT_CHECK(timeoffset,
    4529             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    4530             :                 } else {
    4531         262 :                         const bit *src = bi->base;
    4532      178489 :                         TIMEOUT_LOOP_IDX(i, cnt, timeoffset) {
    4533      177701 :                                 if (src[i] && !is_bit_nil(src[i])) {
    4534      131704 :                                         if (heap1)
    4535        2688 :                                                 p = heap1 + VarHeapVal(col1, k, width1);
    4536             :                                         else
    4537             :                                                 p = col1;
    4538             :                                 } else {
    4539       45997 :                                         if (heap2)
    4540       10142 :                                                 p = heap2 + VarHeapVal(col2, l, width2);
    4541             :                                         else
    4542             :                                                 p = col2;
    4543             :                                 }
    4544      177699 :                                 if (tfastins_nocheckVAR(bn, i, p) != GDK_SUCCEED) {
    4545           0 :                                         goto bailout;
    4546             :                                 }
    4547      177702 :                                 k += incr1;
    4548      177702 :                                 l += incr2;
    4549             :                         }
    4550         263 :                         TIMEOUT_CHECK(timeoffset,
    4551             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    4552             :                 }
    4553             :         } else {
    4554        3247 :                 assert(heap1 == NULL);
    4555        3247 :                 assert(heap2 == NULL);
    4556        3247 :                 if (ATOMstorage(bi->type) == TYPE_msk) {
    4557           0 :                         const uint32_t *src = bi->base;
    4558           0 :                         uint32_t mask = 0;
    4559           0 :                         BUN n = 32;
    4560           0 :                         if (ATOMtype(tpe) == TYPE_oid) {
    4561           0 :                                 TIMEOUT_LOOP_IDX(i, cnt, timeoffset) {
    4562           0 :                                         if (n == 32) {
    4563           0 :                                                 n = 0;
    4564           0 :                                                 mask = src[i / 32];
    4565             :                                         }
    4566           0 :                                         ((oid *) dst)[i] = mask & (1U << n) ?
    4567           0 :                                                 col1 ? ((oid *)col1)[k] : seq1 :
    4568           0 :                                                 col2 ? ((oid *)col2)[l] : seq2;
    4569           0 :                                         k += incr1;
    4570           0 :                                         l += incr2;
    4571           0 :                                         seq1 += incr1;
    4572           0 :                                         seq2 += incr2;
    4573           0 :                                         n++;
    4574             :                                 }
    4575           0 :                                 TIMEOUT_CHECK(timeoffset,
    4576             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    4577           0 :                         } else if (ATOMstorage(tpe) == TYPE_msk) {
    4578           0 :                                 uint32_t v1, v2;
    4579           0 :                                 if (incr1) {
    4580             :                                         v1 = 0;
    4581             :                                 } else {
    4582           0 :                                         v1 = * (msk *) col1 ? ~0U : 0U;
    4583             :                                 }
    4584           0 :                                 if (incr2) {
    4585             :                                         v2 = 0;
    4586             :                                 } else {
    4587           0 :                                         v2 = * (msk *) col2 ? ~0U : 0U;
    4588             :                                 }
    4589           0 :                                 n = (cnt + 31) / 32;
    4590           0 :                                 TIMEOUT_LOOP_IDX(i, n, timeoffset) {
    4591           0 :                                         if (incr1)
    4592           0 :                                                 v1 = ((uint32_t *) col1)[i];
    4593           0 :                                         if (incr2)
    4594           0 :                                                 v2 = ((uint32_t *) col2)[i];
    4595           0 :                                         ((uint32_t *) dst)[i] = (src[i] & v1)
    4596           0 :                                                 | (~src[i] & v2);
    4597             :                                 }
    4598           0 :                                 TIMEOUT_CHECK(timeoffset,
    4599             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    4600             :                         } else {
    4601           0 :                                 switch (bn->twidth) {
    4602             :                                 case 1:
    4603           0 :                                         IFTHENELSELOOP_msk(bte);
    4604             :                                         break;
    4605             :                                 case 2:
    4606           0 :                                         IFTHENELSELOOP_msk(sht);
    4607             :                                         break;
    4608             :                                 case 4:
    4609           0 :                                         IFTHENELSELOOP_msk(int);
    4610             :                                         break;
    4611             :                                 case 8:
    4612           0 :                                         IFTHENELSELOOP_msk(lng);
    4613             :                                         break;
    4614             :                                 case 16:
    4615             : #ifdef HAVE_HGE
    4616           0 :                                         IFTHENELSELOOP_msk(hge);
    4617             : #else
    4618             :                                         IFTHENELSELOOP_msk(uuid);
    4619             : #endif
    4620             :                                         break;
    4621             :                                 default:
    4622           0 :                                         TIMEOUT_LOOP_IDX(i, cnt, timeoffset) {
    4623           0 :                                                 if (n == 32) {
    4624           0 :                                                         n = 0;
    4625           0 :                                                         mask = src[i / 32];
    4626             :                                                 }
    4627           0 :                                                 if (mask & (1U << n))
    4628           0 :                                                         p = ((const char *) col1) + k * width1;
    4629             :                                                 else
    4630           0 :                                                         p = ((const char *) col2) + l * width2;
    4631           0 :                                                 memcpy(dst, p, bn->twidth);
    4632           0 :                                                 dst = (void *) ((char *) dst + bn->twidth);
    4633           0 :                                                 k += incr1;
    4634           0 :                                                 l += incr2;
    4635           0 :                                                 n++;
    4636             :                                         }
    4637           0 :                                         TIMEOUT_CHECK(timeoffset,
    4638             :                                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    4639             :                                 }
    4640             :                         }
    4641             :                 } else {
    4642        3247 :                         const bit *src = bi->base;
    4643        3247 :                         if (ATOMtype(tpe) == TYPE_oid) {
    4644           0 :                                 TIMEOUT_LOOP_IDX(i, cnt, timeoffset) {
    4645           0 :                                         if (src[i] && !is_bit_nil(src[i])) {
    4646           0 :                                                 ((oid *) dst)[i] = col1 ? ((oid *) col1)[k] : seq1;
    4647             :                                         } else {
    4648           0 :                                                 ((oid *) dst)[i] = col2 ? ((oid *) col2)[k] : seq2;
    4649             :                                         }
    4650           0 :                                         k += incr1;
    4651           0 :                                         l += incr2;
    4652           0 :                                         seq1 += incr1;
    4653           0 :                                         seq2 += incr2;
    4654             :                                 }
    4655           0 :                                 TIMEOUT_CHECK(timeoffset,
    4656             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    4657        3247 :                         } else if (ATOMstorage(tpe) == TYPE_msk) {
    4658           0 :                                 uint32_t v1, v2;
    4659           0 :                                 uint32_t *d = dst;
    4660           0 :                                 if (incr1) {
    4661             :                                         v1 = 0;
    4662             :                                 } else {
    4663           0 :                                         v1 = * (msk *) col1 ? ~0U : 0U;
    4664             :                                 }
    4665           0 :                                 if (incr2) {
    4666             :                                         v2 = 0;
    4667             :                                 } else {
    4668           0 :                                         v2 = * (msk *) col2 ? ~0U : 0U;
    4669             :                                 }
    4670           0 :                                 i = 0;
    4671           0 :                                 TIMEOUT_LOOP(cnt / 32, timeoffset) {
    4672           0 :                                         uint32_t mask = 0;
    4673           0 :                                         if (incr1)
    4674           0 :                                                 v1 = ((uint32_t *) col1)[i/32];
    4675           0 :                                         if (incr2)
    4676           0 :                                                 v2 = ((uint32_t *) col2)[i/32];
    4677           0 :                                         for (int n = 0; n < 32; n++) {
    4678           0 :                                                 mask |= (uint32_t) (src[i] != 0) << n;
    4679             :                                         }
    4680           0 :                                         *d++ = (mask & v1) | (~mask & v2);
    4681           0 :                                         i += 32;
    4682             :                                 }
    4683           0 :                                 TIMEOUT_CHECK(timeoffset,
    4684             :                                               GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    4685             :                                 /* do the last word */
    4686           0 :                                 if (i < cnt) {
    4687           0 :                                         uint32_t mask = 0;
    4688           0 :                                         if (incr1)
    4689           0 :                                                 v1 = ((uint32_t *) col1)[i/32];
    4690           0 :                                         if (incr2)
    4691           0 :                                                 v2 = ((uint32_t *) col2)[i/32];
    4692           0 :                                         for (int n = 0; n < 32; n++) {
    4693           0 :                                                 mask |= (uint32_t) (src[i] != 0) << n;
    4694           0 :                                                 if (++i == cnt)
    4695             :                                                         break;
    4696             :                                         }
    4697           0 :                                         *d++ = (mask & v1) | (~mask & v2);
    4698             :                                 }
    4699             :                         } else {
    4700        3247 :                                 switch (bn->twidth) {
    4701             :                                 case 1:
    4702     5053509 :                                         IFTHENELSELOOP(bte);
    4703             :                                         break;
    4704             :                                 case 2:
    4705           0 :                                         IFTHENELSELOOP(sht);
    4706             :                                         break;
    4707             :                                 case 4:
    4708      599433 :                                         IFTHENELSELOOP(int);
    4709             :                                         break;
    4710             :                                 case 8:
    4711       88286 :                                         IFTHENELSELOOP(lng);
    4712             :                                         break;
    4713             :                                 case 16:
    4714             : #ifdef HAVE_HGE
    4715       88545 :                                         IFTHENELSELOOP(hge);
    4716             : #else
    4717             :                                         IFTHENELSELOOP(uuid);
    4718             : #endif
    4719             :                                         break;
    4720             :                                 default:
    4721           0 :                                         TIMEOUT_LOOP_IDX(i, cnt, timeoffset) {
    4722           0 :                                                 if (src[i] && !is_bit_nil(src[i])) {
    4723           0 :                                                         p = ((const char *) col1) + k * width1;
    4724             :                                                 } else {
    4725           0 :                                                         p = ((const char *) col2) + l * width2;
    4726             :                                                 }
    4727           0 :                                                 memcpy(dst, p, bn->twidth);
    4728           0 :                                                 dst = (void *) ((char *) dst + bn->twidth);
    4729           0 :                                                 k += incr1;
    4730           0 :                                                 l += incr2;
    4731             :                                         }
    4732           0 :                                         TIMEOUT_CHECK(timeoffset,
    4733             :                                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout));
    4734             :                                 }
    4735             :                         }
    4736             :                 }
    4737             :         }
    4738             : 
    4739        3510 :         BATsetcount(bn, cnt);
    4740             : 
    4741        3510 :         bn->tsorted = cnt <= 1;
    4742        3510 :         bn->trevsorted = cnt <= 1;
    4743        3510 :         bn->tkey = cnt <= 1;
    4744        3510 :         bn->tnil = 0;
    4745        3510 :         bn->tnonil = nonil1 && nonil2;
    4746             : 
    4747        3510 :         return bn;
    4748           0 : bailout:
    4749           0 :         BBPreclaim(bn);
    4750           0 :         return NULL;
    4751             : }
    4752             : 
    4753             : BAT *
    4754          46 : BATcalcifthenelse(BAT *b, BAT *b1, BAT *b2)
    4755             : {
    4756          46 :         lng t0 = 0;
    4757          46 :         BAT *bn;
    4758             : 
    4759          46 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4760             : 
    4761          46 :         BATcheck(b, NULL);
    4762          46 :         BATcheck(b1, NULL);
    4763          46 :         BATcheck(b2, NULL);
    4764             : 
    4765          46 :         BATiter bi = bat_iterator(b);
    4766          46 :         BATiter b1i = bat_iterator(b1);
    4767          46 :         BATiter b2i = bat_iterator(b2);
    4768          92 :         if (checkbats(&bi, &b1i, __func__) != GDK_SUCCEED ||
    4769          46 :             checkbats(&bi, &b2i, __func__) != GDK_SUCCEED) {
    4770           0 :                 bat_iterator_end(&bi);
    4771           0 :                 bat_iterator_end(&b1i);
    4772           0 :                 bat_iterator_end(&b2i);
    4773           0 :                 return NULL;
    4774             :         }
    4775         138 :         if (b->ttype != TYPE_bit || ATOMtype(b1->ttype) != ATOMtype(b2->ttype)) {
    4776           0 :                 bat_iterator_end(&bi);
    4777           0 :                 bat_iterator_end(&b1i);
    4778           0 :                 bat_iterator_end(&b2i);
    4779           0 :                 GDKerror("\"then\" and \"else\" BATs have different types.\n");
    4780           0 :                 return NULL;
    4781             :         }
    4782          26 :         bn = BATcalcifthenelse_intern(&bi,
    4783          46 :                                       b1i.base, true, b1i.vh ? b1i.vh->base : NULL, b1i.width, b1i.nonil, b1->tseqbase,
    4784          46 :                                       b2i.base, true, b2i.vh ? b2i.vh->base : NULL, b2i.width, b2i.nonil, b2->tseqbase,
    4785          46 :                                       b1i.type);
    4786          46 :         bat_iterator_end(&bi);
    4787          46 :         bat_iterator_end(&b1i);
    4788          46 :         bat_iterator_end(&b2i);
    4789             : 
    4790          46 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",b1=" ALGOBATFMT ",b2=" ALGOBATFMT
    4791             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    4792             :                   ALGOBATPAR(b), ALGOBATPAR(b1), ALGOBATPAR(b2),
    4793             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    4794             : 
    4795             :         return bn;
    4796             : }
    4797             : 
    4798             : BAT *
    4799         125 : BATcalcifthenelsecst(BAT *b, BAT *b1, const ValRecord *c2)
    4800             : {
    4801         125 :         lng t0 = 0;
    4802         125 :         BAT *bn;
    4803             : 
    4804         125 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4805             : 
    4806         125 :         BATcheck(b, NULL);
    4807         125 :         BATcheck(b1, NULL);
    4808         125 :         BATcheck(c2, NULL);
    4809             : 
    4810         125 :         BATiter bi = bat_iterator(b);
    4811         125 :         BATiter b1i = bat_iterator(b1);
    4812         125 :         if (checkbats(&bi, &b1i, __func__) != GDK_SUCCEED) {
    4813           0 :                 bat_iterator_end(&bi);
    4814           0 :                 bat_iterator_end(&b1i);
    4815           0 :                 return NULL;
    4816             :         }
    4817         375 :         if (b->ttype != TYPE_bit || ATOMtype(b1->ttype) != ATOMtype(c2->vtype)) {
    4818           0 :                 bat_iterator_end(&bi);
    4819           0 :                 bat_iterator_end(&b1i);
    4820           0 :                 GDKerror("\"then\" and \"else\" BATs have different types.\n");
    4821           0 :                 return NULL;
    4822             :         }
    4823          24 :         bn = BATcalcifthenelse_intern(&bi,
    4824         125 :                                       b1i.base, true, b1i.vh ? b1i.vh->base : NULL, b1i.width, b1i.nonil, b1->tseqbase,
    4825         125 :                                       VALptr(c2), false, NULL, 0, !VALisnil(c2), 0,
    4826         125 :                                       b1i.type);
    4827         125 :         bat_iterator_end(&bi);
    4828         125 :         bat_iterator_end(&b1i);
    4829             : 
    4830         125 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",b1=" ALGOBATFMT
    4831             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    4832             :                   ALGOBATPAR(b), ALGOBATPAR(b1),
    4833             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    4834             : 
    4835             :         return bn;
    4836             : }
    4837             : 
    4838             : BAT *
    4839        2809 : BATcalcifthencstelse(BAT *b, const ValRecord *c1, BAT *b2)
    4840             : {
    4841        2809 :         lng t0 = 0;
    4842        2809 :         BAT *bn;
    4843             : 
    4844        2809 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4845             : 
    4846        2809 :         BATcheck(b, NULL);
    4847        2809 :         BATcheck(c1, NULL);
    4848        2809 :         BATcheck(b2, NULL);
    4849             : 
    4850        2809 :         BATiter bi = bat_iterator(b);
    4851        2808 :         BATiter b2i = bat_iterator(b2);
    4852        2809 :         if (checkbats(&bi, &b2i, __func__) != GDK_SUCCEED) {
    4853           0 :                 bat_iterator_end(&bi);
    4854           0 :                 bat_iterator_end(&b2i);
    4855           0 :                 return NULL;
    4856             :         }
    4857        8425 :         if (b->ttype != TYPE_bit || ATOMtype(b2->ttype) != ATOMtype(c1->vtype)) {
    4858           0 :                 bat_iterator_end(&bi);
    4859           0 :                 bat_iterator_end(&b2i);
    4860           0 :                 GDKerror("\"then\" and \"else\" BATs have different types.\n");
    4861           0 :                 return NULL;
    4862             :         }
    4863          48 :         bn = BATcalcifthenelse_intern(&bi,
    4864        2809 :                                       VALptr(c1), false, NULL, 0, !VALisnil(c1), 0,
    4865        2857 :                                       b2i.base, true, b2i.vh ? b2i.vh->base : NULL, b2i.width, b2i.nonil, b2->tseqbase,
    4866        2809 :                                       c1->vtype);
    4867        2809 :         bat_iterator_end(&bi);
    4868        2809 :         bat_iterator_end(&b2i);
    4869             : 
    4870        2809 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",b2=" ALGOBATFMT
    4871             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    4872             :                   ALGOBATPAR(b), ALGOBATPAR(b2),
    4873             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    4874             : 
    4875             :         return bn;
    4876             : }
    4877             : 
    4878             : BAT *
    4879        1230 : BATcalcifthencstelsecst(BAT *b, const ValRecord *c1, const ValRecord *c2)
    4880             : {
    4881        1230 :         lng t0 = 0;
    4882        1230 :         BAT *bn;
    4883             : 
    4884        1230 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4885             : 
    4886        1230 :         BATcheck(b, NULL);
    4887        1230 :         BATcheck(c1, NULL);
    4888        1230 :         BATcheck(c2, NULL);
    4889             : 
    4890        3690 :         if (b->ttype != TYPE_bit || ATOMtype(c1->vtype) != ATOMtype(c2->vtype)) {
    4891           0 :                 GDKerror("\"then\" and \"else\" BATs have different types.\n");
    4892           0 :                 return NULL;
    4893             :         }
    4894        1230 :         BATiter bi = bat_iterator(b);
    4895        4920 :         bn = BATcalcifthenelse_intern(&bi,
    4896        1230 :                                       VALptr(c1), false, NULL, 0, !VALisnil(c1), 0,
    4897        1230 :                                       VALptr(c2), false, NULL, 0, !VALisnil(c2), 0,
    4898        1230 :                                       c1->vtype);
    4899        1230 :         bat_iterator_end(&bi);
    4900             : 
    4901        1230 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT
    4902             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    4903             :                   ALGOBATPAR(b),
    4904             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    4905             : 
    4906             :         return bn;
    4907             : }

Generated by: LCOV version 1.14