LCOV - code coverage report
Current view: top level - gdk - gdk_calc_convert.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 403 618 65.2 %
Date: 2024-11-12 19:36:54 Functions: 65 84 77.4 %

          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             : /* ---------------------------------------------------------------------- */
      19             : /* type conversion (cast) */
      20             : 
      21             : /* a note on the return values from the internal conversion functions:
      22             :  *
      23             :  * the functions return the number of NIL values produced (or at
      24             :  * least, 0 if no NIL, and != 0 if there were any);
      25             :  * the return value is BUN_NONE if a message was generated
      26             :  * (e.g. overflow or timeout);
      27             :  * the return value is BUN_NONE + 1 if the types were not compatible;
      28             :  * the return value is BUN_NONE + 2 if inserting a value into a BAT
      29             :  * failed (only happens for conversion to str).
      30             :  */
      31             : 
      32             : #ifdef HAVE_HGE
      33             : static const hge scales[39] = {
      34             :         (hge) LL_CONSTANT(1),
      35             :         (hge) LL_CONSTANT(10),
      36             :         (hge) LL_CONSTANT(100),
      37             :         (hge) LL_CONSTANT(1000),
      38             :         (hge) LL_CONSTANT(10000),
      39             :         (hge) LL_CONSTANT(100000),
      40             :         (hge) LL_CONSTANT(1000000),
      41             :         (hge) LL_CONSTANT(10000000),
      42             :         (hge) LL_CONSTANT(100000000),
      43             :         (hge) LL_CONSTANT(1000000000),
      44             :         (hge) LL_CONSTANT(10000000000),
      45             :         (hge) LL_CONSTANT(100000000000),
      46             :         (hge) LL_CONSTANT(1000000000000),
      47             :         (hge) LL_CONSTANT(10000000000000),
      48             :         (hge) LL_CONSTANT(100000000000000),
      49             :         (hge) LL_CONSTANT(1000000000000000),
      50             :         (hge) LL_CONSTANT(10000000000000000),
      51             :         (hge) LL_CONSTANT(100000000000000000),
      52             :         (hge) LL_CONSTANT(1000000000000000000),
      53             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(1),
      54             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(10),
      55             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(100),
      56             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(1000),
      57             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(10000),
      58             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(100000),
      59             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(1000000),
      60             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(10000000),
      61             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(100000000),
      62             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(1000000000),
      63             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(10000000000),
      64             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(100000000000),
      65             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(1000000000000),
      66             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(10000000000000),
      67             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(100000000000000),
      68             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(1000000000000000),
      69             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(10000000000000000),
      70             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(100000000000000000),
      71             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(1000000000000000000),
      72             :         (hge) LL_CONSTANT(10000000000000000000U) * LL_CONSTANT(10000000000000000000U)
      73             : };
      74             : #else
      75             : static const lng scales[19] = {
      76             :         LL_CONSTANT(1),
      77             :         LL_CONSTANT(10),
      78             :         LL_CONSTANT(100),
      79             :         LL_CONSTANT(1000),
      80             :         LL_CONSTANT(10000),
      81             :         LL_CONSTANT(100000),
      82             :         LL_CONSTANT(1000000),
      83             :         LL_CONSTANT(10000000),
      84             :         LL_CONSTANT(100000000),
      85             :         LL_CONSTANT(1000000000),
      86             :         LL_CONSTANT(10000000000),
      87             :         LL_CONSTANT(100000000000),
      88             :         LL_CONSTANT(1000000000000),
      89             :         LL_CONSTANT(10000000000000),
      90             :         LL_CONSTANT(100000000000000),
      91             :         LL_CONSTANT(1000000000000000),
      92             :         LL_CONSTANT(10000000000000000),
      93             :         LL_CONSTANT(100000000000000000),
      94             :         LL_CONSTANT(1000000000000000000)
      95             : };
      96             : #endif
      97             : 
      98             : #define convertimpl_enlarge_float(TYPE1, TYPE2, MANT_DIG)               \
      99             : static BUN                                                              \
     100             : convert_##TYPE1##_##TYPE2(const TYPE1 *src, TYPE2 *restrict dst,        \
     101             :                           struct canditer *restrict ci,                 \
     102             :                           oid candoff, uint8_t scale1, bool *reduce)    \
     103             : {                                                                       \
     104             :         BUN i, nils = 0;                                                \
     105             :         TYPE1 v;                                                        \
     106             :         oid x;                                                          \
     107             :         const TYPE1 div = (TYPE1) scales[scale1];                       \
     108             :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();                      \
     109             :                                                                         \
     110             :         *reduce = 8 * sizeof(TYPE1) > MANT_DIG;                              \
     111             :         if (ci->tpe == cand_dense) {                                 \
     112             :                 if (div == 1) {                                         \
     113             :                         TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {    \
     114             :                                 x = canditer_next_dense(ci) - candoff;  \
     115             :                                 v = src[x];                             \
     116             :                                 if (is_##TYPE1##_nil(v)) {              \
     117             :                                         dst[i] = TYPE2##_nil;           \
     118             :                                         nils++;                         \
     119             :                                 } else                                  \
     120             :                                         dst[i] = (TYPE2) v;             \
     121             :                         }                                               \
     122             :                 } else {                                                \
     123             :                         TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {    \
     124             :                                 x = canditer_next_dense(ci) - candoff;  \
     125             :                                 v = src[x];                             \
     126             :                                 if (is_##TYPE1##_nil(v)) {              \
     127             :                                         dst[i] = TYPE2##_nil;           \
     128             :                                         nils++;                         \
     129             :                                 } else                                  \
     130             :                                         dst[i] = (TYPE2) v / div;       \
     131             :                         }                                               \
     132             :                 }                                                       \
     133             :         } else {                                                        \
     134             :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {            \
     135             :                         x = canditer_next(ci) - candoff;                \
     136             :                         v = src[x];                                     \
     137             :                         if (is_##TYPE1##_nil(v)) {                      \
     138             :                                 dst[i] = TYPE2##_nil;                   \
     139             :                                 nils++;                                 \
     140             :                         } else                                          \
     141             :                                 dst[i] = (TYPE2) v / div;               \
     142             :                 }                                                       \
     143             :         }                                                               \
     144             :         TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx));     \
     145             :         return nils;                                                    \
     146             : }
     147             : 
     148             : #define CONV_OVERFLOW(TYPE1, TYPE2, value)                              \
     149             :         do {                                                            \
     150             :                 GDKerror("22003!overflow in conversion of "           \
     151             :                          FMT##TYPE1 " to %s.\n", CST##TYPE1 (value),  \
     152             :                          TYPE2);                                        \
     153             :                 return BUN_NONE;                                        \
     154             :         } while (0)
     155             : 
     156             : #define CONV_OVERFLOW_PREC(TYPE1, TYPE2, value, scale, prec)            \
     157             :         do {                                                            \
     158             :                 if (prec > 0)                                                \
     159             :                         GDKerror("22003!overflow in conversion to "   \
     160             :                                  "DECIMAL(%d,%d).\n", prec, scale);   \
     161             :                 else                                                    \
     162             :                         GDKerror("22003!overflow in conversion of "   \
     163             :                                  FMT##TYPE1 " to %s.\n", CST##TYPE1 (value), \
     164             :                                  TYPE2);                                \
     165             :                 return BUN_NONE;                                        \
     166             :         } while (0)
     167             : 
     168             : #define convertimpl_oid_enlarge(TYPE1)                                  \
     169             : static BUN                                                              \
     170             : convert_##TYPE1##_oid(const TYPE1 *src, oid *restrict dst,              \
     171             :                       struct canditer *restrict ci,                     \
     172             :                       oid candoff, bool *reduce)                        \
     173             : {                                                                       \
     174             :         BUN i, nils = 0;                                                \
     175             :         oid x;                                                          \
     176             :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();                      \
     177             :                                                                         \
     178             :         *reduce = false;                                                \
     179             :         if (ci->tpe == cand_dense) {                                 \
     180             :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {            \
     181             :                         x = canditer_next_dense(ci) - candoff;          \
     182             :                         if (is_##TYPE1##_nil(src[x])) {                 \
     183             :                                 dst[i] = oid_nil;                       \
     184             :                                 nils++;                                 \
     185             :                         } else if (src[x] < 0) {                     \
     186             :                                 CONV_OVERFLOW(TYPE1, "oid", src[i]);  \
     187             :                         } else if (is_oid_nil((dst[i] = (oid) src[x]))) { \
     188             :                                 CONV_OVERFLOW(TYPE1, "oid", src[x]);  \
     189             :                         }                                               \
     190             :                 }                                                       \
     191             :                 TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx)); \
     192             :         } else {                                                        \
     193             :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {            \
     194             :                         x = canditer_next(ci) - candoff;                \
     195             :                         if (is_##TYPE1##_nil(src[x])) {                 \
     196             :                                 dst[i] = oid_nil;                       \
     197             :                                 nils++;                                 \
     198             :                         } else if (src[x] < 0) {                     \
     199             :                                 CONV_OVERFLOW(TYPE1, "oid", src[x]);  \
     200             :                         } else if (is_oid_nil((dst[i] = (oid) src[x]))) { \
     201             :                                 CONV_OVERFLOW(TYPE1, "oid", src[x]);  \
     202             :                         }                                               \
     203             :                 }                                                       \
     204             :                 TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx)); \
     205             :         }                                                               \
     206             :         return nils;                                                    \
     207             : }
     208             : 
     209             : #define convertimpl_oid_reduce(TYPE1)                                   \
     210             : static BUN                                                              \
     211             : convert_##TYPE1##_oid(const TYPE1 *src, oid *restrict dst,              \
     212             :                       struct canditer *restrict ci,                     \
     213             :                       oid candoff, bool *reduce)                        \
     214             : {                                                                       \
     215             :         BUN i, nils = 0;                                                \
     216             :         oid x;                                                          \
     217             :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();                      \
     218             :                                                                         \
     219             :         *reduce = false;                                                \
     220             :         if (ci->tpe == cand_dense) {                                 \
     221             :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {            \
     222             :                         x = canditer_next_dense(ci) - candoff;          \
     223             :                         if (is_##TYPE1##_nil(src[x])) {                 \
     224             :                                 dst[i] = oid_nil;                       \
     225             :                                 nils++;                                 \
     226             :                         } else if (src[x] < 0 ||                     \
     227             :                                    src[x] > (TYPE1) GDK_oid_max) {   \
     228             :                                 CONV_OVERFLOW(TYPE1, "oid", src[x]);  \
     229             :                         } else if (is_oid_nil((dst[i] = (oid) src[x]))) { \
     230             :                                 CONV_OVERFLOW(TYPE1, "oid", src[x]);  \
     231             :                         }                                               \
     232             :                 }                                                       \
     233             :                 TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx)); \
     234             :         } else {                                                        \
     235             :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {            \
     236             :                         x = canditer_next(ci) - candoff;                \
     237             :                         if (is_##TYPE1##_nil(src[x])) {                 \
     238             :                                 dst[i] = oid_nil;                       \
     239             :                                 nils++;                                 \
     240             :                         } else if (src[x] < 0 ||                     \
     241             :                                    src[x] > (TYPE1) GDK_oid_max) {   \
     242             :                                 CONV_OVERFLOW(TYPE1, "oid", src[x]);  \
     243             :                         } else if (is_oid_nil((dst[i] = (oid) src[x]))) { \
     244             :                                 CONV_OVERFLOW(TYPE1, "oid", src[x]);  \
     245             :                         }                                               \
     246             :                 }                                                       \
     247             :                 TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx)); \
     248             :         }                                                               \
     249             :         return nils;                                                    \
     250             : }
     251             : 
     252             : #define uint    unsigned int
     253             : #define usht    uint16_t
     254             : #define ubte    uint8_t
     255             : 
     256             : #ifdef TRUNCATE_NUMBERS
     257             : #define DIVIDE(v, div, TYPE)    ((v) / (div))
     258             : #else
     259             : #define DIVIDE(v, div, TYPE)    ((v) < 0 ? -(TYPE) (((u##TYPE) -(v) + ((u##TYPE) (div) >> 1)) / (div)) : (TYPE) (((u##TYPE) (v) + ((u##TYPE) (div) >> 1)) / (div)))
     260             : #endif
     261             : 
     262             : #define convertimpl(TYPE1, TYPE2)                                       \
     263             : static BUN                                                              \
     264             : convert_##TYPE1##_##TYPE2(const TYPE1 *restrict src,                    \
     265             :                           TYPE2 *restrict dst,                          \
     266             :                           struct canditer *restrict ci,                 \
     267             :                           oid candoff,                                  \
     268             :                           uint8_t scale1,                               \
     269             :                           uint8_t scale2,                               \
     270             :                           uint8_t precision,                            \
     271             :                           bool *reduce)                                 \
     272             : {                                                                       \
     273             :         BUN i;                                                          \
     274             :         BUN nils = 0;                                                   \
     275             :         TYPE1 v;                                                        \
     276             :         oid x;                                                          \
     277             :         const TYPE1 div = (TYPE1) scales[scale1 > scale2 ? scale1 - scale2 : 0]; \
     278             :         const TYPE2 mul = (TYPE2) scales[scale2 > scale1 ? scale2 - scale1 : 0]; \
     279             :         const TYPE2 min = GDK_##TYPE2##_min / mul;                      \
     280             :         const TYPE2 max = GDK_##TYPE2##_max / mul;                      \
     281             :         const TYPE2 prec = (TYPE2) scales[precision] / mul;             \
     282             :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();                      \
     283             :                                                                         \
     284             :         assert(div == 1 || mul == 1);                                   \
     285             :         assert(div >= 1 && mul >= 1);                                     \
     286             :                                                                         \
     287             :         *reduce = div > 1;                                           \
     288             :         if (ci->tpe == cand_dense) {                                 \
     289             :                 if (div == 1 && mul == 1) {                             \
     290             :                         TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {    \
     291             :                                 x = canditer_next_dense(ci) - candoff;  \
     292             :                                 v = src[x];                             \
     293             :                                 if (is_##TYPE1##_nil(v)) {              \
     294             :                                         dst[i] = TYPE2##_nil;           \
     295             :                                         nils++;                         \
     296             :                                 } else if (v < min || v > max ||  \
     297             :                                            (precision &&                \
     298             :                                             (v >= prec || v <= -prec))) { \
     299             :                                         CONV_OVERFLOW_PREC(TYPE1, #TYPE2, v, scale2, precision); \
     300             :                                 } else {                                \
     301             :                                         dst[i] = (TYPE2) v;             \
     302             :                                 }                                       \
     303             :                         }                                               \
     304             :                 } else if (div == 1) {                                  \
     305             :                         TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {    \
     306             :                                 x = canditer_next_dense(ci) - candoff;  \
     307             :                                 v = src[x];                             \
     308             :                                 if (is_##TYPE1##_nil(v)) {              \
     309             :                                         dst[i] = TYPE2##_nil;           \
     310             :                                         nils++;                         \
     311             :                                 } else if (v < min || v > max ||  \
     312             :                                            (precision &&                \
     313             :                                             (v >= prec || v <= -prec))) { \
     314             :                                         CONV_OVERFLOW_PREC(TYPE1, #TYPE2, src[x], scale2, precision); \
     315             :                                 } else {                                \
     316             :                                         dst[i] = (TYPE2) v * mul;       \
     317             :                                 }                                       \
     318             :                         }                                               \
     319             :                 } else {                                                \
     320             :                         /* mul == 1 */                                  \
     321             :                         TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {    \
     322             :                                 x = canditer_next_dense(ci) - candoff;  \
     323             :                                 v = src[x];                             \
     324             :                                 if (is_##TYPE1##_nil(v)) {              \
     325             :                                         dst[i] = TYPE2##_nil;           \
     326             :                                         nils++;                         \
     327             :                                 } else {                                \
     328             :                                         v = DIVIDE(v, div, TYPE1);      \
     329             :                                         if (v < min || v > max || \
     330             :                                             (precision &&               \
     331             :                                              (v >= prec || v <= -prec))) { \
     332             :                                                 CONV_OVERFLOW_PREC(TYPE1, #TYPE2, src[x], scale2, precision); \
     333             :                                         } else {                        \
     334             :                                                 dst[i] = (TYPE2) v;     \
     335             :                                         }                               \
     336             :                                 }                                       \
     337             :                         }                                               \
     338             :                 }                                                       \
     339             :         } else {                                                        \
     340             :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {            \
     341             :                         x = canditer_next(ci) - candoff;                \
     342             :                         v = src[x];                                     \
     343             :                         if (is_##TYPE1##_nil(v)) {                      \
     344             :                                 dst[i] = TYPE2##_nil;                   \
     345             :                                 nils++;                                 \
     346             :                         } else {                                        \
     347             :                                 v = DIVIDE(v, div, TYPE1);              \
     348             :                                 if (v < min || v > max ||         \
     349             :                                     (precision &&                       \
     350             :                                      (v >= prec || v <= -prec))) {        \
     351             :                                         CONV_OVERFLOW_PREC(TYPE1, #TYPE2, src[x], scale2, precision); \
     352             :                                 } else {                                \
     353             :                                         dst[i] = (TYPE2) v * mul;       \
     354             :                                 }                                       \
     355             :                         }                                               \
     356             :                 }                                                       \
     357             :         }                                                               \
     358             :         TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx));     \
     359             :         return nils;                                                    \
     360             : }
     361             : 
     362             : /* Special version of the above for converting from floating point.
     363             :  * The final assignment rounds the value which can still come out to
     364             :  * the NIL representation, so we need to check for that. */
     365             : #define convertimpl_reduce_float(TYPE1, TYPE2)                          \
     366             : static BUN                                                              \
     367             : convert_##TYPE1##_##TYPE2(const TYPE1 *src, TYPE2 *restrict dst,        \
     368             :                           struct canditer *restrict ci,                 \
     369             :                           oid candoff, uint8_t scale2, uint8_t precision, \
     370             :                           bool *reduce)                                 \
     371             : {                                                                       \
     372             :         BUN i, nils = 0;                                                \
     373             :         oid x;                                                          \
     374             :         TYPE1 v;                                                        \
     375             :         const TYPE2 mul = (TYPE2) scales[scale2];                       \
     376             :         const TYPE2 min = GDK_##TYPE2##_min;                            \
     377             :         const TYPE2 max = GDK_##TYPE2##_max;                            \
     378             :         const TYPE2 prec = (TYPE2) scales[precision];                   \
     379             :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();                      \
     380             :                                                                         \
     381             :         *reduce = true;                                                 \
     382             :         if (ci->tpe == cand_dense) {                                 \
     383             :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {            \
     384             :                         x = canditer_next_dense(ci) - candoff;          \
     385             :                         v = src[x];                                     \
     386             :                         if (is_##TYPE1##_nil(v)) {                      \
     387             :                                 dst[i] = TYPE2##_nil;                   \
     388             :                                 nils++;                                 \
     389             :                         } else if (v < (TYPE1) min || v > (TYPE1) max) { \
     390             :                                 CONV_OVERFLOW_PREC(TYPE1, #TYPE2, v, scale2, precision); \
     391             :                         } else {                                        \
     392             :                                 ldouble m = (ldouble) v * mul;          \
     393             :                                 dst[i] = (TYPE2) rounddbl(m);           \
     394             :                                 if (is_##TYPE2##_nil(dst[i]) ||         \
     395             :                                     (precision &&                       \
     396             :                                      (dst[i] >= prec ||                      \
     397             :                                       dst[i] <= -prec)))             \
     398             :                                         CONV_OVERFLOW_PREC(TYPE1, #TYPE2, v, scale2, precision); \
     399             :                         }                                               \
     400             :                 }                                                       \
     401             :                 TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx)); \
     402             :         } else {                                                        \
     403             :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {            \
     404             :                         x = canditer_next(ci) - candoff;                \
     405             :                         v = src[x];                                     \
     406             :                         if (is_##TYPE1##_nil(v)) {                      \
     407             :                                 dst[i] = TYPE2##_nil;                   \
     408             :                                 nils++;                                 \
     409             :                         } else if (v < (TYPE1) min || v > (TYPE1) max) { \
     410             :                                 CONV_OVERFLOW_PREC(TYPE1, #TYPE2, v, scale2, precision); \
     411             :                         } else {                                        \
     412             :                                 ldouble m = (ldouble) v * mul;          \
     413             :                                 dst[i] = (TYPE2) rounddbl(m);           \
     414             :                                 if (is_##TYPE2##_nil(dst[i]) ||         \
     415             :                                     (precision &&                       \
     416             :                                      (dst[i] >= prec ||                      \
     417             :                                       dst[i] <= -prec)))             \
     418             :                                         CONV_OVERFLOW_PREC(TYPE1, #TYPE2, v, scale2, precision); \
     419             :                         }                                               \
     420             :                 }                                                       \
     421             :                 TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx)); \
     422             :         }                                                               \
     423             :         return nils;                                                    \
     424             : }
     425             : 
     426             : #define convert2bit_impl(TYPE)                                          \
     427             : static BUN                                                              \
     428             : convert_##TYPE##_bit(const TYPE *src, bit *restrict dst,                \
     429             :                      struct canditer *restrict ci,                      \
     430             :                      oid candoff, bool *reduce)                         \
     431             : {                                                                       \
     432             :         BUN i, nils = 0;                                                \
     433             :         oid x;                                                          \
     434             :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();                      \
     435             :                                                                         \
     436             :         *reduce = true;                                                 \
     437             :         if (ci->tpe == cand_dense) {                                 \
     438             :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {            \
     439             :                         x = canditer_next_dense(ci) - candoff;          \
     440             :                         if (is_##TYPE##_nil(src[x])) {                  \
     441             :                                 dst[i] = bit_nil;                       \
     442             :                                 nils++;                                 \
     443             :                         } else                                          \
     444             :                                 dst[i] = (bit) (src[x] != 0);           \
     445             :                 }                                                       \
     446             :                 TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx)); \
     447             :         } else {                                                        \
     448             :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {            \
     449             :                         x = canditer_next(ci) - candoff;                \
     450             :                         if (is_##TYPE##_nil(src[x])) {                  \
     451             :                                 dst[i] = bit_nil;                       \
     452             :                                 nils++;                                 \
     453             :                         } else                                          \
     454             :                                 dst[i] = (bit) (src[x] != 0);           \
     455             :                 }                                                       \
     456             :                 TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx)); \
     457             :         }                                                               \
     458             :         return nils;                                                    \
     459             : }
     460             : 
     461             : #define convertimpl_msk(TYPE)                                           \
     462             : static BUN                                                              \
     463             : convert_##TYPE##_msk(const TYPE *src, uint32_t *restrict dst,           \
     464             :                      struct canditer *restrict ci,                      \
     465             :                      oid candoff, bool *reduce)                         \
     466             : {                                                                       \
     467             :         BUN cnt = ci->ncand / 32;                                    \
     468             :         BUN i, j;                                                       \
     469             :         uint32_t mask;                                                  \
     470             :         oid x;                                                          \
     471             :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();                      \
     472             :                                                                         \
     473             :         *reduce = true;                                                 \
     474             :         if (ci->tpe == cand_dense) {                                 \
     475             :                 TIMEOUT_LOOP_IDX(i, cnt, qry_ctx) {                     \
     476             :                         mask = 0;                                       \
     477             :                         for (j = 0; j < 32; j++) {                   \
     478             :                                 x = canditer_next_dense(ci) - candoff;  \
     479             :                                 mask |= (uint32_t) (!is_##TYPE##_nil(src[x]) && src[x] != 0) << j; \
     480             :                         }                                               \
     481             :                         dst[i] = mask;                                  \
     482             :                 }                                                       \
     483             :                 TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx)); \
     484             :                 cnt = ci->ncand % 32;                                        \
     485             :                 if (cnt > 0) {                                               \
     486             :                         mask = 0;                                       \
     487             :                         for (j = 0; j < cnt; j++) {                  \
     488             :                                 x = canditer_next_dense(ci) - candoff;  \
     489             :                                 mask |= (uint32_t) (!is_##TYPE##_nil(src[x]) && src[x] != 0) << j; \
     490             :                         }                                               \
     491             :                         dst[i] = mask;                                  \
     492             :                 }                                                       \
     493             :         } else {                                                        \
     494             :                 TIMEOUT_LOOP_IDX(i, cnt, qry_ctx) {                     \
     495             :                         mask = 0;                                       \
     496             :                         for (j = 0; j < 32; j++) {                   \
     497             :                                 x = canditer_next(ci) - candoff;        \
     498             :                                 mask |= (uint32_t) (!is_##TYPE##_nil(src[x]) && src[x] != 0) << j; \
     499             :                         }                                               \
     500             :                         dst[i] = mask;                                  \
     501             :                 }                                                       \
     502             :                 TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx)); \
     503             :                 cnt = ci->ncand % 32;                                        \
     504             :                 if (cnt > 0) {                                               \
     505             :                         mask = 0;                                       \
     506             :                         for (j = 0; j < cnt; j++) {                  \
     507             :                                 x = canditer_next(ci) - candoff;        \
     508             :                                 mask |= (uint32_t) (!is_##TYPE##_nil(src[x]) && src[x] != 0) << j; \
     509             :                         }                                               \
     510             :                         dst[i] = mask;                                  \
     511             :                 }                                                       \
     512             :         }                                                               \
     513             :         return 0;                                                       \
     514             : }                                                                       \
     515             :                                                                         \
     516             : static BUN                                                              \
     517             : convert_msk_##TYPE(const uint32_t *src, TYPE *restrict dst,             \
     518             :                    struct canditer *restrict ci,                        \
     519             :                    oid candoff, bool *reduce)                           \
     520             : {                                                                       \
     521             :         BUN nils = 0;                                                   \
     522             :         BUN k;                                                          \
     523             :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();                      \
     524             :                                                                         \
     525             :         *reduce = false;                                                \
     526             :         if (ci->tpe == cand_dense) {                                 \
     527             :                 uint32_t mask;                                          \
     528             :                 BUN i = (ci->seq - candoff) / 32;                    \
     529             :                 BUN cnt = (ci->seq + ci->ncand - candoff) / 32;           \
     530             :                 BUN first = (ci->seq - candoff) % 32;                        \
     531             :                 BUN rem = (ci->seq + ci->ncand - candoff) % 32;           \
     532             :                 BUN j;                                                  \
     533             :                 k = 0;                                                  \
     534             :                 for (; i < cnt; i++) {                                       \
     535             :                         mask = src[i];                                  \
     536             :                         for (j = first; j < 32; j++) {                       \
     537             :                                 dst[k] = (TYPE) ((mask & (1U << j)) != 0); \
     538             :                                 k++;                                    \
     539             :                         }                                               \
     540             :                         first = 0;                                      \
     541             :                 }                                                       \
     542             :                 if (rem > first) {                                   \
     543             :                         mask = src[i];                                  \
     544             :                         for (j = first; j < rem; j++) {                      \
     545             :                                 dst[k] = (TYPE) ((mask & (1U << j)) != 0); \
     546             :                                 k++;                                    \
     547             :                         }                                               \
     548             :                 }                                                       \
     549             :         } else {                                                        \
     550             :                 TIMEOUT_LOOP_IDX(k, ci->ncand, qry_ctx) {            \
     551             :                         oid x = canditer_next(ci) - candoff;            \
     552             :                         dst[k] = (TYPE) ((src[x / 32] & (1U << (x % 32))) != 0); \
     553             :                 }                                                       \
     554             :                 TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx)); \
     555             :         }                                                               \
     556             :         return nils;                                                    \
     557             : }
     558             : 
     559         655 : convertimpl(bte, bte)
     560     4637428 : convertimpl(bte, sht)
     561     5848731 : convertimpl(bte, int)
     562          36 : convertimpl_oid_enlarge(bte)
     563     8700097 : convertimpl(bte, lng)
     564             : #ifdef HAVE_HGE
     565      649022 : convertimpl(bte, hge)
     566             : #endif
     567        1036 : convertimpl_enlarge_float(bte, flt, FLT_MANT_DIG)
     568       48186 : convertimpl_enlarge_float(bte, dbl, DBL_MANT_DIG)
     569             : 
     570          56 : convertimpl(sht, bte)
     571         296 : convertimpl(sht, sht)
     572     5616765 : convertimpl(sht, int)
     573           2 : convertimpl_oid_enlarge(sht)
     574    11792860 : convertimpl(sht, lng)
     575             : #ifdef HAVE_HGE
     576        2563 : convertimpl(sht, hge)
     577             : #endif
     578         192 : convertimpl_enlarge_float(sht, flt, FLT_MANT_DIG)
     579        3139 : convertimpl_enlarge_float(sht, dbl, DBL_MANT_DIG)
     580             : 
     581        1445 : convertimpl(int, bte)
     582       19659 : convertimpl(int, sht)
     583         764 : convertimpl(int, int)
     584          38 : convertimpl_oid_enlarge(int)
     585   185558908 : convertimpl(int, lng)
     586             : #ifdef HAVE_HGE
     587       33215 : convertimpl(int, hge)
     588             : #endif
     589     1684711 : convertimpl_enlarge_float(int, flt, FLT_MANT_DIG)
     590       81639 : convertimpl_enlarge_float(int, dbl, DBL_MANT_DIG)
     591             : 
     592         170 : convertimpl(lng, bte)
     593      129637 : convertimpl(lng, sht)
     594     2067624 : convertimpl(lng, int)
     595             : #if SIZEOF_OID == SIZEOF_LNG
     596        9308 : convertimpl_oid_enlarge(lng)
     597             : #else
     598             : convertimpl_oid_reduce(lng)
     599             : #endif
     600     4838924 : convertimpl(lng, lng)
     601             : #ifdef HAVE_HGE
     602    11397888 : convertimpl(lng, hge)
     603             : #endif
     604         308 : convertimpl_enlarge_float(lng, flt, FLT_MANT_DIG)
     605      287504 : convertimpl_enlarge_float(lng, dbl, DBL_MANT_DIG)
     606             : 
     607             : #ifdef HAVE_HGE
     608          71 : convertimpl(hge, bte)
     609          77 : convertimpl(hge, sht)
     610        8787 : convertimpl(hge, int)
     611           0 : convertimpl_oid_reduce(hge)
     612       47580 : convertimpl(hge, lng)
     613     2118293 : convertimpl(hge, hge)
     614          60 : convertimpl_enlarge_float(hge, flt, FLT_MANT_DIG)
     615         225 : convertimpl_enlarge_float(hge, dbl, DBL_MANT_DIG)
     616             : #endif
     617             : 
     618          20 : convertimpl_reduce_float(flt, bte)
     619          24 : convertimpl_reduce_float(flt, sht)
     620          34 : convertimpl_reduce_float(flt, int)
     621           0 : convertimpl_oid_reduce(flt)
     622         272 : convertimpl_reduce_float(flt, lng)
     623             : #ifdef HAVE_HGE
     624          30 : convertimpl_reduce_float(flt, hge)
     625             : #endif
     626          38 : convertimpl_enlarge_float(flt, flt, 128)
     627     7533724 : convertimpl_enlarge_float(flt, dbl, DBL_MANT_DIG)
     628             : 
     629         151 : convertimpl_reduce_float(dbl, bte)
     630          55 : convertimpl_reduce_float(dbl, sht)
     631         749 : convertimpl_reduce_float(dbl, int)
     632           0 : convertimpl_oid_reduce(dbl)
     633      300496 : convertimpl_reduce_float(dbl, lng)
     634             : #ifdef HAVE_HGE
     635         130 : convertimpl_reduce_float(dbl, hge)
     636             : #endif
     637             : #undef rounddbl
     638             : /* no rounding here */
     639             : #define rounddbl(x)     (x)
     640         260 : convertimpl_reduce_float(dbl, flt)
     641           0 : convertimpl_enlarge_float(dbl, dbl, 128)
     642             : 
     643     1066770 : convert2bit_impl(bte)
     644         100 : convert2bit_impl(sht)
     645         459 : convert2bit_impl(int)
     646       14410 : convert2bit_impl(lng)
     647             : #ifdef HAVE_HGE
     648          36 : convert2bit_impl(hge)
     649             : #endif
     650          34 : convert2bit_impl(flt)
     651          74 : convert2bit_impl(dbl)
     652             : 
     653           0 : convertimpl_msk(bte)
     654           0 : convertimpl_msk(sht)
     655           0 : convertimpl_msk(int)
     656           0 : convertimpl_msk(lng)
     657             : #ifdef HAVE_HGE
     658           0 : convertimpl_msk(hge)
     659             : #endif
     660           0 : convertimpl_msk(flt)
     661           0 : convertimpl_msk(dbl)
     662             : 
     663             : static BUN
     664         180 : convert_any_str(BATiter *bi, BAT *bn, struct canditer *restrict ci)
     665             : {
     666         180 :         int tp = bi->type;
     667         180 :         oid candoff = bi->b->hseqbase;
     668         180 :         str dst = 0;
     669         180 :         size_t len = 0;
     670         180 :         BUN nils = 0;
     671         180 :         BUN i;
     672         180 :         const void *nil = ATOMnilptr(tp);
     673         180 :         const void *restrict src;
     674         180 :         ssize_t (*atomtostr)(str *, size_t *, const void *, bool) = BATatoms[tp].atomToStr;
     675         180 :         int (*atomcmp)(const void *, const void *) = ATOMcompare(tp);
     676         180 :         oid x;
     677             : 
     678         180 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     679             : 
     680         179 :         if (atomtostr == BATatoms[TYPE_str].atomToStr) {
     681             :                 /* compatible with str, we just copy the value */
     682           0 :                 assert(bi->type != TYPE_void);
     683           0 :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     684           0 :                         x = canditer_next(ci) - candoff;
     685           0 :                         src = BUNtvar(*bi, x);
     686           0 :                         if (strNil(src))
     687           0 :                                 nils++;
     688           0 :                         if (tfastins_nocheckVAR(bn, i, src) != GDK_SUCCEED) {
     689           0 :                                 goto bailout;
     690             :                         }
     691             :                 }
     692         179 :         } else if (bi->b->tvheap) {
     693          12 :                 assert(bi->type != TYPE_void);
     694          82 :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     695          46 :                         x = canditer_next(ci) - candoff;
     696          46 :                         src = BUNtvar(*bi, x);
     697          46 :                         if ((*atomcmp)(src, nil) == 0) {
     698           6 :                                 nils++;
     699           6 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED) {
     700           0 :                                         goto bailout;
     701             :                                 }
     702             :                         } else {
     703          80 :                                 if ((*atomtostr)(&dst, &len, src, false) < 0 ||
     704          40 :                                     tfastins_nocheckVAR(bn, i, dst) != GDK_SUCCEED) {
     705           0 :                                         goto bailout;
     706             :                                 }
     707             :                         }
     708             :                 }
     709         167 :         } else if (ATOMstorage(bi->type) == TYPE_msk) {
     710           0 :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     711           0 :                         const char *v;
     712           0 :                         x = canditer_next(ci) - candoff;
     713           0 :                         v = Tmskval(bi, x) ? "1" : "0";
     714           0 :                         if (tfastins_nocheckVAR(bn, i, v) != GDK_SUCCEED)
     715           0 :                                 goto bailout;
     716             :                 }
     717             :         } else {
     718     1008732 :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     719     1008167 :                         x = canditer_next(ci) - candoff;
     720     1008170 :                         src = BUNtloc(*bi, x);
     721     1008170 :                         if ((*atomcmp)(src, nil) == 0) {
     722        4117 :                                 nils++;
     723        4117 :                                 if (tfastins_nocheckVAR(bn, i, str_nil) != GDK_SUCCEED)
     724           0 :                                         goto bailout;
     725             :                         } else {
     726     1004055 :                                 if ((*atomtostr)(&dst, &len, src, false) < 0)
     727           0 :                                         goto bailout;
     728     1004054 :                                 if (tfastins_nocheckVAR(bn, i, dst) != GDK_SUCCEED)
     729           0 :                                         goto bailout;
     730             :                         }
     731             :                 }
     732             :         }
     733         180 :         GDKfree(dst);
     734         181 :         TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx));
     735         180 :         BATsetcount(bn, ci->ncand);
     736         180 :         return nils;
     737           0 :   bailout:
     738           0 :         GDKfree(dst);
     739           0 :         return BUN_NONE + 2;
     740             : }
     741             : 
     742             : static BUN
     743           9 : convert_str_var(BATiter *bi, BAT *bn, struct canditer *restrict ci)
     744             : {
     745           9 :         int tp = bn->ttype;
     746           9 :         oid candoff = bi->b->hseqbase;
     747           9 :         void *dst = 0;
     748           9 :         size_t len = 0;
     749           9 :         BUN nils = 0;
     750           9 :         BUN i;
     751           9 :         const void *nil = ATOMnilptr(tp);
     752           9 :         const char *restrict src;
     753           9 :         ssize_t (*atomfromstr)(const char *, size_t *, ptr *, bool) = BATatoms[tp].atomFromStr;
     754           9 :         oid x;
     755             : 
     756           9 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     757             : 
     758        2034 :         TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     759        2007 :                 x = canditer_next(ci) - candoff;
     760        2007 :                 src = BUNtvar(*bi, x);
     761        2007 :                 if (strNil(src)) {
     762           0 :                         nils++;
     763           0 :                         if (tfastins_nocheckVAR(bn, i, nil) != GDK_SUCCEED) {
     764           0 :                                 goto bailout;
     765             :                         }
     766             :                 } else {
     767        2007 :                         ssize_t l;
     768        2007 :                         if ((l = (*atomfromstr)(src, &len, &dst, false)) < 0 ||
     769        4014 :                             l < (ssize_t) strlen(src) ||
     770        2007 :                             tfastins_nocheckVAR(bn, i, dst) != GDK_SUCCEED) {
     771           0 :                                 goto bailout;
     772             :                         }
     773             :                 }
     774             :         }
     775           9 :         GDKfree(dst);
     776           9 :         TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx));
     777           9 :         BATsetcount(bn, ci->ncand);
     778           9 :         return nils;
     779           0 :   bailout:
     780           0 :         GDKfree(dst);
     781           0 :         return BUN_NONE + 2;
     782             : }
     783             : 
     784             : static BUN
     785        1318 : convert_str_fix(BATiter *bi, int tp, void *restrict dst,
     786             :                 struct canditer *restrict ci, oid candoff)
     787             : {
     788        1318 :         BUN nils = 0;
     789        1318 :         const void *nil = ATOMnilptr(tp);
     790        1318 :         size_t len = ATOMsize(tp);
     791        1318 :         ssize_t l;
     792        1318 :         ssize_t (*atomfromstr)(const char *, size_t *, ptr *, bool) = BATatoms[tp].atomFromStr;
     793        1318 :         const char *s = NULL;
     794             : 
     795        1318 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     796             : 
     797        1318 :         if (ATOMstorage(tp) == TYPE_msk) {
     798           0 :                 uint32_t mask = 0;
     799           0 :                 uint32_t *d = dst;
     800           0 :                 int j = 0;
     801           0 :                 TIMEOUT_LOOP(ci->ncand, qry_ctx) {
     802           0 :                         oid x = canditer_next(ci) - candoff;
     803           0 :                         uint32_t v;
     804           0 :                         s = BUNtvar(*bi, x);
     805           0 :                         if (strcmp(s, "0") == 0)
     806             :                                 v = 0;
     807           0 :                         else if (strcmp(s, "1") == 0)
     808             :                                 v = 1;
     809             :                         else
     810           0 :                                 goto conversion_failed;
     811           0 :                         mask |= v << j;
     812           0 :                         if (++j == 32) {
     813           0 :                                 *d++ = mask;
     814           0 :                                 j = 0;
     815           0 :                                 mask = 0;
     816             :                         }
     817             :                 }
     818           0 :                 TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx));
     819           0 :                 if (j > 0)
     820           0 :                         *d = mask;
     821           0 :                 return 0;
     822             :         }
     823             : 
     824        1318 :         int (*atomcmp)(const void *, const void *) = ATOMcompare(tp);
     825      231941 :         TIMEOUT_LOOP(ci->ncand, qry_ctx) {
     826      229319 :                 oid x = canditer_next(ci) - candoff;
     827      224509 :                 const char *s = BUNtvar(*bi, x);
     828      224984 :                 if (strNil(s)) {
     829           5 :                         memcpy(dst, nil, len);
     830           5 :                         nils++;
     831             :                 } else {
     832      224979 :                         void *d = dst;
     833      224979 :                         if ((l = (*atomfromstr)(s, &len, &d, false)) < 0 ||
     834      236367 :                             l < (ssize_t) strlen(s)) {
     835          12 :                                 goto conversion_failed;
     836             :                         }
     837      236365 :                         assert(len == ATOMsize(tp));
     838      236365 :                         if (atomcmp(dst, nil) == 0)
     839           0 :                                 nils++;
     840             :                 }
     841      229313 :                 dst = (void *) ((char *) dst + len);
     842             :         }
     843        1310 :         TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx));
     844             :         return nils;
     845             : 
     846           0 :   conversion_failed:
     847           0 :         GDKclrerr();
     848          12 :         size_t sz = 0;
     849          12 :         char *bf = NULL;
     850             : 
     851          12 :         if (s) {
     852           0 :                 sz = escapedStrlen(s, NULL, NULL, '\'');
     853           0 :                 bf = GDKmalloc(sz + 1);
     854             :         }
     855          12 :         if (bf) {
     856           0 :                 escapedStr(bf, s, sz + 1, NULL, NULL, '\'');
     857           0 :                 GDKerror("22018!conversion of string "
     858             :                          "'%s' to type %s failed.\n",
     859             :                          bf, ATOMname(tp));
     860           0 :                 GDKfree(bf);
     861             :         } else {
     862          12 :                 GDKerror("22018!conversion of string "
     863             :                          "to type %s failed.\n",
     864             :                          ATOMname(tp));
     865             :         }
     866             :         return BUN_NONE;
     867             : }
     868             : 
     869             : static BUN
     870           0 : convert_void_any(oid seq, BAT *bn,
     871             :                  struct canditer *restrict ci,
     872             :                  oid candoff, bool *reduce)
     873             : {
     874           0 :         BUN nils = 0;
     875           0 :         BUN i;
     876           0 :         int tp = bn->ttype;
     877           0 :         void *restrict dst = Tloc(bn, 0);
     878           0 :         ssize_t (*atomtostr)(str *, size_t *, const void *, bool) = BATatoms[TYPE_oid].atomToStr;
     879           0 :         char *s = NULL;
     880           0 :         size_t len = 0;
     881           0 :         oid x;
     882             : 
     883           0 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     884             : 
     885           0 :         *reduce = false;
     886           0 :         assert(!is_oid_nil(seq));
     887             : 
     888           0 :         switch (ATOMbasetype(tp)) {
     889           0 :         case TYPE_bte:
     890           0 :                 if (tp == TYPE_bit) {
     891           0 :                         if (ci->ncand > 0) {
     892           0 :                                 x = canditer_next(ci) - candoff;
     893           0 :                                 ((bit *) dst)[0] = x + seq != 0;
     894             :                         }
     895           0 :                         TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     896           0 :                                 ((bit *) dst)[i] = 1;
     897             :                         }
     898             :                 } else {
     899           0 :                         TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     900           0 :                                 x = canditer_next(ci) - candoff;
     901           0 :                                 if (seq + x > GDK_bte_max) {
     902           0 :                                         CONV_OVERFLOW(oid, "bte", seq + x);
     903             :                                 } else {
     904           0 :                                         ((bte *) dst)[i] = (bte) (seq + x);
     905             :                                 }
     906             :                         }
     907             :                 }
     908             :                 break;
     909           0 :         case TYPE_sht:
     910           0 :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     911           0 :                         x = canditer_next(ci) - candoff;
     912           0 :                         if (seq + x > GDK_sht_max) {
     913           0 :                                 CONV_OVERFLOW(oid, "sht", seq + x);
     914             :                         } else {
     915           0 :                                 ((sht *) dst)[i] = (sht) (seq + x);
     916             :                         }
     917             :                 }
     918             :                 break;
     919           0 :         case TYPE_int:
     920           0 :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     921           0 :                         x = canditer_next(ci) - candoff;
     922             : #if SIZEOF_OID > SIZEOF_INT
     923           0 :                         if (seq + x > GDK_int_max) {
     924           0 :                                 CONV_OVERFLOW(oid, "int", seq + x);
     925             :                         } else
     926             : #endif
     927           0 :                                 ((int *) dst)[i] = (int) (seq + x);
     928             :                 }
     929             :                 break;
     930           0 :         case TYPE_lng:
     931           0 :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     932           0 :                         x = canditer_next(ci) - candoff;
     933           0 :                         ((lng *) dst)[i] = (lng) (seq + x);
     934             :                 }
     935             :                 break;
     936             : #ifdef HAVE_HGE
     937           0 :         case TYPE_hge:
     938           0 :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     939           0 :                         x = canditer_next(ci) - candoff;
     940           0 :                         ((hge *) dst)[i] = (hge) (seq + x);
     941             :                 }
     942             :                 break;
     943             : #endif
     944           0 :         case TYPE_flt:
     945           0 :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     946           0 :                         x = canditer_next(ci) - candoff;
     947           0 :                         ((flt *) dst)[i] = (flt) (seq + x);
     948             :                 }
     949             :                 break;
     950           0 :         case TYPE_dbl:
     951           0 :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     952           0 :                         x = canditer_next(ci) - candoff;
     953           0 :                         ((dbl *) dst)[i] = (dbl) (seq + x);
     954             :                 }
     955             :                 break;
     956           0 :         case TYPE_str:
     957           0 :                 TIMEOUT_LOOP_IDX(i, ci->ncand, qry_ctx) {
     958           0 :                         x = canditer_next(ci) - candoff;
     959           0 :                         if ((*atomtostr)(&s, &len, &(oid){seq + x}, false) < 0)
     960           0 :                                 goto bailout;
     961           0 :                         if (tfastins_nocheckVAR(bn, i, s) != GDK_SUCCEED)
     962           0 :                                 goto bailout;
     963             :                 }
     964           0 :                 GDKfree(s);
     965           0 :                 s = NULL;
     966           0 :                 break;
     967             :         default:
     968             :                 return BUN_NONE + 1;
     969             :         }
     970           0 :         TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx));
     971             : 
     972           0 :         bn->theap->dirty = true;
     973           0 :         return nils;
     974             : 
     975           0 :   bailout:
     976           0 :         GDKfree(s);
     977           0 :         return BUN_NONE + 2;
     978             : }
     979             : 
     980             : static BUN
     981     2020771 : convert_typeswitchloop(const void *src, int stp, void *restrict dst, int dtp,
     982             :                        struct canditer *restrict ci,
     983             :                        oid candoff, bool *reduce,
     984             :                        uint8_t scale1, uint8_t scale2, uint8_t precision)
     985             : {
     986     2020771 :         assert(stp == TYPE_flt || stp == TYPE_dbl || scale1 < (uint8_t) (sizeof(scales) / sizeof(scales[0])));
     987     2020771 :         assert(dtp == TYPE_flt || dtp == TYPE_dbl || scale2 < (uint8_t) (sizeof(scales) / sizeof(scales[0])));
     988     4041222 :         switch (ATOMbasetype(stp)) {
     989           0 :         case TYPE_msk:
     990           0 :                 switch (ATOMbasetype(dtp)) {
     991             :                 /* case TYPE_msk not needed: it is done with the help
     992             :                  * of BATappend */
     993           0 :                 case TYPE_bte:
     994           0 :                         return convert_bte_msk(src, dst, ci, candoff,
     995             :                                                reduce);
     996           0 :                 case TYPE_sht:
     997           0 :                         return convert_sht_msk(src, dst, ci, candoff,
     998             :                                                reduce);
     999           0 :                 case TYPE_int:
    1000           0 :                         return convert_int_msk(src, dst, ci, candoff,
    1001             :                                                reduce);
    1002           0 :                 case TYPE_lng:
    1003           0 :                         return convert_lng_msk(src, dst, ci, candoff,
    1004             :                                                reduce);
    1005             : #ifdef HAVE_HGE
    1006           0 :                 case TYPE_hge:
    1007           0 :                         return convert_hge_msk(src, dst, ci, candoff,
    1008             :                                                reduce);
    1009             : #endif
    1010           0 :                 case TYPE_flt:
    1011           0 :                         return convert_flt_msk(src, dst, ci, candoff,
    1012             :                                                reduce);
    1013           0 :                 case TYPE_dbl:
    1014           0 :                         return convert_dbl_msk(src, dst, ci, candoff,
    1015             :                                                reduce);
    1016             :                 default:
    1017             :                         return BUN_NONE + 1;
    1018             :                 }
    1019      561615 :         case TYPE_bte:
    1020     1123145 :                 switch (ATOMbasetype(dtp)) {
    1021           0 :                 case TYPE_msk:
    1022           0 :                         return convert_msk_bte(src, dst, ci, candoff,
    1023             :                                                reduce);
    1024         212 :                 case TYPE_bte:
    1025         212 :                         if (dtp == TYPE_bit)
    1026          76 :                                 return convert_bte_bit(src, dst, ci,
    1027             :                                                        candoff, reduce);
    1028         136 :                         return convert_bte_bte(src, dst, ci, candoff,
    1029             :                                                scale1,
    1030             :                                                scale2,
    1031             :                                                precision, reduce);
    1032      159158 :                 case TYPE_sht:
    1033      159158 :                         return convert_bte_sht(src, dst, ci, candoff,
    1034             :                                                scale1,
    1035             :                                                scale2,
    1036             :                                                precision, reduce);
    1037      368920 :                 case TYPE_int:
    1038             : #if SIZEOF_OID == SIZEOF_INT
    1039             :                         if (dtp == TYPE_oid)
    1040             :                                 return convert_bte_oid(src, dst, ci,
    1041             :                                                        candoff,
    1042             :                                                        reduce);
    1043             : #endif
    1044      368920 :                         return convert_bte_int(src, dst, ci, candoff,
    1045             :                                                scale1,
    1046             :                                                scale2,
    1047             :                                                precision, reduce);
    1048       30080 :                 case TYPE_lng:
    1049             : #if SIZEOF_OID == SIZEOF_LNG
    1050       30080 :                         if (dtp == TYPE_oid)
    1051           9 :                                 return convert_bte_oid(src, dst, ci,
    1052             :                                                        candoff,
    1053             :                                                        reduce);
    1054             : #endif
    1055       30071 :                         return convert_bte_lng(src, dst, ci, candoff,
    1056             :                                                scale1,
    1057             :                                                scale2,
    1058             :                                                precision, reduce);
    1059             : #ifdef HAVE_HGE
    1060        1162 :                 case TYPE_hge:
    1061        1162 :                         return convert_bte_hge(src, dst, ci, candoff,
    1062             :                                                scale1,
    1063             :                                                scale2,
    1064             :                                                precision, reduce);
    1065             : #endif
    1066         207 :                 case TYPE_flt:
    1067         207 :                         return convert_bte_flt(src, dst, ci, candoff,
    1068             :                                                scale1,
    1069             :                                                reduce);
    1070        1876 :                 case TYPE_dbl:
    1071        1876 :                         return convert_bte_dbl(src, dst, ci, candoff,
    1072             :                                                scale1,
    1073             :                                                reduce);
    1074             :                 default:
    1075             :                         return BUN_NONE + 1;
    1076             :                 }
    1077      260267 :         case TYPE_sht:
    1078      520521 :                 switch (ATOMbasetype(dtp)) {
    1079           0 :                 case TYPE_msk:
    1080           0 :                         return convert_msk_sht(src, dst, ci, candoff,
    1081             :                                                reduce);
    1082          23 :                 case TYPE_bte:
    1083          23 :                         if (dtp == TYPE_bit)
    1084          11 :                                 return convert_sht_bit(src, dst, ci,
    1085             :                                                        candoff, reduce);
    1086          12 :                         return convert_sht_bte(src, dst, ci, candoff,
    1087             :                                                scale1,
    1088             :                                                scale2,
    1089             :                                                precision, reduce);
    1090          73 :                 case TYPE_sht:
    1091          73 :                         return convert_sht_sht(src, dst, ci, candoff,
    1092             :                                                scale1,
    1093             :                                                scale2,
    1094             :                                                precision, reduce);
    1095      257269 :                 case TYPE_int:
    1096             : #if SIZEOF_OID == SIZEOF_INT
    1097             :                         if (dtp == TYPE_oid)
    1098             :                                 return convert_sht_oid(src, dst, ci,
    1099             :                                                        candoff,
    1100             :                                                        reduce);
    1101             : #endif
    1102      257269 :                         return convert_sht_int(src, dst, ci, candoff,
    1103             :                                                scale1,
    1104             :                                                scale2,
    1105             :                                                precision, reduce);
    1106        1544 :                 case TYPE_lng:
    1107             : #if SIZEOF_OID == SIZEOF_LNG
    1108        1544 :                         if (dtp == TYPE_oid)
    1109           2 :                                 return convert_sht_oid(src, dst, ci,
    1110             :                                                        candoff,
    1111             :                                                        reduce);
    1112             : #endif
    1113        1542 :                         return convert_sht_lng(src, dst, ci, candoff,
    1114             :                                                scale1,
    1115             :                                                scale2,
    1116             :                                                precision, reduce);
    1117             : #ifdef HAVE_HGE
    1118         549 :                 case TYPE_hge:
    1119         549 :                         return convert_sht_hge(src, dst, ci, candoff,
    1120             :                                                scale1,
    1121             :                                                scale2,
    1122             :                                                precision, reduce);
    1123             : #endif
    1124          41 :                 case TYPE_flt:
    1125          41 :                         return convert_sht_flt(src, dst, ci, candoff,
    1126             :                                                scale1,
    1127             :                                                reduce);
    1128         768 :                 case TYPE_dbl:
    1129         768 :                         return convert_sht_dbl(src, dst, ci, candoff,
    1130             :                                                scale1,
    1131             :                                                reduce);
    1132             :                 default:
    1133             :                         return BUN_NONE + 1;
    1134             :                 }
    1135     1192258 :         case TYPE_int:
    1136     2384417 :                 switch (ATOMbasetype(dtp)) {
    1137           0 :                 case TYPE_msk:
    1138           0 :                         return convert_msk_int(src, dst, ci, candoff,
    1139             :                                                reduce);
    1140         450 :                 case TYPE_bte:
    1141         450 :                         if (dtp == TYPE_bit) {
    1142          88 :                                 return convert_int_bit(src, dst, ci,
    1143             :                                                        candoff, reduce);
    1144             :                         }
    1145         362 :                         return convert_int_bte(src, dst, ci, candoff,
    1146             :                                                scale1,
    1147             :                                                scale2,
    1148             :                                                precision, reduce);
    1149        2569 :                 case TYPE_sht:
    1150        2569 :                         return convert_int_sht(src, dst, ci, candoff,
    1151             :                                                scale1,
    1152             :                                                scale2,
    1153             :                                                precision, reduce);
    1154         193 :                 case TYPE_int:
    1155             : #if SIZEOF_OID == SIZEOF_INT
    1156             :                         if (dtp == TYPE_oid)
    1157             :                                 return convert_int_oid(src, dst, ci,
    1158             :                                                        candoff,
    1159             :                                                        reduce);
    1160             : #endif
    1161         193 :                         return convert_int_int(src, dst, ci, candoff,
    1162             :                                                scale1,
    1163             :                                                scale2,
    1164             :                                                precision, reduce);
    1165     1171112 :                 case TYPE_lng:
    1166             : #if SIZEOF_OID == SIZEOF_LNG
    1167     1171112 :                         if (dtp == TYPE_oid)
    1168           9 :                                 return convert_int_oid(src, dst, ci,
    1169             :                                                        candoff,
    1170             :                                                        reduce);
    1171             : #endif
    1172     1171103 :                         return convert_int_lng(src, dst, ci, candoff,
    1173             :                                                scale1,
    1174             :                                                scale2,
    1175             :                                                precision, reduce);
    1176             : #ifdef HAVE_HGE
    1177        1826 :                 case TYPE_hge:
    1178        1826 :                         return convert_int_hge(src, dst, ci, candoff,
    1179             :                                                scale1,
    1180             :                                                scale2,
    1181             :                                                precision, reduce);
    1182             : #endif
    1183         174 :                 case TYPE_flt:
    1184         174 :                         return convert_int_flt(src, dst, ci, candoff,
    1185             :                                                scale1,
    1186             :                                                reduce);
    1187       15933 :                 case TYPE_dbl:
    1188       15933 :                         return convert_int_dbl(src, dst, ci, candoff,
    1189             :                                                scale1,
    1190             :                                                reduce);
    1191             :                 default:
    1192             :                         return BUN_NONE + 1;
    1193             :                 }
    1194        5452 :         case TYPE_lng:
    1195       10874 :                 switch (ATOMbasetype(dtp)) {
    1196           0 :                 case TYPE_msk:
    1197           0 :                         return convert_msk_lng(src, dst, ci, candoff,
    1198             :                                                reduce);
    1199          47 :                 case TYPE_bte:
    1200          47 :                         if (dtp == TYPE_bit) {
    1201          15 :                                 return convert_lng_bit(src, dst, ci,
    1202             :                                                        candoff, reduce);
    1203             :                         }
    1204          32 :                         return convert_lng_bte(src, dst, ci, candoff,
    1205             :                                                scale1,
    1206             :                                                scale2,
    1207             :                                                precision, reduce);
    1208         151 :                 case TYPE_sht:
    1209         151 :                         return convert_lng_sht(src, dst, ci, candoff,
    1210             :                                                scale1,
    1211             :                                                scale2,
    1212             :                                                precision, reduce);
    1213        2037 :                 case TYPE_int:
    1214             : #if SIZEOF_OID == SIZEOF_INT
    1215             :                         if (dtp == TYPE_oid)
    1216             :                                 return convert_lng_oid(src, dst, ci,
    1217             :                                                        candoff,
    1218             :                                                        reduce);
    1219             : #endif
    1220        2037 :                         return convert_lng_int(src, dst, ci, candoff,
    1221             :                                                scale1,
    1222             :                                                scale2,
    1223             :                                                precision, reduce);
    1224         430 :                 case TYPE_lng:
    1225             : #if SIZEOF_OID == SIZEOF_LNG
    1226         430 :                         if (dtp == TYPE_oid)
    1227          14 :                                 return convert_lng_oid(src, dst, ci,
    1228             :                                                        candoff,
    1229             :                                                        reduce);
    1230             : #endif
    1231         416 :                         return convert_lng_lng(src, dst, ci, candoff,
    1232             :                                                scale1,
    1233             :                                                scale2,
    1234             :                                                precision, reduce);
    1235             : #ifdef HAVE_HGE
    1236        1256 :                 case TYPE_hge:
    1237        1256 :                         return convert_lng_hge(src, dst, ci, candoff,
    1238             :                                                scale1,
    1239             :                                                scale2,
    1240             :                                                precision, reduce);
    1241             : #endif
    1242          38 :                 case TYPE_flt:
    1243          38 :                         return convert_lng_flt(src, dst, ci, candoff,
    1244             :                                                scale1,
    1245             :                                                reduce);
    1246        1493 :                 case TYPE_dbl:
    1247        1493 :                         return convert_lng_dbl(src, dst, ci, candoff,
    1248             :                                                scale1,
    1249             :                                                reduce);
    1250             :                 default:
    1251             :                         return BUN_NONE + 1;
    1252             :                 }
    1253             : #ifdef HAVE_HGE
    1254         840 :         case TYPE_hge:
    1255        1677 :                 switch (ATOMbasetype(dtp)) {
    1256           0 :                 case TYPE_msk:
    1257           0 :                         return convert_msk_hge(src, dst, ci, candoff,
    1258             :                                                reduce);
    1259          18 :                 case TYPE_bte:
    1260          18 :                         if (dtp == TYPE_bit) {
    1261           3 :                                 return convert_hge_bit(src, dst, ci,
    1262             :                                                        candoff, reduce);
    1263             :                         }
    1264          15 :                         return convert_hge_bte(src, dst, ci, candoff,
    1265             :                                                scale1,
    1266             :                                                scale2,
    1267             :                                                precision, reduce);
    1268          20 :                 case TYPE_sht:
    1269          20 :                         return convert_hge_sht(src, dst, ci, candoff,
    1270             :                                                scale1,
    1271             :                                                scale2,
    1272             :                                                precision, reduce);
    1273         121 :                 case TYPE_int:
    1274         121 :                         return convert_hge_int(src, dst, ci, candoff,
    1275             :                                                scale1,
    1276             :                                                scale2,
    1277             :                                                precision, reduce);
    1278         389 :                 case TYPE_lng:
    1279         389 :                         return convert_hge_lng(src, dst, ci, candoff,
    1280             :                                                scale1,
    1281             :                                                scale2,
    1282             :                                                precision, reduce);
    1283         247 :                 case TYPE_hge:
    1284         247 :                         return convert_hge_hge(src, dst, ci, candoff,
    1285             :                                                scale1,
    1286             :                                                scale2,
    1287             :                                                precision, reduce);
    1288           0 :                 case TYPE_oid:
    1289           0 :                         return convert_hge_oid(src, dst, ci, candoff, reduce);
    1290           6 :                 case TYPE_flt:
    1291           6 :                         return convert_hge_flt(src, dst, ci, candoff,
    1292             :                                                scale1,
    1293             :                                                reduce);
    1294          39 :                 case TYPE_dbl:
    1295          39 :                         return convert_hge_dbl(src, dst, ci, candoff,
    1296             :                                                scale1,
    1297             :                                                reduce);
    1298             :                 default:
    1299             :                         return BUN_NONE + 1;
    1300             :                 }
    1301             : #endif
    1302         162 :         case TYPE_flt:
    1303         321 :                 switch (ATOMbasetype(dtp)) {
    1304           0 :                 case TYPE_msk:
    1305           0 :                         return convert_msk_flt(src, dst, ci, candoff,
    1306             :                                                reduce);
    1307           5 :                 case TYPE_bte:
    1308           5 :                         if (dtp == TYPE_bit) {
    1309           3 :                                 return convert_flt_bit(src, dst, ci,
    1310             :                                                        candoff, reduce);
    1311             :                         }
    1312           2 :                         return convert_flt_bte(src, dst, ci, candoff,
    1313             :                                                scale2,
    1314             :                                                precision, reduce);
    1315           2 :                 case TYPE_sht:
    1316           2 :                         return convert_flt_sht(src, dst, ci, candoff,
    1317             :                                                scale2,
    1318             :                                                precision, reduce);
    1319           6 :                 case TYPE_int:
    1320             : #if SIZEOF_OID == SIZEOF_INT
    1321             :                         if (dtp == TYPE_oid)
    1322             :                                 return convert_flt_oid(src, dst, ci,
    1323             :                                                        candoff,
    1324             :                                                        reduce);
    1325             : #endif
    1326           6 :                         return convert_flt_int(src, dst, ci, candoff,
    1327             :                                                scale2,
    1328             :                                                precision, reduce);
    1329          22 :                 case TYPE_lng:
    1330             : #if SIZEOF_OID == SIZEOF_LNG
    1331          22 :                         if (dtp == TYPE_oid)
    1332           0 :                                 return convert_flt_oid(src, dst, ci,
    1333             :                                                        candoff,
    1334             :                                                        reduce);
    1335             : #endif
    1336          22 :                         return convert_flt_lng(src, dst, ci, candoff,
    1337             :                                                scale2,
    1338             :                                                precision, reduce);
    1339             : #ifdef HAVE_HGE
    1340           2 :                 case TYPE_hge:
    1341           2 :                         return convert_flt_hge(src, dst, ci, candoff,
    1342             :                                                scale2,
    1343             :                                                precision, reduce);
    1344             : #endif
    1345           4 :                 case TYPE_flt:
    1346           4 :                         return convert_flt_flt(src, dst, ci, candoff,
    1347             :                                                0,
    1348             :                                                reduce);
    1349         121 :                 case TYPE_dbl:
    1350         121 :                         return convert_flt_dbl(src, dst, ci, candoff,
    1351             :                                                0,
    1352             :                                                reduce);
    1353             :                 default:
    1354             :                         return BUN_NONE + 1;
    1355             :                 }
    1356         177 :         case TYPE_dbl:
    1357         347 :                 switch (ATOMbasetype(dtp)) {
    1358           0 :                 case TYPE_msk:
    1359           0 :                         return convert_msk_dbl(src, dst, ci, candoff,
    1360             :                                                reduce);
    1361          23 :                 case TYPE_bte:
    1362          23 :                         if (dtp == TYPE_bit) {
    1363           7 :                                 return convert_dbl_bit(src, dst, ci,
    1364             :                                                        candoff, reduce);
    1365             :                         }
    1366          16 :                         return convert_dbl_bte(src, dst, ci, candoff,
    1367             :                                                scale2,
    1368             :                                                precision, reduce);
    1369           6 :                 case TYPE_sht:
    1370           6 :                         return convert_dbl_sht(src, dst, ci, candoff,
    1371             :                                                scale2,
    1372             :                                                precision, reduce);
    1373          41 :                 case TYPE_int:
    1374             : #if SIZEOF_OID == SIZEOF_INT
    1375             :                         if (dtp == TYPE_oid)
    1376             :                                 return convert_dbl_oid(src, dst, ci,
    1377             :                                                        candoff,
    1378             :                                                        reduce);
    1379             : #endif
    1380          41 :                         return convert_dbl_int(src, dst, ci, candoff,
    1381             :                                                scale2,
    1382             :                                                precision, reduce);
    1383          49 :                 case TYPE_lng:
    1384             : #if SIZEOF_OID == SIZEOF_LNG
    1385          49 :                         if (dtp == TYPE_oid)
    1386           0 :                                 return convert_dbl_oid(src, dst, ci,
    1387             :                                                        candoff,
    1388             :                                                        reduce);
    1389             : #endif
    1390          49 :                         return convert_dbl_lng(src, dst, ci, candoff,
    1391             :                                                scale2,
    1392             :                                                precision, reduce);
    1393             : #ifdef HAVE_HGE
    1394          14 :                 case TYPE_hge:
    1395          14 :                         return convert_dbl_hge(src, dst, ci, candoff,
    1396             :                                                scale2,
    1397             :                                                precision, reduce);
    1398             : #endif
    1399          44 :                 case TYPE_flt:
    1400          44 :                         return convert_dbl_flt(src, dst, ci, candoff,
    1401             :                                                0, 0, reduce);
    1402           0 :                 case TYPE_dbl:
    1403           0 :                         return convert_dbl_dbl(src, dst, ci, candoff,
    1404             :                                                0,
    1405             :                                                reduce);
    1406             :                 default:
    1407             :                         return BUN_NONE + 1;
    1408             :                 }
    1409             :         default:
    1410             :                 return BUN_NONE + 1;
    1411             :         }
    1412             : }
    1413             : 
    1414             : BAT *
    1415       86867 : BATconvert(BAT *b, BAT *s, int tp,
    1416             :            uint8_t scale1, uint8_t scale2, uint8_t precision)
    1417             : {
    1418       86867 :         lng t0 = 0;
    1419       86867 :         BAT *bn;
    1420       86867 :         BUN nils = 0;   /* in case no conversion defined */
    1421       86867 :         struct canditer ci;
    1422       86867 :         BUN cnt;
    1423             :         /* set reduce to true if there are (potentially) multiple
    1424             :          * (different) source values that map to the same destination
    1425             :          * value */
    1426       86867 :         bool reduce = false;
    1427             : 
    1428       86867 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    1429             : 
    1430       86867 :         BATcheck(b, NULL);
    1431       86867 :         if (tp == TYPE_void)
    1432           0 :                 tp = TYPE_oid;
    1433             : 
    1434       86867 :         BATiter bi = bat_iterator(b);
    1435       87032 :         cnt = BATcount(b);
    1436       87032 :         canditer_init(&ci, b, s);
    1437       86887 :         if (ci.ncand == 0 || (bi.type == TYPE_void && is_oid_nil(b->tseqbase))) {
    1438       32976 :                 bat_iterator_end(&bi);
    1439       32946 :                 return BATconstant(ci.hseq, tp,
    1440             :                                    ATOMnilptr(tp), ci.ncand, TRANSIENT);
    1441             :         }
    1442             : 
    1443      105722 :         if (cnt == ci.ncand && tp != TYPE_bit &&
    1444      104911 :             ATOMbasetype(bi.type) == ATOMbasetype(tp) &&
    1445          11 :             (tp != TYPE_oid || bi.type == TYPE_oid) &&
    1446        1653 :             scale1 == 0 && scale2 == 0 && precision == 0 &&
    1447          15 :             (tp != TYPE_str ||
    1448          15 :              BATatoms[bi.type].atomToStr == BATatoms[TYPE_str].atomToStr)) {
    1449        1436 :                 bn = COLcopy(b, tp, false, TRANSIENT);
    1450        1439 :                 if (bn && s)
    1451          34 :                         bn->hseqbase = s->hseqbase;
    1452        1439 :                 bat_iterator_end(&bi);
    1453        1439 :                 return bn;
    1454             :         }
    1455       52475 :         if (ATOMstorage(tp) == TYPE_ptr) {
    1456           0 :                 GDKerror("type combination (convert(%s)->%s) "
    1457             :                          "not supported.\n",
    1458             :                          ATOMname(bi.type), ATOMname(tp));
    1459           0 :                 bat_iterator_end(&bi);
    1460           0 :                 return NULL;
    1461             :         }
    1462       52475 :         if (ATOMstorage(tp) == TYPE_msk) {
    1463           0 :                 if (BATtdensebi(&bi)) {
    1464             :                         /* dense to msk is easy: all values 1, except
    1465             :                          * maybe the first */
    1466           0 :                         bn = BATconstant(ci.hseq, tp, &(msk){1}, ci.ncand,
    1467             :                                          TRANSIENT);
    1468           0 :                         if (bn && b->tseqbase == 0)
    1469           0 :                                 mskClr(bn, 0);
    1470           0 :                         bat_iterator_end(&bi);
    1471           0 :                         return bn;
    1472           0 :                 } else if (bi.type == TYPE_void) {
    1473             :                         /* void-nil to msk is easy: all values 0 */
    1474           0 :                         bn = BATconstant(ci.hseq, tp, &(msk){0}, ci.ncand,
    1475             :                                          TRANSIENT);
    1476           0 :                         bat_iterator_end(&bi);
    1477           0 :                         return bn;
    1478             :                 }
    1479             :         }
    1480             : 
    1481       52475 :         bn = COLnew(ci.hseq, tp, ci.ncand, TRANSIENT);
    1482       52524 :         if (bn == NULL) {
    1483           0 :                 bat_iterator_end(&bi);
    1484           0 :                 return NULL;
    1485             :         }
    1486             : 
    1487       52524 :         if (bi.type == TYPE_void)
    1488           0 :                 nils = convert_void_any(b->tseqbase, bn,
    1489             :                                         &ci, b->hseqbase, &reduce);
    1490       52524 :         else if (tp == TYPE_str)
    1491         181 :                 nils = convert_any_str(&bi, bn, &ci);
    1492       52343 :         else if (bi.type == TYPE_str) {
    1493        1332 :                 reduce = true;
    1494        1332 :                 if (ATOMvarsized(tp)) {
    1495           9 :                         nils = convert_str_var(&bi, bn, &ci);
    1496             :                 } else {
    1497        1323 :                         nils = convert_str_fix(&bi, tp, Tloc(bn, 0),
    1498             :                                                &ci, b->hseqbase);
    1499             :                 }
    1500       51011 :         } else if (ATOMstorage(bi.type) == TYPE_msk &&
    1501           0 :                    ATOMstorage(tp) == TYPE_msk) {
    1502           0 :                 if (BATappend(bn, b, s, false) != GDK_SUCCEED)
    1503             :                         nils = BUN_NONE + 2;
    1504             :         } else {
    1505       51011 :                 nils = convert_typeswitchloop(bi.base, bi.type,
    1506       51011 :                                               Tloc(bn, 0), tp,
    1507             :                                               &ci, b->hseqbase, &reduce,
    1508             :                                               scale1, scale2, precision);
    1509             :         }
    1510             : 
    1511       52430 :         if (nils >= BUN_NONE) {
    1512          16 :                 BBPunfix(bn->batCacheid);
    1513          16 :                 if (nils == BUN_NONE + 1) {
    1514           0 :                         GDKerror("type combination (convert(%s)->%s) "
    1515             :                                  "not supported.\n",
    1516             :                                  ATOMname(bi.type), ATOMname(tp));
    1517          16 :                 } else if (nils == BUN_NONE + 2) {
    1518           0 :                         GDKerror("could not insert value into BAT.\n");
    1519             :                 }
    1520          16 :                 bat_iterator_end(&bi);
    1521          16 :                 return NULL;
    1522             :         }
    1523             : 
    1524       52414 :         BATsetcount(bn, ci.ncand);
    1525             : 
    1526       52462 :         bn->tnil = nils != 0;
    1527       52462 :         bn->tnonil = nils == 0;
    1528       52462 :         if ((bn->ttype != TYPE_str && bn->ttype != TYPE_bit && bi.type != TYPE_str) ||
    1529        1714 :             BATcount(bn) < 2) {
    1530       51361 :                 bn->tsorted = nils == 0 && bi.sorted;
    1531       92821 :                 bn->trevsorted = nils == 0 && bi.revsorted;
    1532             :         } else {
    1533        1101 :                 bn->tsorted = false;
    1534        1101 :                 bn->trevsorted = false;
    1535             :         }
    1536       52462 :         if (!reduce || BATcount(bn) < 2)
    1537       79664 :                 bn->tkey = bi.key && nils <= 1;
    1538             :         else
    1539        2288 :                 bn->tkey = false;
    1540             : 
    1541       52462 :         bat_iterator_end(&bi);
    1542       52504 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    1543             :                   " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
    1544             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    1545             :                   ALGOOPTBATPAR(bn), GDKusec() - t0);
    1546             : 
    1547             :         return bn;
    1548             : }
    1549             : 
    1550             : gdk_return
    1551     2255242 : VARconvert(ValPtr ret, const ValRecord *v,
    1552             :            uint8_t scale1, uint8_t scale2, uint8_t precision)
    1553             : {
    1554     2255242 :         ptr p;
    1555     2255242 :         BUN nils = 0;
    1556     2255242 :         bool reduce;
    1557             : 
    1558     2255242 :         assert(!v->bat);
    1559     2255242 :         if (ret->vtype == TYPE_msk) {
    1560           0 :                 ValRecord tmp = { .vtype = TYPE_bit };
    1561           0 :                 if (VARconvert(&tmp, v, scale1, scale2, precision) != GDK_SUCCEED)
    1562           0 :                         return GDK_FAIL;
    1563           0 :                 if (is_bte_nil(tmp.val.btval)) {
    1564           0 :                         GDKerror("22003!cannot convert nil to msk.\n");
    1565           0 :                         nils = BUN_NONE;
    1566             :                 }
    1567           0 :                 ret->val.mval = tmp.val.btval;
    1568           0 :                 ret->len = ATOMsize(TYPE_msk);
    1569     2255242 :         } else if (v->vtype == TYPE_msk) {
    1570           0 :                 ValRecord tmp = { .vtype = TYPE_bit, .val.btval = v->val.mval };
    1571           0 :                 if (VARconvert(ret, &tmp, scale1, scale2, precision) != GDK_SUCCEED)
    1572           0 :                         return GDK_FAIL;
    1573     2255242 :         } else if (ret->vtype == TYPE_str) {
    1574       34715 :                 if (v->vtype == TYPE_void ||
    1575         593 :                     (*ATOMcompare(v->vtype))(VALptr(v),
    1576             :                                              ATOMnilptr(v->vtype)) == 0) {
    1577       33625 :                         if (VALinit(ret, TYPE_str, str_nil) == NULL)
    1578             :                                 return GDK_FAIL;
    1579         497 :                 } else if (BATatoms[v->vtype].atomToStr == BATatoms[TYPE_str].atomToStr) {
    1580           2 :                         if (VALinit(ret, TYPE_str, v->val.sval) == NULL)
    1581             :                                 return GDK_FAIL;
    1582             :                 } else {
    1583         495 :                         ret->len = 0;
    1584         495 :                         ret->val.sval = NULL;
    1585         495 :                         if ((*BATatoms[v->vtype].atomToStr)(&ret->val.sval,
    1586             :                                                             &ret->len,
    1587             :                                                             VALptr(v),
    1588             :                                                             false) < 0) {
    1589           0 :                                 GDKfree(ret->val.sval);
    1590           0 :                                 ret->val.sval = NULL;
    1591           0 :                                 ret->len = 0;
    1592           0 :                                 return GDK_FAIL;
    1593             :                         }
    1594             :                 }
    1595     2221120 :         } else if (ret->vtype == TYPE_void) {
    1596           0 :                 if (ATOMcmp(v->vtype, VALptr(v), ATOMnilptr(v->vtype)) != 0) {
    1597           0 :                         GDKerror("22003!cannot convert non-nil to void.\n");
    1598           0 :                         return GDK_FAIL;
    1599             :                 }
    1600           0 :                 ret->val.oval = oid_nil;
    1601           0 :                 ret->len = ATOMsize(TYPE_void);
    1602     2221120 :         } else if (v->vtype == TYPE_void) {
    1603      247478 :                 if (VALinit(ret, ret->vtype, ATOMnilptr(ret->vtype)) == NULL)
    1604             :                         return GDK_FAIL;
    1605     1973642 :         } else if (v->vtype == TYPE_str) {
    1606        3763 :                 if (strNil(v->val.sval)) {
    1607          23 :                         if (VALinit(ret, ret->vtype, ATOMnilptr(ret->vtype)) == NULL)
    1608             :                                 return GDK_FAIL;
    1609        3740 :                 } else if (ATOMstorage(ret->vtype) == TYPE_ptr) {
    1610             :                         nils = BUN_NONE + 1;
    1611             :                 } else {
    1612        3740 :                         ssize_t l;
    1613        3740 :                         size_t len;
    1614             : 
    1615        3740 :                         if (ATOMextern(ret->vtype)) {
    1616             :                                 /* let atomFromStr allocate memory
    1617             :                                  * which we later give away to ret */
    1618           4 :                                 p = NULL;
    1619           4 :                                 len = 0;
    1620             :                         } else {
    1621             :                                 /* use the space provided by ret */
    1622        3736 :                                 p = VALget(ret);
    1623        3736 :                                 len = ATOMsize(ret->vtype);
    1624             :                         }
    1625        3740 :                         if ((l = (*BATatoms[ret->vtype].atomFromStr)(
    1626        3740 :                                      v->val.sval, &len, &p, false)) < 0 ||
    1627        3447 :                             l < (ssize_t) strlen(v->val.sval)) {
    1628         370 :                                 if (ATOMextern(ret->vtype))
    1629           0 :                                         GDKfree(p);
    1630         370 :                                 GDKclrerr();
    1631         370 :                                 size_t sz = escapedStrlen(v->val.sval, NULL, NULL, '\'');
    1632         370 :                                 char *bf = GDKmalloc(sz + 1);
    1633         370 :                                 if (bf) {
    1634         370 :                                         escapedStr(bf, v->val.sval, sz + 1, NULL, NULL, '\'');
    1635         370 :                                         GDKerror("22018!conversion of string "
    1636             :                                                  "'%s' to type %s failed.\n",
    1637             :                                                  bf, ATOMname(ret->vtype));
    1638         370 :                                         GDKfree(bf);
    1639             :                                 } else {
    1640           0 :                                         GDKerror("22018!conversion of string "
    1641             :                                                  "to type %s failed.\n",
    1642             :                                                  ATOMname(ret->vtype));
    1643             :                                 }
    1644         370 :                                 return GDK_FAIL;
    1645             :                         } else {
    1646             :                                 /* now give value obtained to ret */
    1647        3370 :                                 assert(ATOMextern(ret->vtype) ||
    1648             :                                        p == VALget(ret));
    1649        3370 :                                 ret->len = (int) len;
    1650        3370 :                                 if (ATOMextern(ret->vtype))
    1651           4 :                                         VALset(ret, ret->vtype, p);
    1652             :                         }
    1653             :                 }
    1654             :         } else {
    1655     1969919 :                 nils = convert_typeswitchloop(VALptr(v), v->vtype,
    1656             :                                               VALget(ret), ret->vtype,
    1657     1969879 :                                               &(struct canditer){.tpe=cand_dense, .ncand=1},
    1658             :                                               0, &reduce,
    1659             :                                               scale1, scale2, precision);
    1660     1969914 :                 if (nils < BUN_NONE)
    1661     1969844 :                         ret->len = ATOMlen(ret->vtype, VALptr(ret));
    1662             :         }
    1663     1973261 :         if (nils == BUN_NONE + 1) {
    1664           1 :                 GDKerror("conversion from type %s to type %s "
    1665             :                          "unsupported.\n",
    1666             :                          ATOMname(v->vtype), ATOMname(ret->vtype));
    1667           1 :                 return GDK_FAIL;
    1668             :         }
    1669     2254895 :         return nils == BUN_NONE ? GDK_FAIL : GDK_SUCCEED;
    1670             : }

Generated by: LCOV version 1.14