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 - 2019 MonetDB B.V.
7 */
8
9#define dec_round_body_nonil FUN(TYPE, dec_round_body_nonil)
10#define dec_round_body FUN(TYPE, dec_round_body)
11#define dec_round_wrap FUN(TYPE, dec_round_wrap)
12#define bat_dec_round_wrap FUN(TYPE, bat_dec_round_wrap)
13#define round_body_nonil FUN(TYPE, round_body_nonil)
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 trunc_wrap FUN(TYPE, trunc_wrap)
18
19static inline TYPE
20dec_round_body_nonil(TYPE v, TYPE r)
21{
22 assert(!ISNIL(TYPE)(v));
23
24 return v / r;
25}
26
27static inline TYPE
28dec_round_body(TYPE v, TYPE r)
29{
30 /* shortcut nil */
31 if (ISNIL(TYPE)(v)) {
32 return NIL(TYPE);
33 } else {
34 return dec_round_body_nonil(v, r);
35 }
36}
37
38str
39dec_round_wrap(TYPE *res, const TYPE *v, const TYPE *r)
40{
41 /* basic sanity checks */
42 assert(res && v && r);
43
44 *res = dec_round_body(*v, *r);
45 return MAL_SUCCEED;
46}
47
48str
49bat_dec_round_wrap(bat *_res, const bat *_v, const TYPE *r)
50{
51 BAT *res, *v;
52 TYPE *src, *dst;
53 BUN i, cnt;
54 int nonil; /* TRUE: we know there are no NIL (NULL) values */
55
56 /* basic sanity checks */
57 assert(_res && _v && r);
58
59 /* get argument BAT descriptor */
60 if ((v = BATdescriptor(*_v)) == NULL)
61 throw(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
62
63 /* more sanity checks */
64 if (v->ttype != TPE(TYPE)) {
65 BBPunfix(v->batCacheid);
66 throw(MAL, "round", SQLSTATE(42000) "Argument 1 must have a " STRING(TYPE) " tail");
67 }
68 cnt = BATcount(v);
69
70 /* allocate result BAT */
71 res = COLnew(v->hseqbase, TPE(TYPE), cnt, TRANSIENT);
72 if (res == NULL) {
73 BBPunfix(v->batCacheid);
74 throw(MAL, "round", SQLSTATE(HY001) MAL_MALLOC_FAIL);
75 }
76
77 /* access columns as arrays */
78 src = (TYPE *) Tloc(v, 0);
79 dst = (TYPE *) Tloc(res, 0);
80
81 nonil = TRUE;
82 if (v->tnonil) {
83 for (i = 0; i < cnt; i++)
84 dst[i] = dec_round_body_nonil(src[i], *r);
85 } else {
86 for (i = 0; i < cnt; i++) {
87 if (ISNIL(TYPE)(src[i])) {
88 nonil = FALSE;
89 dst[i] = NIL(TYPE);
90 } else {
91 dst[i] = dec_round_body_nonil(src[i], *r);
92 }
93 }
94 }
95
96 /* set result BAT properties */
97 BATsetcount(res, cnt);
98 /* hard to predict correct tail properties in general */
99 res->tnonil = nonil;
100 res->tnil = !nonil;
101 res->tseqbase = oid_nil;
102 res->tsorted = v->tsorted;
103 res->trevsorted = v->trevsorted;
104 BATkey(res, false);
105
106 /* release argument BAT descriptors */
107 BBPunfix(v->batCacheid);
108
109 /* keep result */
110 BBPkeepref(*_res = res->batCacheid);
111
112 return MAL_SUCCEED;
113}
114
115static inline TYPE
116round_body_nonil(TYPE v, int r)
117{
118 TYPE res = NIL(TYPE);
119
120 assert(!ISNIL(TYPE)(v));
121
122 if (r < 0) {
123 int d = -r;
124 TYPE rnd = (TYPE) (scales[d] >> 1);
125
126 res = (TYPE) (floor(((v + rnd) / ((TYPE) (scales[d])))) * scales[d]);
127 } else if (r > 0) {
128 int d = r;
129
130 res = (TYPE) (floor(v * (TYPE) scales[d] + .5) / scales[d]);
131 } else {
132 res = (TYPE) round(v);
133 }
134 return res;
135}
136
137static inline TYPE
138round_body(TYPE v, int r)
139{
140 /* shortcut nil */
141 if (ISNIL(TYPE)(v)) {
142 return NIL(TYPE);
143 } else {
144 return round_body_nonil(v, r);
145 }
146}
147
148str
149round_wrap(TYPE *res, const TYPE *v, const bte *r)
150{
151 /* basic sanity checks */
152 assert(res && v && r);
153
154 *res = round_body(*v, *r);
155 return MAL_SUCCEED;
156}
157
158str
159bat_round_wrap(bat *_res, const bat *_v, const bte *r)
160{
161 BAT *res, *v;
162 TYPE *src, *dst;
163 BUN i, cnt;
164 int nonil; /* TRUE: we know there are no NIL (NULL) values */
165
166 /* basic sanity checks */
167 assert(_res && _v && r);
168
169 /* get argument BAT descriptor */
170 if ((v = BATdescriptor(*_v)) == NULL)
171 throw(MAL, "round", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
172
173 /* more sanity checks */
174 if (v->ttype != TPE(TYPE)) {
175 BBPunfix(v->batCacheid);
176 throw(MAL, "round", SQLSTATE(42000) "Argument 1 must have a " STRING(TYPE) " tail");
177 }
178 cnt = BATcount(v);
179
180 /* allocate result BAT */
181 res = COLnew(v->hseqbase, TPE(TYPE), cnt, TRANSIENT);
182 if (res == NULL) {
183 BBPunfix(v->batCacheid);
184 throw(MAL, "round", SQLSTATE(HY001) MAL_MALLOC_FAIL);
185 }
186
187 /* access columns as arrays */
188 src = (TYPE *) Tloc(v, 0);
189 dst = (TYPE *) Tloc(res, 0);
190
191 nonil = TRUE;
192 if (v->tnonil) {
193 for (i = 0; i < cnt; i++)
194 dst[i] = round_body_nonil(src[i], *r);
195 } else {
196 for (i = 0; i < cnt; i++) {
197 if (ISNIL(TYPE)(src[i])) {
198 nonil = FALSE;
199 dst[i] = NIL(TYPE);
200 } else {
201 dst[i] = round_body_nonil(src[i], *r);
202 }
203 }
204 }
205
206 /* set result BAT properties */
207 BATsetcount(res, cnt);
208 /* hard to predict correct tail properties in general */
209 res->tnonil = nonil;
210 res->tnil = !nonil;
211 res->tseqbase = oid_nil;
212 res->tsorted = v->tsorted;
213 res->trevsorted = v->trevsorted;
214 BATkey(res, false);
215
216 /* release argument BAT descriptors */
217 BBPunfix(v->batCacheid);
218
219 /* keep result */
220 BBPkeepref(*_res = res->batCacheid);
221
222 return MAL_SUCCEED;
223}
224
225str
226trunc_wrap(TYPE *res, const TYPE *v, const int *r)
227{
228 /* shortcut nil */
229 if (ISNIL(TYPE)(*v)) {
230 *res = NIL(TYPE);
231 } else if (*r < 0) {
232 int d = -*r;
233 *res = (TYPE) (trunc((*v) / ((TYPE) scales[d])) * scales[d]);
234 } else if (*r > 0) {
235 int d = *r;
236 *res = (TYPE) (trunc(*v * (TYPE) scales[d]) / ((TYPE) scales[d]));
237 } else {
238 *res = (TYPE) trunc(*v);
239 }
240 return MAL_SUCCEED;
241}
242
243#undef dec_round_body_nonil
244#undef dec_round_body
245#undef dec_round_wrap
246#undef bat_dec_round_wrap
247#undef round_body_nonil
248#undef round_body
249#undef round_wrap
250#undef bat_round_wrap
251#undef trunc_wrap
252