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

Generated by: LCOV version 1.14