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 31 : round_body(TYPE v, int r)
335 : {
336 31 : TYPE res = NIL(TYPE);
337 :
338 31 : assert(!ISNIL(TYPE)(v));
339 :
340 31 : 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 31 : } else if (r > 0) {
346 13 : int d = r;
347 :
348 13 : res = (TYPE) (floor(v * (TYPE) scales[d] + .5) / scales[d]);
349 : } else {
350 18 : res = (TYPE) round(v);
351 : }
352 31 : return res;
353 : }
354 :
355 : str
356 8 : round_wrap(TYPE *res, const TYPE *v, const bte *r)
357 : {
358 : /* basic sanity checks */
359 8 : assert(res && v && r);
360 8 : bte rr = *r;
361 :
362 8 : if (is_bte_nil(rr))
363 0 : throw(MAL, "round", SQLSTATE(42000) "Number of digits cannot be NULL");
364 8 : if ((size_t) abs(rr) >= sizeof(scales) / sizeof(scales[0]))
365 0 : throw(MAL, "round", SQLSTATE(42000) "Digits out of bounds");
366 8 : *res = (ISNIL(TYPE)(*v)) ? NIL(TYPE) : round_body(*v, rr);
367 8 : 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 1 : msg = createException(MAL, "round", SQLSTATE(42000) "Digits out of bounds");
394 1 : goto bailout;
395 : }
396 5 : if (!(b = BATdescriptor(*bid))) {
397 0 : msg = createException(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
398 0 : goto bailout;
399 : }
400 5 : 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 5 : 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 5 : canditer_init(&ci1, b, bs);
409 5 : 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 5 : off1 = b->hseqbase;
415 5 : bi = bat_iterator(b);
416 5 : src = (TYPE *) bi.base;
417 5 : dst = (TYPE *) Tloc(bn, 0);
418 5 : if (ci1.tpe == cand_dense) {
419 28 : for (BUN i = 0; i < ci1.ncand; i++) {
420 23 : oid p1 = (canditer_next_dense(&ci1) - off1);
421 23 : x = src[p1];
422 :
423 23 : if (ISNIL(TYPE)(x)) {
424 0 : dst[i] = NIL(TYPE);
425 0 : nils = true;
426 : } else {
427 23 : dst[i] = round_body(x, r);
428 23 : 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 5 : btsorted = bi.sorted;
452 5 : btrevsorted = bi.revsorted;
453 5 : bailout1:
454 5 : 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
|