LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_fround_impl.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 66 480 13.8 %
Date: 2024-10-04 20:04:04 Functions: 6 22 27.3 %

          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             : #define dec_round_body          FUN(TYPE, dec_round_body)
      14             : #define dec_round_wrap          FUN(TYPE, dec_round_wrap)
      15             : #define bat_dec_round_wrap      FUN(TYPE, bat_dec_round_wrap)
      16             : #define bat_dec_round_wrap_cst  FUN(TYPE, bat_dec_round_wrap_cst)
      17             : #define bat_dec_round_wrap_nocst        FUN(TYPE, bat_dec_round_wrap_nocst)
      18             : #define round_body              FUN(TYPE, round_body)
      19             : #define round_wrap              FUN(TYPE, round_wrap)
      20             : #define bat_round_wrap          FUN(TYPE, bat_round_wrap)
      21             : #define bat_round_wrap_cst      FUN(TYPE, bat_round_wrap_cst)
      22             : #define bat_round_wrap_nocst    FUN(TYPE, bat_round_wrap_nocst)
      23             : #define trunc_wrap              FUN(TYPE, trunc_wrap)
      24             : 
      25             : static inline TYPE
      26           0 : dec_round_body(TYPE v, TYPE r)
      27             : {
      28           0 :         assert(!ISNIL(TYPE)(v));
      29             : 
      30           0 :         return v / r;
      31             : }
      32             : 
      33             : str
      34           0 : dec_round_wrap(TYPE *res, const TYPE *v, const TYPE *r)
      35             : {
      36             :         /* basic sanity checks */
      37           0 :         assert(res && v);
      38           0 :         TYPE rr = *r;
      39             : 
      40           0 :         if (ISNIL(TYPE)(rr))
      41           0 :                 throw(MAL, "round", SQLSTATE(42000) "Argument 2 to round function cannot be null");
      42           0 :         if (rr <= 0)
      43           0 :                 throw(MAL, "round", SQLSTATE(42000) "Argument 2 to round function must be positive");
      44           0 :         *res = ISNIL(TYPE)(*v) ? NIL(TYPE) : dec_round_body(*v, rr);
      45           0 :         if (isinf(*res))
      46           0 :                 throw(MAL, "round", SQLSTATE(22003) "Overflow in round");
      47             :         return MAL_SUCCEED;
      48             : }
      49             : 
      50             : str
      51           0 : bat_dec_round_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      52             : {
      53           0 :         BAT *bn = NULL, *b = NULL, *bs = NULL;
      54           0 :         TYPE *restrict src, *restrict dst, x, r = *(TYPE *)getArgReference(stk, pci, 2);
      55           0 :         str msg = MAL_SUCCEED;
      56           0 :         bool nils = false, btsorted = false, btrevsorted = false;
      57           0 :         struct canditer ci1 = {0};
      58           0 :         oid off1;
      59           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
      60           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
      61           0 :         BATiter bi;
      62             : 
      63           0 :         (void) cntxt;
      64           0 :         (void) mb;
      65           0 :         if (ISNIL(TYPE)(r)) {
      66           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function cannot be null");
      67           0 :                 goto bailout;
      68             :         }
      69           0 :         if (r <= 0) {
      70           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function must be positive");
      71           0 :                 goto bailout;
      72             :         }
      73           0 :         if (!(b = BATdescriptor(*bid))) {
      74           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      75           0 :                 goto bailout;
      76             :         }
      77           0 :         if (b->ttype != TPE(TYPE)) {
      78           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 1 must have a " STRING(TYPE) " tail");
      79           0 :                 goto bailout;
      80             :         }
      81           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
      82           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      83           0 :                 goto bailout;
      84             :         }
      85           0 :         canditer_init(&ci1, b, bs);
      86           0 :         if (!(bn = COLnew(ci1.hseq, TPE(TYPE), ci1.ncand, TRANSIENT))) {
      87           0 :                 msg = createException(MAL, "round", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      88           0 :                 goto bailout;
      89             :         }
      90             : 
      91           0 :         off1 = b->hseqbase;
      92           0 :         bi = bat_iterator(b);
      93           0 :         src = (TYPE *) bi.base;
      94           0 :         dst = (TYPE *) Tloc(bn, 0);
      95           0 :         if (ci1.tpe == cand_dense) {
      96           0 :                 for (BUN i = 0; i < ci1.ncand; i++) {
      97           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
      98           0 :                         x = src[p1];
      99             : 
     100           0 :                         if (ISNIL(TYPE)(x)) {
     101           0 :                                 dst[i] = NIL(TYPE);
     102           0 :                                 nils = true;
     103             :                         } else {
     104           0 :                                 dst[i] = dec_round_body(x, r);
     105           0 :                                 if (isinf(dst[i])) {
     106           0 :                                         msg = createException(MAL, "round", SQLSTATE(22003) "Overflow in round");
     107           0 :                                         goto bailout1;
     108             :                                 }
     109             :                         }
     110             :                 }
     111             :         } else {
     112           0 :                 for (BUN i = 0; i < ci1.ncand; i++) {
     113           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     114           0 :                         x = src[p1];
     115             : 
     116           0 :                         if (ISNIL(TYPE)(x)) {
     117           0 :                                 dst[i] = NIL(TYPE);
     118           0 :                                 nils = true;
     119             :                         } else {
     120           0 :                                 dst[i] = dec_round_body(x, r);
     121           0 :                                 if (isinf(dst[i])) {
     122           0 :                                         msg = createException(MAL, "round", SQLSTATE(22003) "Overflow in round");
     123           0 :                                         goto bailout1;
     124             :                                 }
     125             :                         }
     126             :                 }
     127             :         }
     128           0 :         btsorted = bi.sorted;
     129           0 :         btrevsorted = bi.revsorted;
     130           0 : bailout1:
     131           0 :         bat_iterator_end(&bi);
     132           0 : bailout:
     133           0 :         finalize_ouput_copy_sorted_property(res, bn, msg, nils, ci1.ncand, btsorted, btrevsorted);
     134           0 :         unfix_inputs(2, b, bs);
     135           0 :         return msg;
     136             : }
     137             : 
     138             : str
     139           0 : bat_dec_round_wrap_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     140             : {
     141           0 :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     142           0 :         TYPE *restrict src, *restrict dst, x = *(TYPE *)getArgReference(stk, pci, 1), r;
     143           0 :         str msg = MAL_SUCCEED;
     144           0 :         bool nils = false;
     145           0 :         struct canditer ci1 = {0};
     146           0 :         oid off1;
     147           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 2),
     148           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
     149           0 :         BATiter bi;
     150             : 
     151           0 :         (void) cntxt;
     152           0 :         (void) mb;
     153           0 :         if (!(b = BATdescriptor(*bid))) {
     154           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     155           0 :                 goto bailout;
     156             :         }
     157           0 :         if (b->ttype != TPE(TYPE)) {
     158           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 must have a " STRING(TYPE) " tail");
     159           0 :                 goto bailout;
     160             :         }
     161           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     162           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     163           0 :                 goto bailout;
     164             :         }
     165           0 :         canditer_init(&ci1, b, bs);
     166           0 :         if (!(bn = COLnew(ci1.hseq, TPE(TYPE), ci1.ncand, TRANSIENT))) {
     167           0 :                 msg = createException(MAL, "round", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     168           0 :                 goto bailout;
     169             :         }
     170             : 
     171           0 :         off1 = b->hseqbase;
     172           0 :         bi = bat_iterator(b);
     173           0 :         src = (TYPE *) bi.base;
     174           0 :         dst = (TYPE *) Tloc(bn, 0);
     175           0 :         if (ci1.tpe == cand_dense) {
     176           0 :                 for (BUN i = 0; i < ci1.ncand; i++) {
     177           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     178           0 :                         r = src[p1];
     179             : 
     180           0 :                         if (ISNIL(TYPE)(r)) {
     181           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function cannot be null");
     182           0 :                                 goto bailout1;
     183           0 :                         } else if (r <= 0) {
     184           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function must be positive");
     185           0 :                                 goto bailout1;
     186           0 :                         } else if (ISNIL(TYPE)(x)) {
     187           0 :                                 dst[i] = NIL(TYPE);
     188           0 :                                 nils = true;
     189             :                         } else {
     190           0 :                                 dst[i] = dec_round_body(x, r);
     191           0 :                                 if (isinf(dst[i])) {
     192           0 :                                         msg = createException(MAL, "round", SQLSTATE(22003) "Overflow in round");
     193           0 :                                         goto bailout1;
     194             :                                 }
     195             :                         }
     196             :                 }
     197             :         } else {
     198           0 :                 for (BUN i = 0; i < ci1.ncand; i++) {
     199           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     200           0 :                         r = src[p1];
     201             : 
     202           0 :                         if (ISNIL(TYPE)(r)) {
     203           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function cannot be null");
     204           0 :                                 goto bailout1;
     205           0 :                         } else if (r <= 0) {
     206           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function must be positive");
     207           0 :                                 goto bailout1;
     208           0 :                         } else if (ISNIL(TYPE)(x)) {
     209           0 :                                 dst[i] = NIL(TYPE);
     210           0 :                                 nils = true;
     211             :                         } else {
     212           0 :                                 dst[i] = dec_round_body(x, r);
     213           0 :                                 if (isinf(dst[i])) {
     214           0 :                                         msg = createException(MAL, "round", SQLSTATE(22003) "Overflow in round");
     215           0 :                                         goto bailout1;
     216             :                                 }
     217             :                         }
     218             :                 }
     219             :         }
     220           0 : bailout1:
     221           0 :         bat_iterator_end(&bi);
     222             : 
     223           0 : bailout:
     224           0 :         finalize_ouput_copy_sorted_property(res, bn, msg, nils, ci1.ncand, false, false/* don't propagate here*/);
     225           0 :         unfix_inputs(2, b, bs);
     226           0 :         return msg;
     227             : }
     228             : 
     229             : str
     230           0 : bat_dec_round_wrap_nocst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     231             : {
     232           0 :         BAT *bn = NULL, *left = NULL, *lefts = NULL, *right = NULL, *rights = NULL;
     233           0 :         TYPE *src1, *src2, *restrict dst, x, rr;
     234           0 :         str msg = MAL_SUCCEED;
     235           0 :         bool nils = false;
     236           0 :         struct canditer ci1 = {0}, ci2 = {0};
     237           0 :         oid off1, off2;
     238           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
     239           0 :                 *r = getArgReference_bat(stk, pci, 2),
     240           0 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 3) : NULL,
     241           0 :                 *sid2 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
     242           0 :         BATiter lefti, righti;
     243             : 
     244           0 :         (void) cntxt;
     245           0 :         (void) mb;
     246           0 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*r))) {
     247           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     248           0 :                 goto bailout;
     249             :         }
     250           0 :         if (left->ttype != TPE(TYPE) || right->ttype != TPE(TYPE)) {
     251           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Arguments must have a " STRING(TYPE) " tail");
     252           0 :                 goto bailout;
     253             :         }
     254           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(lefts = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(rights = BATdescriptor(*sid2)))) {
     255           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     256           0 :                 goto bailout;
     257             :         }
     258           0 :         canditer_init(&ci1, left, lefts);
     259           0 :         canditer_init(&ci2, right, rights);
     260           0 :         if (ci2.ncand != ci1.ncand || ci1.hseq != ci2.hseq) {
     261           0 :                 msg = createException(MAL, "round", ILLEGAL_ARGUMENT " Requires bats of identical size");
     262           0 :                 goto bailout;
     263             :         }
     264           0 :         if (!(bn = COLnew(ci1.hseq, TPE(TYPE), ci1.ncand, TRANSIENT))) {
     265           0 :                 msg = createException(MAL, "round", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     266           0 :                 goto bailout;
     267             :         }
     268             : 
     269           0 :         off1 = left->hseqbase;
     270           0 :         off2 = right->hseqbase;
     271           0 :         lefti = bat_iterator(left);
     272           0 :         righti = bat_iterator(right);
     273           0 :         src1 = (TYPE *) lefti.base;
     274           0 :         src2 = (TYPE *) righti.base;
     275           0 :         dst = (TYPE *) Tloc(bn, 0);
     276           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
     277           0 :                 for (BUN i = 0; i < ci1.ncand; i++) {
     278           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
     279           0 :                         x = src1[p1];
     280           0 :                         rr = src2[p2];
     281             : 
     282           0 :                         if (ISNIL(TYPE)(rr)) {
     283           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function cannot be null");
     284           0 :                                 goto bailout1;
     285           0 :                         } else if (rr <= 0) {
     286           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function must be positive");
     287           0 :                                 goto bailout1;
     288           0 :                         } else if (ISNIL(TYPE)(x)) {
     289           0 :                                 dst[i] = NIL(TYPE);
     290           0 :                                 nils = true;
     291             :                         } else {
     292           0 :                                 dst[i] = dec_round_body(x, rr);
     293           0 :                                 if (isinf(dst[i])) {
     294           0 :                                         msg = createException(MAL, "round", SQLSTATE(22003) "Overflow in round");
     295           0 :                                         goto bailout1;
     296             :                                 }
     297             :                         }
     298             :                 }
     299             :         } else {
     300           0 :                 for (BUN i = 0; i < ci1.ncand; i++) {
     301           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
     302           0 :                         x = src1[p1];
     303           0 :                         rr = src2[p2];
     304             : 
     305           0 :                         if (ISNIL(TYPE)(rr)) {
     306           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function cannot be null");
     307           0 :                                 goto bailout1;
     308           0 :                         } else if (rr <= 0) {
     309           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 to round function must be positive");
     310           0 :                                 goto bailout1;
     311           0 :                         } else if (ISNIL(TYPE)(x)) {
     312           0 :                                 dst[i] = NIL(TYPE);
     313           0 :                                 nils = true;
     314             :                         } else {
     315           0 :                                 dst[i] = dec_round_body(x, rr);
     316           0 :                                 if (isinf(dst[i])) {
     317           0 :                                         msg = createException(MAL, "round", SQLSTATE(22003) "Overflow in round");
     318           0 :                                         goto bailout1;
     319             :                                 }
     320             :                         }
     321             :                 }
     322             :         }
     323           0 : bailout1:
     324           0 :         bat_iterator_end(&lefti);
     325           0 :         bat_iterator_end(&righti);
     326             : 
     327           0 : bailout:
     328           0 :         finalize_ouput_copy_sorted_property(res, bn, msg, nils, ci1.ncand, false, false/* don't propagate here*/);
     329           0 :         unfix_inputs(4, left, lefts, right, rights);
     330           0 :         return msg;
     331             : }
     332             : 
     333             : static inline TYPE
     334          29 : round_body(TYPE v, int r)
     335             : {
     336          29 :         TYPE res = NIL(TYPE);
     337             : 
     338          29 :         assert(!ISNIL(TYPE)(v));
     339             : 
     340          29 :         if (r < 0) {
     341           0 :                 int d = -r;
     342           0 :                 TYPE rnd = (TYPE) (scales[d] >> 1);
     343             : 
     344           0 :                 res = (TYPE) (floor(((v + rnd) / ((TYPE) (scales[d])))) * scales[d]);
     345          29 :         } else if (r > 0) {
     346          12 :                 int d = r;
     347             : 
     348          12 :                 res = (TYPE) (floor(v * (TYPE) scales[d] + .5) / scales[d]);
     349             :         } else {
     350          17 :                 res = (TYPE) round(v);
     351             :         }
     352          29 :         return res;
     353             : }
     354             : 
     355             : str
     356           5 : round_wrap(TYPE *res, const TYPE *v, const bte *r)
     357             : {
     358             :         /* basic sanity checks */
     359           5 :         assert(res && v && r);
     360           5 :         bte rr = *r;
     361             : 
     362           5 :         if (is_bte_nil(rr))
     363           0 :                 throw(MAL, "round", SQLSTATE(42000) "Number of digits cannot be NULL");
     364           5 :         if ((size_t) abs(rr) >= sizeof(scales) / sizeof(scales[0]))
     365           0 :                 throw(MAL, "round", SQLSTATE(42000) "Digits out of bounds");
     366           5 :         *res = (ISNIL(TYPE)(*v)) ? NIL(TYPE) : round_body(*v, rr);
     367           5 :         if (isinf(*res))
     368           2 :                 throw(MAL, "round", SQLSTATE(22003) "Overflow in round");
     369             :         return MAL_SUCCEED;
     370             : }
     371             : 
     372             : str
     373           6 : bat_round_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     374             : {
     375           6 :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     376           6 :         TYPE *restrict src, *restrict dst, x;
     377           6 :         bte r = *getArgReference_bte(stk, pci, 2);
     378           6 :         str msg = MAL_SUCCEED;
     379           6 :         bool nils = false, btsorted = false, btrevsorted = false;
     380           6 :         struct canditer ci1 = {0};
     381           6 :         oid off1;
     382           6 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1),
     383           6 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
     384           6 :         BATiter bi;
     385             : 
     386           6 :         (void) cntxt;
     387           6 :         (void) mb;
     388           6 :         if (is_bte_nil(r)) {
     389           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Number of digits cannot be NULL");
     390           0 :                 goto bailout;
     391             :         }
     392           6 :         if ((size_t) abs(r) >= sizeof(scales) / sizeof(scales[0])) {
     393           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Digits out of bounds");
     394           0 :                 goto bailout;
     395             :         }
     396           6 :         if (!(b = BATdescriptor(*bid))) {
     397           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     398           0 :                 goto bailout;
     399             :         }
     400           6 :         if (b->ttype != TPE(TYPE)) {
     401           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 1 must have a " STRING(TYPE) " tail");
     402           0 :                 goto bailout;
     403             :         }
     404           6 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     405           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     406           0 :                 goto bailout;
     407             :         }
     408           6 :         canditer_init(&ci1, b, bs);
     409           6 :         if (!(bn = COLnew(ci1.hseq, TPE(TYPE), ci1.ncand, TRANSIENT))) {
     410           0 :                 msg = createException(MAL, "round", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     411           0 :                 goto bailout;
     412             :         }
     413             : 
     414           6 :         off1 = b->hseqbase;
     415           6 :         bi = bat_iterator(b);
     416           6 :         src = (TYPE *) bi.base;
     417           6 :         dst = (TYPE *) Tloc(bn, 0);
     418           6 :         if (ci1.tpe == cand_dense) {
     419          30 :                 for (BUN i = 0; i < ci1.ncand; i++) {
     420          24 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     421          24 :                         x = src[p1];
     422             : 
     423          24 :                         if (ISNIL(TYPE)(x)) {
     424           0 :                                 dst[i] = NIL(TYPE);
     425           0 :                                 nils = true;
     426             :                         } else {
     427          24 :                                 dst[i] = round_body(x, r);
     428          24 :                                 if (isinf(dst[i])) {
     429           0 :                                         msg = createException(MAL, "round", SQLSTATE(22003) "Overflow in round");
     430           0 :                                         goto bailout1;
     431             :                                 }
     432             :                         }
     433             :                 }
     434             :         } else {
     435           0 :                 for (BUN i = 0; i < ci1.ncand; i++) {
     436           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     437           0 :                         x = src[p1];
     438             : 
     439           0 :                         if (ISNIL(TYPE)(x)) {
     440           0 :                                 dst[i] = NIL(TYPE);
     441           0 :                                 nils = true;
     442             :                         } else {
     443           0 :                                 dst[i] = round_body(x, r);
     444           0 :                                 if (isinf(dst[i])) {
     445           0 :                                         msg = createException(MAL, "round", SQLSTATE(22003) "Overflow in round");
     446           0 :                                         goto bailout1;
     447             :                                 }
     448             :                         }
     449             :                 }
     450             :         }
     451           6 :         btsorted = bi.sorted;
     452           6 :         btrevsorted = bi.revsorted;
     453           6 : bailout1:
     454           6 :         bat_iterator_end(&bi);
     455           6 : bailout:
     456           6 :         finalize_ouput_copy_sorted_property(res, bn, msg, nils, ci1.ncand, btsorted, btrevsorted);
     457           6 :         unfix_inputs(2, b, bs);
     458           6 :         return msg;
     459             : }
     460             : 
     461             : str
     462           0 : bat_round_wrap_cst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     463             : {
     464           0 :         BAT *bn = NULL, *b = NULL, *bs = NULL;
     465           0 :         TYPE *restrict dst, x = *(TYPE *)getArgReference(stk, pci, 1);
     466           0 :         bte *restrict src, r;
     467           0 :         str msg = MAL_SUCCEED;
     468           0 :         bool nils = false;
     469           0 :         struct canditer ci1 = {0};
     470           0 :         oid off1;
     471           0 :         bat *res = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 2),
     472           0 :                 *sid1 = pci->argc == 4 ? getArgReference_bat(stk, pci, 3) : NULL;
     473           0 :         BATiter bi;
     474             : 
     475           0 :         (void) cntxt;
     476           0 :         (void) mb;
     477           0 :         if (!(b = BATdescriptor(*bid))) {
     478           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     479           0 :                 goto bailout;
     480             :         }
     481           0 :         if (b->ttype != TYPE_bte) {
     482           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 must have a bte tail");
     483           0 :                 goto bailout;
     484             :         }
     485           0 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
     486           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     487           0 :                 goto bailout;
     488             :         }
     489           0 :         canditer_init(&ci1, b, bs);
     490           0 :         if (!(bn = COLnew(ci1.hseq, TPE(TYPE), ci1.ncand, TRANSIENT))) {
     491           0 :                 msg = createException(MAL, "round", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     492           0 :                 goto bailout;
     493             :         }
     494             : 
     495           0 :         off1 = b->hseqbase;
     496           0 :         bi = bat_iterator(b);
     497           0 :         src = (bte *) bi.base;
     498           0 :         dst = (TYPE *) Tloc(bn, 0);
     499           0 :         if (ci1.tpe == cand_dense) {
     500           0 :                 for (BUN i = 0; i < ci1.ncand; i++) {
     501           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
     502           0 :                         r = src[p1];
     503             : 
     504           0 :                         if (is_bte_nil(r)) {
     505           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Number of digits cannot be NULL");
     506           0 :                                 goto bailout1;
     507           0 :                         } else if ((size_t) abs(r) >= sizeof(scales) / sizeof(scales[0])) {
     508           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Digits out of bounds");
     509           0 :                                 goto bailout1;
     510           0 :                         } else if (ISNIL(TYPE)(x)) {
     511           0 :                                 dst[i] = NIL(TYPE);
     512           0 :                                 nils = true;
     513             :                         } else {
     514           0 :                                 dst[i] = round_body(x, r);
     515           0 :                                 if (isinf(dst[i])) {
     516           0 :                                         msg = createException(MAL, "round", SQLSTATE(22003) "Overflow in round");
     517           0 :                                         goto bailout1;
     518             :                                 }
     519             :                         }
     520             :                 }
     521             :         } else {
     522           0 :                 for (BUN i = 0; i < ci1.ncand; i++) {
     523           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     524           0 :                         r = src[p1];
     525             : 
     526           0 :                         if (is_bte_nil(r)) {
     527           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Number of digits cannot be NULL");
     528           0 :                                 goto bailout1;
     529           0 :                         } else if ((size_t) abs(r) >= sizeof(scales) / sizeof(scales[0])) {
     530           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Digits out of bounds");
     531           0 :                                 goto bailout1;
     532           0 :                         } else if (ISNIL(TYPE)(x)) {
     533           0 :                                 dst[i] = NIL(TYPE);
     534           0 :                                 nils = true;
     535             :                         } else {
     536           0 :                                 dst[i] = round_body(x, r);
     537           0 :                                 if (isinf(dst[i])) {
     538           0 :                                         msg = createException(MAL, "round", SQLSTATE(22003) "Overflow in round");
     539           0 :                                         goto bailout1;
     540             :                                 }
     541             :                         }
     542             :                 }
     543             :         }
     544           0 : bailout1:
     545           0 :         bat_iterator_end(&bi);
     546             : 
     547           0 : bailout:
     548           0 :         finalize_ouput_copy_sorted_property(res, bn, msg, nils, ci1.ncand, false, false/* don't propagate here*/);
     549           0 :         unfix_inputs(2, b, bs);
     550           0 :         return msg;
     551             : }
     552             : 
     553             : str
     554           0 : bat_round_wrap_nocst(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     555             : {
     556           0 :         BAT *bn = NULL, *left = NULL, *lefts = NULL, *right = NULL, *rights = NULL;
     557           0 :         TYPE *src1, *restrict dst, x;
     558           0 :         bte *src2, rr;
     559           0 :         str msg = MAL_SUCCEED;
     560           0 :         bool nils = false;
     561           0 :         struct canditer ci1 = {0}, ci2 = {0};
     562           0 :         oid off1, off2;
     563           0 :         bat *res = getArgReference_bat(stk, pci, 0), *l = getArgReference_bat(stk, pci, 1),
     564           0 :                 *r = getArgReference_bat(stk, pci, 2),
     565           0 :                 *sid1 = pci->argc == 5 ? getArgReference_bat(stk, pci, 3) : NULL,
     566           0 :                 *sid2 = pci->argc == 5 ? getArgReference_bat(stk, pci, 4) : NULL;
     567           0 :         BATiter lefti, righti;
     568             : 
     569           0 :         (void) cntxt;
     570           0 :         (void) mb;
     571           0 :         if (!(left = BATdescriptor(*l)) || !(right = BATdescriptor(*r))) {
     572           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     573           0 :                 goto bailout;
     574             :         }
     575           0 :         if (left->ttype != TPE(TYPE)) {
     576           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 1 must have a " STRING(TYPE) " tail");
     577           0 :                 goto bailout;
     578             :         }
     579           0 :         if (right->ttype != TYPE_bte) {
     580           0 :                 msg = createException(MAL, "round", SQLSTATE(42000) "Argument 2 must have a bte tail");
     581           0 :                 goto bailout;
     582             :         }
     583           0 :         if ((sid1 && !is_bat_nil(*sid1) && !(lefts = BATdescriptor(*sid1))) || (sid2 && !is_bat_nil(*sid2) && !(rights = BATdescriptor(*sid2)))) {
     584           0 :                 msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     585           0 :                 goto bailout;
     586             :         }
     587           0 :         canditer_init(&ci1, left, lefts);
     588           0 :         canditer_init(&ci2, right, rights);
     589           0 :         if (ci2.ncand != ci1.ncand || ci1.hseq != ci2.hseq) {
     590           0 :                 msg = createException(MAL, "round", ILLEGAL_ARGUMENT " Requires bats of identical size");
     591           0 :                 goto bailout;
     592             :         }
     593           0 :         if (!(bn = COLnew(ci1.hseq, TPE(TYPE), ci1.ncand, TRANSIENT))) {
     594           0 :                 msg = createException(MAL, "round", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     595           0 :                 goto bailout;
     596             :         }
     597             : 
     598           0 :         off1 = left->hseqbase;
     599           0 :         off2 = right->hseqbase;
     600           0 :         lefti = bat_iterator(left);
     601           0 :         righti = bat_iterator(right);
     602           0 :         src1 = (TYPE *) lefti.base;
     603           0 :         src2 = (bte *) righti.base;
     604           0 :         dst = (TYPE *) Tloc(bn, 0);
     605           0 :         if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
     606           0 :                 for (BUN i = 0; i < ci1.ncand; i++) {
     607           0 :                         oid p1 = (canditer_next_dense(&ci1) - off1), p2 = (canditer_next_dense(&ci2) - off2);
     608           0 :                         x = src1[p1];
     609           0 :                         rr = src2[p2];
     610             : 
     611           0 :                         if (is_bte_nil(rr)) {
     612           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Number of digits cannot be NULL");
     613           0 :                                 goto bailout1;
     614           0 :                         } else if ((size_t) abs(rr) >= sizeof(scales) / sizeof(scales[0])) {
     615           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Digits out of bounds");
     616           0 :                                 goto bailout1;
     617           0 :                         } else if (ISNIL(TYPE)(x)) {
     618           0 :                                 dst[i] = NIL(TYPE);
     619           0 :                                 nils = true;
     620             :                         } else {
     621           0 :                                 dst[i] = round_body(x, rr);
     622           0 :                                 if (isinf(dst[i])) {
     623           0 :                                         msg = createException(MAL, "round", SQLSTATE(22003) "Overflow in round");
     624           0 :                                         goto bailout1;
     625             :                                 }
     626             :                         }
     627             :                 }
     628             :         } else {
     629           0 :                 for (BUN i = 0; i < ci1.ncand; i++) {
     630           0 :                         oid p1 = (canditer_next(&ci1) - off1), p2 = (canditer_next(&ci2) - off2);
     631           0 :                         x = src1[p1];
     632           0 :                         rr = src2[p2];
     633             : 
     634           0 :                         if (is_bte_nil(rr)) {
     635           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Number of digits cannot be NULL");
     636           0 :                                 goto bailout1;
     637           0 :                         } else if ((size_t) abs(rr) >= sizeof(scales) / sizeof(scales[0])) {
     638           0 :                                 msg = createException(MAL, "round", SQLSTATE(42000) "Digits out of bounds");
     639           0 :                                 goto bailout1;
     640           0 :                         } else if (ISNIL(TYPE)(x)) {
     641           0 :                                 dst[i] = NIL(TYPE);
     642           0 :                                 nils = true;
     643             :                         } else {
     644           0 :                                 dst[i] = round_body(x, rr);
     645           0 :                                 if (isinf(dst[i])) {
     646           0 :                                         msg = createException(MAL, "round", SQLSTATE(22003) "Overflow in round");
     647           0 :                                         goto bailout1;
     648             :                                 }
     649             :                         }
     650             :                 }
     651             :         }
     652           0 : bailout1:
     653           0 :         bat_iterator_end(&lefti);
     654           0 :         bat_iterator_end(&righti);
     655             : 
     656           0 : bailout:
     657           0 :         finalize_ouput_copy_sorted_property(res, bn, msg, nils, ci1.ncand, false, false/* don't propagate here*/);
     658           0 :         unfix_inputs(4, left, lefts, right, rights);
     659           0 :         return msg;
     660             : }
     661             : 
     662             : str
     663           5 : trunc_wrap(TYPE *res, const TYPE *v, const int *r)
     664             : {
     665           5 :         int rr = *r;
     666             : 
     667           5 :         if (is_int_nil(rr))
     668           0 :                 throw(MAL, "trunc", SQLSTATE(42000) "Number of digits cannot be NULL");
     669           5 :         if ((size_t) abs(rr) >= sizeof(scales) / sizeof(scales[0]))
     670           0 :                 throw(MAL, "trunc", SQLSTATE(42000) "Digits out of bounds");
     671             : 
     672             :         /* shortcut nil */
     673           5 :         if (ISNIL(TYPE)(*v)) {
     674           0 :                 *res = NIL(TYPE);
     675           5 :         } else if (rr < 0) {
     676           0 :                 int d = -rr;
     677           0 :                 *res = (TYPE) (trunc((*v) / ((TYPE) scales[d])) * scales[d]);
     678           5 :         } else if (rr > 0) {
     679           4 :                 int d = rr;
     680           4 :                 *res = (TYPE) (trunc(*v * (TYPE) scales[d]) / ((TYPE) scales[d]));
     681             :         } else {
     682           1 :                 *res = (TYPE) trunc(*v);
     683             :         }
     684             :         return MAL_SUCCEED;
     685             : }
     686             : 
     687             : #undef dec_round_body
     688             : #undef dec_round_wrap
     689             : #undef bat_dec_round_wrap
     690             : #undef bat_dec_round_wrap_cst
     691             : #undef bat_dec_round_wrap_nocst
     692             : #undef round_body
     693             : #undef round_wrap
     694             : #undef bat_round_wrap
     695             : #undef bat_round_wrap_cst
     696             : #undef bat_round_wrap_nocst
     697             : #undef trunc_wrap

Generated by: LCOV version 1.14