LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_round_impl.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 203 501 40.5 %
Date: 2021-10-13 02:24:04 Functions: 35 85 41.2 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #define dec_round_body          FUN(TYPE, dec_round_body)
      10             : #define dec_round_wrap          FUN(TYPE, dec_round_wrap)
      11             : #define bat_dec_round_wrap      FUN(TYPE, bat_dec_round_wrap)
      12             : #define bat_dec_round_wrap_cst  FUN(TYPE, bat_dec_round_wrap_cst)
      13             : #define bat_dec_round_wrap_nocst        FUN(TYPE, bat_dec_round_wrap_nocst)
      14             : #define round_body              FUN(TYPE, round_body)
      15             : #define round_wrap              FUN(TYPE, round_wrap)
      16             : #define bat_round_wrap          FUN(TYPE, bat_round_wrap)
      17             : #define bat_round_wrap_cst      FUN(TYPE, bat_round_wrap_cst)
      18             : #define bat_round_wrap_nocst    FUN(TYPE, bat_round_wrap_nocst)
      19             : #define nil_2dec                FUN(nil_2dec, TYPE)
      20             : #define str_2dec_body           FUN(str_2dec_body, TYPE)
      21             : #define str_2dec                FUN(str_2dec, TYPE)
      22             : #define batnil_2dec             FUN(batnil_2dec, TYPE)
      23             : #define batstr_2dec             FUN(batstr_2dec, TYPE)
      24             : #define dec2second_interval     FUN(TYPE, dec2second_interval)
      25             : #define batdec2second_interval  FUN(TYPE, batdec2second_interval)
      26             : 
      27             : static inline TYPE
      28          32 : dec_round_body(TYPE v, TYPE r)
      29             : {
      30          32 :         TYPE add = r >> 1;
      31             : 
      32          32 :         assert(!ISNIL(TYPE)(v));
      33             : 
      34          32 :         if (v < 0)
      35           4 :                 add = -add;
      36          32 :         v += add;
      37          32 :         return v / r;
      38             : }
      39             : 
      40             : str
      41          27 : dec_round_wrap(TYPE *res, const TYPE *v, const TYPE *r)
      42             : {
      43             :         /* basic sanity checks */
      44          27 :         assert(res && v && r);
      45             : 
      46          27 :         if (ISNIL(TYPE)(*r))
      47           0 :                 throw(MAL, "round", SQLSTATE(42000) "Argument 2 to round function cannot be null");
      48          27 :         if (*r <= 0)
      49           4 :                 throw(MAL, "round", SQLSTATE(42000) "Argument 2 to round function must be positive");
      50             : 
      51          23 :         *res = ISNIL(TYPE)(*v) ? NIL(TYPE) : dec_round_body(*v, *r);
      52          23 :         return MAL_SUCCEED;
      53             : }
      54             : 
      55             : str
      56           1 : bat_dec_round_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      57             : {
      58             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
      59             :         BUN q = 0;
      60           1 :         TYPE *restrict src, *restrict dst, x, r = *(TYPE *)getArgReference(stk, pci, 2);
      61             :         str msg = MAL_SUCCEED;
      62             :         bool nils = false;
      63           1 :         struct canditer ci1 = {0};
      64             :         oid off1;
      65           1 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
      66           1 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
      67             :         BATiter bi;
      68             : 
      69             :         (void) cntxt;
      70             :         (void) mb;
      71           1 :         if (ISNIL(TYPE)(r)) {
      72           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function cannot be null");
      73           0 :                 goto bailout;
      74             :         }
      75           1 :         if (r <= 0) {
      76           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function must be positive");
      77           0 :                 goto bailout;
      78             :         }
      79           1 :         if (!(b = BATdescriptor(*bid))) {
      80           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      81           0 :                 goto bailout;
      82             :         }
      83           1 :         if (b->ttype != TPE(TYPE)) {
      84           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 1 must have a " STRING(TYPE) " tail");
      85           0 :                 goto bailout;
      86             :         }
      87           1 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
      88           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      89           0 :                 goto bailout;
      90             :         }
      91           1 :         q = canditer_init(&ci1, b, bs);
      92           1 :         if (!(bn = COLnew(ci1.hseq, TPE(TYPE), q, TRANSIENT))) {
      93           0 :                 msg = createException(MAL, "round", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      94           0 :                 goto bailout;
      95             :         }
      96             : 
      97           1 :         off1 = b->hseqbase;
      98           1 :         bi = bat_iterator(b);
      99           1 :         src = (TYPE *) bi.base;
     100           1 :         dst = (TYPE *) Tloc(bn, 0);
     101           1 :         if (ci1.tpe == cand_dense) {
     102          10 :                 for (BUN i = 0; i < q; i++) {
     103           9 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     104           9 :                         x = src[p1];
     105             : 
     106           9 :                         if (ISNIL(TYPE)(x)) {
     107           0 :                                 dst[i] = NIL(TYPE);
     108             :                                 nils = true;
     109             :                         } else {
     110           9 :                                 dst[i] = dec_round_body(x, r);
     111             :                         }
     112             :                 }
     113             :         } else {
     114           0 :                 for (BUN i = 0; i < q; i++) {
     115           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     116           0 :                         x = src[p1];
     117             : 
     118           0 :                         if (ISNIL(TYPE)(x)) {
     119           0 :                                 dst[i] = NIL(TYPE);
     120             :                                 nils = true;
     121             :                         } else {
     122           0 :                                 dst[i] = dec_round_body(x, r);
     123             :                         }
     124             :                 }
     125             :         }
     126           1 :         bat_iterator_end(&bi);
     127           1 : bailout:
     128           1 :         finalize_ouput_copy_sorted_property(res, bn, b, msg, nils, q, true);
     129           1 :         unfix_inputs(2, b, bs);
     130           1 :         return msg;
     131             : }
     132             : 
     133             : str
     134           0 : bat_dec_round_wrap_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     135             : {
     136             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     137             :         BUN q = 0;
     138           0 :         TYPE *restrict src, *restrict dst, x = *(TYPE *)getArgReference(stk, pci, 1), r;
     139             :         str msg = MAL_SUCCEED;
     140             :         bool nils = false;
     141           0 :         struct canditer ci1 = {0};
     142             :         oid off1;
     143           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 2),
     144           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
     145             :         BATiter bi;
     146             : 
     147             :         (void) cntxt;
     148             :         (void) mb;
     149           0 :         if (!(b = BATdescriptor(*bid))) {
     150           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     151           0 :                 goto bailout;
     152             :         }
     153           0 :         if (b->ttype != TPE(TYPE)) {
     154           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 1 must have a " STRING(TYPE) " tail");
     155           0 :                 goto bailout;
     156             :         }
     157           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     158           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     159           0 :                 goto bailout;
     160             :         }
     161           0 :         q = canditer_init(&ci1, b, bs);
     162           0 :         if (!(bn = COLnew(ci1.hseq, TPE(TYPE), q, TRANSIENT))) {
     163           0 :                 msg = createException(MAL, "round", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     164           0 :                 goto bailout;
     165             :         }
     166             : 
     167           0 :         off1 = b->hseqbase;
     168           0 :         bi = bat_iterator(b);
     169           0 :         src = (TYPE *) bi.base;
     170           0 :         dst = (TYPE *) Tloc(bn, 0);
     171           0 :         if (ci1.tpe == cand_dense) {
     172           0 :                 for (BUN i = 0; i < q; i++) {
     173           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     174           0 :                         r = src[p1];
     175             : 
     176           0 :                         if (ISNIL(TYPE)(r)) {
     177           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function cannot be null");
     178           0 :                                 goto bailout1;
     179           0 :                         } else if (r <= 0) {
     180           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function must be positive");
     181           0 :                                 goto bailout1;
     182           0 :                         } else if (ISNIL(TYPE)(x)) {
     183           0 :                                 dst[i] = NIL(TYPE);
     184             :                                 nils = true;
     185             :                         } else {
     186           0 :                                 dst[i] = dec_round_body(x, r);
     187             :                         }
     188             :                 }
     189             :         } else {
     190           0 :                 for (BUN i = 0; i < q; i++) {
     191           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     192           0 :                         r = src[p1];
     193             : 
     194           0 :                         if (ISNIL(TYPE)(r)) {
     195           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function cannot be null");
     196           0 :                                 goto bailout1;
     197           0 :                         } else if (r <= 0) {
     198           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function must be positive");
     199           0 :                                 goto bailout1;
     200           0 :                         } else if (ISNIL(TYPE)(x)) {
     201           0 :                                 dst[i] = NIL(TYPE);
     202             :                                 nils = true;
     203             :                         } else {
     204           0 :                                 dst[i] = dec_round_body(x, r);
     205             :                         }
     206             :                 }
     207             :         }
     208           0 : bailout1:
     209           0 :         bat_iterator_end(&bi);
     210             : 
     211           0 : bailout:
     212           0 :         finalize_ouput_copy_sorted_property(res, bn, b, msg, nils, q, false);
     213           0 :         unfix_inputs(2, b, bs);
     214           0 :         return msg;
     215             : }
     216             : 
     217             : str
     218           0 : bat_dec_round_wrap_nocst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     219             : {
     220             :         BAT *bn = NULL, *left = NULL, *lefts = NULL, *right = NULL, *rights = NULL;
     221             :         BUN q = 0;
     222             :         TYPE *src1, *src2, *restrict dst, x, rr;
     223             :         str msg = MAL_SUCCEED;
     224             :         bool nils = false;
     225           0 :         struct canditer ci1 = {0}, ci2 = {0};
     226             :         oid off1, off2;
     227           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
     228           0 :                 *r = getArgReference_bat(stk, pci, 2),
     229           0 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 3) : NULL,
     230           0 :                 *sid2 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
     231             :         BATiter lefti, righti;
     232             : 
     233             :         (void) cntxt;
     234             :         (void) mb;
     235           0 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*r))) {
     236           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     237           0 :                 goto bailout;
     238             :         }
     239           0 :         if (left->ttype != TPE(TYPE) || right->ttype != TPE(TYPE)) {
     240           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Arguments must have a " STRING(TYPE) " tail");
     241           0 :                 goto bailout;
     242             :         }
     243           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(lefts = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(rights = BATdescriptor(*sid2)))) {
     244           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     245           0 :                 goto bailout;
     246             :         }
     247           0 :         q = canditer_init(&ci1, left, lefts);
     248           0 :         if (canditer_init(&ci2, right, rights) != q || ci1.hseq != ci2.hseq) {
     249           0 :                 msg = createException(MAL, "round", ILLEGAL_ARGUMENT " Requires bats of identical size");
     250           0 :                 goto bailout;
     251             :         }
     252           0 :         if (!(bn = COLnew(ci1.hseq, TPE(TYPE), q, TRANSIENT))) {
     253           0 :                 msg = createException(MAL, "round", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     254           0 :                 goto bailout;
     255             :         }
     256             : 
     257           0 :         off1 = left->hseqbase;
     258           0 :         off2 = right->hseqbase;
     259           0 :         lefti = bat_iterator(left);
     260           0 :         righti = bat_iterator(right);
     261           0 :         src1 = (TYPE *) lefti.base;
     262           0 :         src2 = (TYPE *) righti.base;
     263           0 :         dst = (TYPE *) Tloc(bn, 0);
     264           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
     265           0 :                 for (BUN i = 0; i < q; i++) {
     266           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
     267           0 :                         x = src1[p1];
     268           0 :                         rr = src2[p2];
     269             : 
     270           0 :                         if (ISNIL(TYPE)(rr)) {
     271           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function cannot be null");
     272           0 :                                 goto bailout1;
     273           0 :                         } else if (rr <= 0) {
     274           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function must be positive");
     275           0 :                                 goto bailout1;
     276           0 :                         } else if (ISNIL(TYPE)(x)) {
     277           0 :                                 dst[i] = NIL(TYPE);
     278             :                                 nils = true;
     279             :                         } else {
     280           0 :                                 dst[i] = dec_round_body(x, rr);
     281             :                         }
     282             :                 }
     283             :         } else {
     284           0 :                 for (BUN i = 0; i < q; i++) {
     285           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
     286           0 :                         x = src1[p1];
     287           0 :                         rr = src2[p2];
     288             : 
     289           0 :                         if (ISNIL(TYPE)(rr)) {
     290           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function cannot be null");
     291           0 :                                 goto bailout1;
     292           0 :                         } else if (rr <= 0) {
     293           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function must be positive");
     294           0 :                                 goto bailout1;
     295           0 :                         } else if (ISNIL(TYPE)(x)) {
     296           0 :                                 dst[i] = NIL(TYPE);
     297             :                                 nils = true;
     298             :                         } else {
     299           0 :                                 dst[i] = dec_round_body(x, rr);
     300             :                         }
     301             :                 }
     302             :         }
     303           0 : bailout1:
     304           0 :         bat_iterator_end(&lefti);
     305           0 :         bat_iterator_end(&righti);
     306             : 
     307           0 : bailout:
     308           0 :         finalize_ouput_copy_sorted_property(res, bn, left, msg, nils, q, false);
     309           0 :         unfix_inputs(4, left, lefts, right, rights);
     310           0 :         return msg;
     311             : }
     312             : 
     313             : static inline TYPE
     314       18673 : round_body(TYPE v, int d, int s, int r)
     315             : {
     316             :         TYPE res = NIL(TYPE);
     317             : 
     318       18673 :         assert(!ISNIL(TYPE)(v));
     319             : 
     320       18673 :         if (r > 0 && r < s) {
     321       17816 :                 int dff = s - r;
     322       17816 :                 BIG rnd = scales[dff] >> 1;
     323             :                 BIG lres;
     324       17816 :                 if (v > 0)
     325       17816 :                         lres = ((v + rnd) / scales[dff]) * scales[dff];
     326             :                 else
     327           0 :                         lres = ((v - rnd) / scales[dff]) * scales[dff];
     328           6 :                 res = (TYPE) lres;
     329         857 :         } else if (r <= 0 && -r > -s) {
     330          25 :                 int dff = -r + s;
     331          25 :                 if (dff > d) {
     332             :                         res = 0;
     333             :                 } else {
     334          21 :                         BIG rnd = scales[dff] >> 1;
     335             :                         BIG lres;
     336          21 :                         if (v > 0)
     337          13 :                                 lres = ((v + rnd) / scales[dff]) * scales[dff];
     338             :                         else
     339           8 :                                 lres = ((v - rnd) / scales[dff]) * scales[dff];
     340          11 :                         res = (TYPE) lres;
     341             :                 }
     342             :         } else {
     343             :                 res = v;
     344             :         }
     345       18673 :         return res;
     346             : }
     347             : 
     348             : str
     349          16 : round_wrap(TYPE *res, const TYPE *v, const bte *r, const int *d, const int *s)
     350             : {
     351             :         /* basic sanity checks */
     352          16 :         assert(res && v && r && d && s);
     353             : 
     354          16 :         *res = (ISNIL(TYPE)(*v) || is_bte_nil(*r)) ? NIL(TYPE) : round_body(*v, *d, *s, *r);
     355          16 :         return MAL_SUCCEED;
     356             : }
     357             : 
     358             : str
     359          26 : bat_round_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     360             : {
     361             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     362             :         BUN q = 0;
     363             :         TYPE *restrict src, *restrict dst, x;
     364          26 :         bte r = *getArgReference_bte(stk, pci, 2);
     365          78 :         int d = *getArgReference_int(stk, pci, pci->argc == 6 ? 4 : 3), s = *getArgReference_int(stk, pci, pci->argc == 6 ? 5 : 4);
     366             :         str msg = MAL_SUCCEED;
     367             :         bool nils = false;
     368          26 :         struct canditer ci1 = {0};
     369             :         oid off1;
     370          26 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
     371          26 :                 *sid1 = pci->argc == 6 ? getArgReference_bat(stk, pci, 3) : NULL;
     372             :         BATiter bi;
     373             : 
     374             :         (void) cntxt;
     375             :         (void) mb;
     376          26 :         if (!(b = BATdescriptor(*bid))) {
     377           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     378           0 :                 goto bailout;
     379             :         }
     380          26 :         if (b->ttype != TPE(TYPE)) {
     381           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 1 must have a " STRING(TYPE) " tail");
     382           0 :                 goto bailout;
     383             :         }
     384          26 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     385           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     386           0 :                 goto bailout;
     387             :         }
     388          26 :         q = canditer_init(&ci1, b, bs);
     389          26 :         if (!(bn = COLnew(ci1.hseq, TPE(TYPE), q, TRANSIENT))) {
     390           0 :                 msg = createException(MAL, "round", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     391           0 :                 goto bailout;
     392             :         }
     393             : 
     394          26 :         off1 = b->hseqbase;
     395          26 :         bi = bat_iterator(b);
     396          26 :         src = (TYPE *) bi.base;
     397          26 :         dst = (TYPE *) Tloc(bn, 0);
     398          26 :         if (ci1.tpe == cand_dense) {
     399       18680 :                 for (BUN i = 0; i < q; i++) {
     400       18654 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     401       18654 :                         x = src[p1];
     402             : 
     403       18654 :                         if (ISNIL(TYPE)(x) || is_bte_nil(r)) {
     404           4 :                                 dst[i] = NIL(TYPE);
     405             :                                 nils = true;
     406             :                         } else {
     407       18650 :                                 dst[i] = round_body(x, d, s, r);
     408             :                         }
     409             :                 }
     410             :         } else {
     411           0 :                 for (BUN i = 0; i < q; i++) {
     412           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     413           0 :                         x = src[p1];
     414             : 
     415           0 :                         if (ISNIL(TYPE)(x) || is_bte_nil(r)) {
     416           0 :                                 dst[i] = NIL(TYPE);
     417             :                                 nils = true;
     418             :                         } else {
     419           0 :                                 dst[i] = round_body(x, d, s, r);
     420             :                         }
     421             :                 }
     422             :         }
     423          26 :         bat_iterator_end(&bi);
     424             : 
     425          26 : bailout:
     426          26 :         finalize_ouput_copy_sorted_property(res, bn, b, msg, nils, q, true);
     427          26 :         unfix_inputs(2, b, bs);
     428          26 :         return msg;
     429             : }
     430             : 
     431             : str
     432           1 : bat_round_wrap_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     433             : {
     434             :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     435             :         BUN q = 0;
     436           1 :         TYPE *restrict dst, x = *(TYPE *)getArgReference(stk, pci, 1);
     437             :         bte *restrict src, r;
     438           1 :         int d = *getArgReference_int(stk, pci, pci->argc == 6 ? 4 : 3), s = *getArgReference_int(stk, pci, pci->argc == 6 ? 5 : 4);
     439             :         str msg = MAL_SUCCEED;
     440             :         bool nils = false;
     441           1 :         struct canditer ci1 = {0};
     442             :         oid off1;
     443           1 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 2),
     444           1 :                 *sid1 = pci->argc == 6 ? getArgReference_bat(stk, pci, 3) : NULL;
     445             :         BATiter bi;
     446             : 
     447             :         (void) cntxt;
     448             :         (void) mb;
     449           1 :         if (!(b = BATdescriptor(*bid))) {
     450           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     451           0 :                 goto bailout;
     452             :         }
     453           1 :         if (b->ttype != TYPE_bte) {
     454           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 must have a bte tail");
     455           0 :                 goto bailout;
     456             :         }
     457           1 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     458           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     459           0 :                 goto bailout;
     460             :         }
     461           1 :         q = canditer_init(&ci1, b, bs);
     462           1 :         if (!(bn = COLnew(ci1.hseq, TPE(TYPE), q, TRANSIENT))) {
     463           0 :                 msg = createException(MAL, "round", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     464           0 :                 goto bailout;
     465             :         }
     466             : 
     467           1 :         off1 = b->hseqbase;
     468           1 :         bi = bat_iterator(b);
     469           1 :         src = (bte *) bi.base;
     470           1 :         dst = (TYPE *) Tloc(bn, 0);
     471           1 :         if (ci1.tpe == cand_dense) {
     472           7 :                 for (BUN i = 0; i < q; i++) {
     473           6 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     474           6 :                         r = src[p1];
     475             : 
     476           6 :                         if (ISNIL(TYPE)(x) || is_bte_nil(r)) {
     477           0 :                                 dst[i] = NIL(TYPE);
     478             :                                 nils = true;
     479             :                         } else {
     480           6 :                                 dst[i] = round_body(x, d, s, r);
     481             :                         }
     482             :                 }
     483             :         } else {
     484           0 :                 for (BUN i = 0; i < q; i++) {
     485           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     486           0 :                         r = src[p1];
     487             : 
     488           0 :                         if (ISNIL(TYPE)(x) || is_bte_nil(r)) {
     489           0 :                                 dst[i] = NIL(TYPE);
     490             :                                 nils = true;
     491             :                         } else {
     492           0 :                                 dst[i] = round_body(x, d, s, r);
     493             :                         }
     494             :                 }
     495             :         }
     496           1 :         bat_iterator_end(&bi);
     497             : 
     498           1 : bailout:
     499           1 :         finalize_ouput_copy_sorted_property(res, bn, b, msg, nils, q, false);
     500           1 :         unfix_inputs(2, b, bs);
     501           1 :         return msg;
     502             : }
     503             : 
     504             : str
     505           1 : bat_round_wrap_nocst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     506             : {
     507             :         BAT *bn = NULL, *left = NULL, *lefts = NULL, *right = NULL, *rights = NULL;
     508             :         BUN q = 0;
     509             :         TYPE *restrict dst, *src1, x;
     510             :         bte *src2, rr;
     511           3 :         int d = *getArgReference_int(stk, pci, pci->argc == 7 ? 5 : 3), s = *getArgReference_int(stk, pci, pci->argc == 7 ? 6 : 4);
     512             :         str msg = MAL_SUCCEED;
     513             :         bool nils = false;
     514           1 :         struct canditer ci1 = {0}, ci2 = {0};
     515             :         oid off1, off2;
     516           1 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
     517           1 :                 *r = getArgReference_bat(stk, pci, 2),
     518           1 :                 *sid1 = pci->argc == 7 ? getArgReference_bat(stk, pci, 3) : NULL,
     519           1 :                 *sid2 = pci->argc == 7 ? getArgReference_bat(stk, pci, 4) : NULL;
     520             :         BATiter lefti, righti;
     521             : 
     522             :         (void) cntxt;
     523             :         (void) mb;
     524           1 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*r))) {
     525           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     526           0 :                 goto bailout;
     527             :         }
     528           1 :         if (left->ttype != TPE(TYPE)) {
     529           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 1 must have a " STRING(TYPE) " tail");
     530           0 :                 goto bailout;
     531             :         }
     532           1 :         if (right->ttype != TYPE_bte) {
     533           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 must have a bte tail");
     534           0 :                 goto bailout;
     535             :         }
     536           1 :         if ((sid1 && !is_bat_nil(*sid1) && !(lefts = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(rights = BATdescriptor(*sid2)))) {
     537           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     538           0 :                 goto bailout;
     539             :         }
     540           1 :         q = canditer_init(&ci1, left, lefts);
     541           1 :         if (canditer_init(&ci2, right, rights) != q || ci1.hseq != ci2.hseq) {
     542           0 :                 msg = createException(MAL, "round", ILLEGAL_ARGUMENT " Requires bats of identical size");
     543           0 :                 goto bailout;
     544             :         }
     545           1 :         if (!(bn = COLnew(ci1.hseq, TPE(TYPE), q, TRANSIENT))) {
     546           0 :                 msg = createException(MAL, "round", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     547           0 :                 goto bailout;
     548             :         }
     549             : 
     550           1 :         off1 = left->hseqbase;
     551           1 :         off2 = right->hseqbase;
     552           1 :         lefti = bat_iterator(left);
     553           1 :         righti = bat_iterator(right);
     554           1 :         src1 = (TYPE *) lefti.base;
     555           1 :         src2 = (bte *) righti.base;
     556           1 :         dst = (TYPE *) Tloc(bn, 0);
     557           1 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
     558           2 :                 for (BUN i = 0; i < q; i++) {
     559           1 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
     560           1 :                         x = src1[p1];
     561           1 :                         rr = src2[p2];
     562             : 
     563           1 :                         if (ISNIL(TYPE)(x) || is_bte_nil(rr)) {
     564           0 :                                 dst[i] = NIL(TYPE);
     565             :                                 nils = true;
     566             :                         } else {
     567           1 :                                 dst[i] = round_body(x, d, s, rr);
     568             :                         }
     569             :                 }
     570             :         } else {
     571           0 :                 for (BUN i = 0; i < q; i++) {
     572           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
     573           0 :                         x = src1[p1];
     574           0 :                         rr = src2[p2];
     575             : 
     576           0 :                         if (ISNIL(TYPE)(x) || is_bte_nil(rr)) {
     577           0 :                                 dst[i] = NIL(TYPE);
     578             :                                 nils = true;
     579             :                         } else {
     580           0 :                                 dst[i] = round_body(x, d, s, rr);
     581             :                         }
     582             :                 }
     583             :         }
     584           1 :         bat_iterator_end(&lefti);
     585           1 :         bat_iterator_end(&righti);
     586             : 
     587           1 : bailout:
     588           1 :         finalize_ouput_copy_sorted_property(res, bn, left, msg, nils, q, false);
     589           1 :         unfix_inputs(4, left, lefts, right, rights);
     590           1 :         return msg;
     591             : }
     592             : 
     593             : str
     594           0 : nil_2dec(TYPE *res, const void *val, const int *d, const int *sc)
     595             : {
     596             :         (void) val;
     597             :         (void) d;
     598             :         (void) sc;
     599             : 
     600           0 :         *res = NIL(TYPE);
     601           0 :         return MAL_SUCCEED;
     602             : }
     603             : 
     604             : static inline str
     605         676 : str_2dec_body(TYPE *res, const str val, const int d, const int sc)
     606             : {
     607             :         char *s = val;
     608             :         int digits;
     609             :         int scale;
     610             :         BIG value;
     611             : 
     612         676 :         if (d < 0 || d >= (int) (sizeof(scales) / sizeof(scales[0])))
     613           0 :                 throw(SQL, STRING(TYPE), SQLSTATE(42000) "Decimal (%s) doesn't have format (%d.%d)", s, d, sc);
     614             : 
     615             :         int has_errors;
     616             :         value = 0;
     617             : 
     618             :         // s = strip_extra_zeros(s);
     619             : 
     620         676 :         value = decimal_from_str(s, &digits, &scale, &has_errors);
     621         676 :         if (has_errors)
     622          77 :                 throw(SQL, STRING(TYPE), SQLSTATE(42000) "Decimal (%s) doesn't have format (%d.%d)", s, d, sc);
     623             : 
     624             :         // handle situations where the de facto scale is different from the formal scale.
     625         599 :         if (scale < sc) {
     626             :                 /* the current scale is too small, increase it by adding 0's */
     627         415 :                 int dff = sc - scale;   /* CANNOT be 0! */
     628         415 :                 if (dff >= MAX_SCALE)
     629           0 :                         throw(SQL, STRING(TYPE), SQLSTATE(42000) "Rounding of decimal (%s) doesn't fit format (%d.%d)", s, d, sc);
     630             : 
     631         415 :                 value *= scales[dff];
     632         415 :                 scale += dff;
     633         415 :                 digits += dff;
     634         184 :         } else if (scale > sc) {
     635             :                 /* the current scale is too big, decrease it by correctly rounding */
     636             :                 /* we should round properly, and check for overflow (res >= 10^digits+scale) */
     637         120 :                 int dff = scale - sc;   /* CANNOT be 0 */
     638             : 
     639         120 :                 if (dff >= MAX_SCALE)
     640           0 :                         throw(SQL, STRING(TYPE), SQLSTATE(42000) "Rounding of decimal (%s) doesn't fit format (%d.%d)", s, d, sc);
     641             : 
     642         120 :                 BIG rnd = scales[dff] >> 1;
     643             : 
     644         120 :                 if (value > 0)
     645          83 :                         value += rnd;
     646             :                 else
     647          37 :                         value -= rnd;
     648         120 :                 value /= scales[dff];
     649         120 :                 scale -= dff;
     650         120 :                 digits -= dff;
     651         120 :                 if (value >= scales[d] || value <= -scales[d])
     652          14 :                         throw(SQL, STRING(TYPE), SQLSTATE(42000) "Rounding of decimal (%s) doesn't fit format (%d.%d)", s, d, sc);
     653             :         }
     654         585 :         if (value <= -scales[d] || value >= scales[d])
     655           2 :                 throw(SQL, STRING(TYPE), SQLSTATE(42000) "Decimal (%s) doesn't have format (%d.%d)", s, d, sc);
     656         583 :         *res = (TYPE) value;
     657         583 :         return MAL_SUCCEED;
     658             : }
     659             : 
     660             : str
     661         581 : str_2dec(TYPE *res, const str *val, const int *d, const int *sc)
     662             : {
     663         581 :         str v = *val;
     664             : 
     665         581 :         if (strNil(v)) {
     666           0 :                 *res = NIL(TYPE);
     667           0 :                 return MAL_SUCCEED;
     668             :         } else {
     669         581 :                 return str_2dec_body(res, v, *d, *sc);
     670             :         }
     671             : }
     672             : 
     673             : str
     674           0 : batnil_2dec(bat *res, const bat *bid, const int *d, const int *sc)
     675             : {
     676             :         BAT *b, *dst;
     677             :         BUN p, q;
     678             : 
     679             :         (void) d;
     680             :         (void) sc;
     681           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     682           0 :                 throw(SQL, "batcalc.nil_2dec_" STRING(TYPE), SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     683             :         }
     684           0 :         dst = COLnew(b->hseqbase, TPE(TYPE), BATcount(b), TRANSIENT);
     685           0 :         if (dst == NULL) {
     686           0 :                 BBPunfix(b->batCacheid);
     687           0 :                 throw(SQL, "sql.dec_" STRING(TYPE), SQLSTATE(HY013) MAL_MALLOC_FAIL);
     688             :         }
     689           0 :         const TYPE r = NIL(TYPE);
     690           0 :         BATloop(b, p, q) {
     691           0 :                 if (BUNappend(dst, &r, false) != GDK_SUCCEED) {
     692           0 :                         BBPunfix(b->batCacheid);
     693           0 :                         BBPreclaim(dst);
     694           0 :                         throw(SQL, "sql.dec_" STRING(TYPE), SQLSTATE(HY013) MAL_MALLOC_FAIL);
     695             :                 }
     696             :         }
     697           0 :         BBPkeepref(*res = dst->batCacheid);
     698           0 :         BBPunfix(b->batCacheid);
     699           0 :         return MAL_SUCCEED;
     700             : }
     701             : 
     702             : str
     703          46 : batstr_2dec(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     704             : {
     705             :         str msg = MAL_SUCCEED;
     706          46 :         int d = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2), sk = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3);
     707             :         BAT *b = NULL, *s = NULL, *res = NULL;
     708          46 :         bat *r = getArgReference_bat(stk, pci, 0), *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2) : NULL;
     709             :         BUN q = 0;
     710             :         BATiter bi;
     711             :         oid off;
     712          46 :         struct canditer ci = {0};
     713             :         TYPE *restrict ret;
     714             :         bool nils = false;
     715             : 
     716             :         (void) cntxt;
     717             :         (void) mb;
     718          46 :         if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     719           0 :                 msg = createException(SQL, "sql.dec_" STRING(TYPE), SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     720           0 :                 goto bailout;
     721             :         }
     722          46 :         bi = bat_iterator(b);
     723          46 :         if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     724           0 :                 msg = createException(SQL, "sql.dec_" STRING(TYPE), SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     725           0 :                 goto bailout1;
     726             :         }
     727          46 :         off = b->hseqbase;
     728          46 :         q = canditer_init(&ci, b, s);
     729          46 :         if (!(res = COLnew(ci.hseq, TPE(TYPE), q, TRANSIENT))) {
     730           0 :                 msg = createException(SQL, "sql.dec_" STRING(TYPE), SQLSTATE(HY013) MAL_MALLOC_FAIL);
     731           0 :                 goto bailout1;
     732             :         }
     733          46 :         ret = (TYPE*) Tloc(res, 0);
     734             : 
     735          46 :         if (ci.tpe == cand_dense) {
     736         140 :                 for (BUN i = 0; i < q; i++) {
     737          95 :                         oid p = (canditer_next_dense(&ci) - off);
     738          95 :                         const str next = BUNtail(bi, p);
     739             : 
     740          95 :                         if (strNil(next)) {
     741           0 :                                 ret[i] = NIL(TYPE);
     742             :                                 nils = true;
     743          95 :                         } else if ((msg = str_2dec_body(&(ret[i]), next, d, sk)))
     744           1 :                                 goto bailout1;
     745             :                 }
     746             :         } else {
     747           0 :                 for (BUN i = 0; i < q; i++) {
     748           0 :                         oid p = (canditer_next(&ci) - off);
     749           0 :                         const str next = BUNtail(bi, p);
     750             : 
     751           0 :                         if (strNil(next)) {
     752           0 :                                 ret[i] = NIL(TYPE);
     753             :                                 nils = true;
     754           0 :                         } else if ((msg = str_2dec_body(&(ret[i]), next, d, sk)))
     755           0 :                                 goto bailout1;
     756             :                 }
     757             :         }
     758           0 : bailout1:
     759          46 :         bat_iterator_end(&bi);
     760             : 
     761          46 : bailout:
     762          46 :         finalize_ouput_copy_sorted_property(r, res, b, msg, nils, q, false);
     763          46 :         unfix_inputs(2, b, s);
     764          46 :         return msg;
     765             : }
     766             : 
     767             : str
     768           0 : dec2second_interval(lng *res, const int *sc, const TYPE *dec, const int *ek, const int *sk)
     769             : {
     770           0 :         BIG value = *dec;
     771           0 :         int scale = *sc;
     772             : 
     773           0 :         if (scale < 0 || (size_t) scale >= sizeof(scales) / sizeof(scales[0]))
     774           0 :                 throw(SQL, "calc.dec2second_interval", SQLSTATE(42000) "Digits out of bounds");
     775             : 
     776             :         (void) ek;
     777             :         (void) sk;
     778           0 :         if (ISNIL(TYPE)(*dec)) {
     779           0 :                 value = lng_nil;
     780           0 :         } else if (scale < 3) {
     781           0 :                 int d = 3 - scale;
     782           0 :                 value *= scales[d];
     783           0 :         } else if (scale > 3) {
     784           0 :                 int d = scale - 3;
     785           0 :                 lng rnd = scales[d] >> 1;
     786             : 
     787           0 :                 value += rnd;
     788           0 :                 value /= scales[d];
     789             :         }
     790           0 :         *res = value;
     791           0 :         return MAL_SUCCEED;
     792             : }
     793             : 
     794             : str
     795           0 : batdec2second_interval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     796             : {
     797             :         str msg = MAL_SUCCEED;
     798           0 :         int sc = *getArgReference_int(stk, pci, 1);
     799             :         BAT *b = NULL, *s = NULL, *res = NULL;
     800           0 :         bat *r = getArgReference_bat(stk, pci, 0), *sid = pci->argc == 6 ? getArgReference_bat(stk, pci, 3) : NULL;
     801             :         BUN q = 0;
     802             :         oid off;
     803           0 :         struct canditer ci = {0};
     804             :         TYPE *restrict src;
     805             :         BIG *restrict ret, multiplier = 1, divider = 1, offset = 0;
     806             :         bool nils = false;
     807             :         BATiter bi;
     808             : 
     809             :         (void) cntxt;
     810             :         (void) mb;
     811           0 :         if (sc < 0 || (size_t) sc >= sizeof(scales) / sizeof(scales[0])) {
     812           0 :                 msg = createException(SQL, "batcalc.batdec2second_interval", SQLSTATE(42000) "Digits out of bounds");
     813           0 :                 goto bailout;
     814             :         }
     815           0 :         if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
     816           0 :                 msg = createException(SQL, "batcalc.batdec2second_interval", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     817           0 :                 goto bailout;
     818             :         }
     819           0 :         if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     820           0 :                 msg = createException(SQL, "batcalc.batdec2second_interval", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     821           0 :                 goto bailout;
     822             :         }
     823           0 :         off = b->hseqbase;
     824           0 :         q = canditer_init(&ci, b, s);
     825           0 :         if (!(res = COLnew(ci.hseq, TYPE_lng, q, TRANSIENT))) {
     826           0 :                 msg = createException(SQL, "batcalc.batdec2second_interval", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     827           0 :                 goto bailout;
     828             :         }
     829           0 :         bi = bat_iterator(b);
     830           0 :         src = bi.base;
     831           0 :         ret = Tloc(res, 0);
     832             : 
     833           0 :         if (sc < 3) {
     834           0 :                 int d = 3 - sc;
     835           0 :                 multiplier = scales[d];
     836           0 :         } else if (sc > 3) {
     837           0 :                 int d = sc - 3;
     838           0 :                 lng rnd = scales[d] >> 1;
     839             : 
     840           0 :                 offset = rnd;
     841           0 :                 divider = scales[d];
     842             :         }
     843             : 
     844             :         /* the cast from decimal to interval is now deactivated. So adding the canditer_next_dense case is not worth */
     845           0 :         if (sc < 3) {
     846           0 :                 for (BUN i = 0 ; i < q ; i++) {
     847           0 :                         oid p = (canditer_next(&ci) - off);
     848           0 :                         if (ISNIL(TYPE)(src[p])) {
     849           0 :                                 ret[i] = lng_nil;
     850             :                                 nils = true;
     851             :                         } else {
     852           0 :                                 BIG next = (BIG) src[p];
     853           0 :                                 next *= multiplier;
     854           0 :                                 ret[i] = next;
     855             :                         }
     856             :                 }
     857           0 :         } else if (sc > 3) {
     858           0 :                 for (BUN i = 0 ; i < q ; i++) {
     859           0 :                         oid p = (canditer_next(&ci) - off);
     860           0 :                         if (ISNIL(TYPE)(src[p])) {
     861           0 :                                 ret[i] = lng_nil;
     862             :                                 nils = true;
     863             :                         } else {
     864           0 :                                 BIG next = (BIG) src[p];
     865           0 :                                 next += offset;
     866           0 :                                 next /= divider;
     867           0 :                                 ret[i] = next;
     868             :                         }
     869             :                 }
     870             :         } else {
     871           0 :                 for (BUN i = 0 ; i < q ; i++) {
     872           0 :                         oid p = (canditer_next(&ci) - off);
     873           0 :                         if (ISNIL(TYPE)(src[p])) {
     874           0 :                                 ret[i] = lng_nil;
     875             :                                 nils = true;
     876             :                         } else {
     877           0 :                                 ret[i] = (BIG) src[p];
     878             :                         }
     879             :                 }
     880             :         }
     881           0 :         bat_iterator_end(&bi);
     882             : 
     883           0 : bailout:
     884           0 :         finalize_ouput_copy_sorted_property(r, res, b, msg, nils, q, false);
     885           0 :         unfix_inputs(2, b, s);
     886           0 :         return msg;
     887             : }
     888             : 
     889             : #undef dec_round_body
     890             : #undef dec_round_wrap
     891             : #undef bat_dec_round_wrap
     892             : #undef bat_dec_round_wrap_cst
     893             : #undef bat_dec_round_wrap_nocst
     894             : #undef round_body
     895             : #undef round_wrap
     896             : #undef bat_round_wrap
     897             : #undef bat_round_wrap_cst
     898             : #undef bat_round_wrap_nocst
     899             : #undef nil_2dec
     900             : #undef str_2dec_body
     901             : #undef str_2dec
     902             : #undef batnil_2dec
     903             : #undef batstr_2dec
     904             : #undef dec2second_interval
     905             : #undef batdec2second_interval

Generated by: LCOV version 1.14