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 | #include "monetdb_config.h" |
10 | #include "gdk.h" |
11 | #include "gdk_analytic.h" |
12 | #include "gdk_calc_private.h" |
13 | |
14 | #define ANALYTICAL_DIFF_IMP(TPE) \ |
15 | do { \ |
16 | TPE *bp = (TPE*)Tloc(b, 0); \ |
17 | TPE prev = *bp, *end = bp + cnt; \ |
18 | if (np) { \ |
19 | for (; bp < end; bp++, rb++, np++) { \ |
20 | *rb = *np; \ |
21 | if (*bp != prev) { \ |
22 | *rb = TRUE; \ |
23 | prev = *bp; \ |
24 | } \ |
25 | } \ |
26 | } else { \ |
27 | for (; bp < end; bp++, rb++) { \ |
28 | if (*bp == prev) { \ |
29 | *rb = FALSE; \ |
30 | } else { \ |
31 | *rb = TRUE; \ |
32 | prev = *bp; \ |
33 | } \ |
34 | } \ |
35 | } \ |
36 | } while (0) |
37 | |
38 | /* We use NaN for floating point null values, which always output false on equality tests */ |
39 | #define ANALYTICAL_DIFF_FLOAT_IMP(TPE) \ |
40 | do { \ |
41 | TPE *bp = (TPE*)Tloc(b, 0); \ |
42 | TPE prev = *bp, *end = bp + cnt; \ |
43 | if (np) { \ |
44 | for (; bp < end; bp++, rb++, np++) { \ |
45 | *rb = *np; \ |
46 | if (*bp != prev && (!is_##TPE##_nil(*bp) || !is_##TPE##_nil(prev))) { \ |
47 | *rb = TRUE; \ |
48 | prev = *bp; \ |
49 | } \ |
50 | } \ |
51 | } else { \ |
52 | for (; bp < end; bp++, rb++) { \ |
53 | if (*bp == prev || (is_##TPE##_nil(*bp) && is_##TPE##_nil(prev))) { \ |
54 | *rb = FALSE; \ |
55 | } else { \ |
56 | *rb = TRUE; \ |
57 | prev = *bp; \ |
58 | } \ |
59 | } \ |
60 | } \ |
61 | } while (0) |
62 | |
63 | gdk_return |
64 | GDKanalyticaldiff(BAT *r, BAT *b, BAT *p, int tpe) |
65 | { |
66 | BUN i, cnt = BATcount(b); |
67 | bit *restrict rb = (bit *) Tloc(r, 0), *restrict np = p ? (bit *) Tloc(p, 0) : NULL; |
68 | |
69 | switch (tpe) { |
70 | case TYPE_bit: |
71 | ANALYTICAL_DIFF_IMP(bit); |
72 | break; |
73 | case TYPE_bte: |
74 | ANALYTICAL_DIFF_IMP(bte); |
75 | break; |
76 | case TYPE_sht: |
77 | ANALYTICAL_DIFF_IMP(sht); |
78 | break; |
79 | case TYPE_int: |
80 | ANALYTICAL_DIFF_IMP(int); |
81 | break; |
82 | case TYPE_lng: |
83 | ANALYTICAL_DIFF_IMP(lng); |
84 | break; |
85 | #ifdef HAVE_HGE |
86 | case TYPE_hge: |
87 | ANALYTICAL_DIFF_IMP(hge); |
88 | break; |
89 | #endif |
90 | case TYPE_flt: { |
91 | if (b->tnonil) { |
92 | ANALYTICAL_DIFF_IMP(flt); |
93 | } else { /* Because of NaN values, use this path */ |
94 | ANALYTICAL_DIFF_FLOAT_IMP(flt); |
95 | } |
96 | } break; |
97 | case TYPE_dbl: { |
98 | if (b->tnonil) { |
99 | ANALYTICAL_DIFF_IMP(dbl); |
100 | } else { /* Because of NaN values, use this path */ |
101 | ANALYTICAL_DIFF_FLOAT_IMP(dbl); |
102 | } |
103 | } break; |
104 | default:{ |
105 | BATiter it = bat_iterator(b); |
106 | ptr v = BUNtail(it, 0), next; |
107 | int (*atomcmp) (const void *, const void *) = ATOMcompare(tpe); |
108 | if (np) { |
109 | for (i = 0; i < cnt; i++, rb++, np++) { |
110 | *rb = *np; |
111 | next = BUNtail(it, i); |
112 | if (atomcmp(v, next) != 0) { |
113 | *rb = TRUE; |
114 | v = next; |
115 | } |
116 | } |
117 | } else { |
118 | for (i = 0; i < cnt; i++, rb++) { |
119 | next = BUNtail(it, i); |
120 | if (atomcmp(v, next) != 0) { |
121 | *rb = TRUE; |
122 | v = next; |
123 | } else { |
124 | *rb = FALSE; |
125 | } |
126 | } |
127 | } |
128 | } |
129 | } |
130 | BATsetcount(r, cnt); |
131 | r->tnonil = true; |
132 | r->tnil = false; |
133 | return GDK_SUCCEED; |
134 | } |
135 | |
136 | #define NTILE_CALC \ |
137 | do { \ |
138 | if (bval >= ncnt) { \ |
139 | j = 1; \ |
140 | for (; rb < rp; j++, rb++) \ |
141 | *rb = j; \ |
142 | } else if (ncnt % bval == 0) { \ |
143 | buckets = ncnt / bval; \ |
144 | for (; rb < rp; i++, rb++) { \ |
145 | if (i == buckets) { \ |
146 | j++; \ |
147 | i = 0; \ |
148 | } \ |
149 | *rb = j; \ |
150 | } \ |
151 | } else { \ |
152 | buckets = ncnt / bval; \ |
153 | for (; rb < rp; i++, rb++) { \ |
154 | *rb = j; \ |
155 | if (i == buckets) { \ |
156 | j++; \ |
157 | i = 0; \ |
158 | } \ |
159 | } \ |
160 | } \ |
161 | } while (0) |
162 | |
163 | #define ANALYTICAL_NTILE_IMP(TPE) \ |
164 | do { \ |
165 | TPE j = 1, *rp, *rb, val = *(TPE*) ntile; \ |
166 | BUN bval = (BUN) val; \ |
167 | rb = rp = (TPE*)Tloc(r, 0); \ |
168 | if (is_##TPE##_nil(val)) { \ |
169 | TPE *end = rp + cnt; \ |
170 | has_nils = true; \ |
171 | for (; rp < end; rp++) \ |
172 | *rp = TPE##_nil; \ |
173 | } else if (p) { \ |
174 | pnp = np = (bit*)Tloc(p, 0); \ |
175 | end = np + cnt; \ |
176 | for (; np < end; np++) { \ |
177 | if (*np) { \ |
178 | i = 0; \ |
179 | j = 1; \ |
180 | ncnt = np - pnp; \ |
181 | rp += ncnt; \ |
182 | NTILE_CALC; \ |
183 | pnp = np; \ |
184 | } \ |
185 | } \ |
186 | i = 0; \ |
187 | j = 1; \ |
188 | ncnt = np - pnp; \ |
189 | rp += ncnt; \ |
190 | NTILE_CALC; \ |
191 | } else { \ |
192 | rp += cnt; \ |
193 | NTILE_CALC; \ |
194 | } \ |
195 | } while (0) |
196 | |
197 | gdk_return |
198 | GDKanalyticalntile(BAT *r, BAT *b, BAT *p, int tpe, const void *restrict ntile) |
199 | { |
200 | BUN cnt = BATcount(b), ncnt = cnt, buckets, i = 0; |
201 | bit *np, *pnp, *end; |
202 | bool has_nils = false; |
203 | |
204 | assert(ntile); |
205 | |
206 | switch (tpe) { |
207 | case TYPE_bte: |
208 | ANALYTICAL_NTILE_IMP(bte); |
209 | break; |
210 | case TYPE_sht: |
211 | ANALYTICAL_NTILE_IMP(sht); |
212 | break; |
213 | case TYPE_int: |
214 | ANALYTICAL_NTILE_IMP(int); |
215 | break; |
216 | case TYPE_lng: |
217 | ANALYTICAL_NTILE_IMP(lng); |
218 | break; |
219 | #ifdef HAVE_HGE |
220 | case TYPE_hge: |
221 | ANALYTICAL_NTILE_IMP(hge); |
222 | break; |
223 | #endif |
224 | default: |
225 | GDKerror("GDKanalyticalntile: type %s not supported.\n" , ATOMname(tpe)); |
226 | return GDK_FAIL; |
227 | } |
228 | BATsetcount(r, cnt); |
229 | r->tnonil = !has_nils; |
230 | r->tnil = has_nils; |
231 | return GDK_SUCCEED; |
232 | } |
233 | |
234 | #define ANALYTICAL_FIRST_IMP(TPE) \ |
235 | do { \ |
236 | TPE *bp, *bs, *be, curval, *restrict rb; \ |
237 | bp = (TPE*)Tloc(b, 0); \ |
238 | rb = (TPE*)Tloc(r, 0); \ |
239 | for (; i < cnt; i++, rb++) { \ |
240 | bs = bp + start[i]; \ |
241 | be = bp + end[i]; \ |
242 | curval = (be > bs) ? *bs : TPE##_nil; \ |
243 | *rb = curval; \ |
244 | if (is_##TPE##_nil(curval)) \ |
245 | has_nils = true; \ |
246 | } \ |
247 | } while (0) |
248 | |
249 | gdk_return |
250 | GDKanalyticalfirst(BAT *r, BAT *b, BAT *s, BAT *e, int tpe) |
251 | { |
252 | BUN i = 0, cnt = BATcount(b); |
253 | lng *restrict start, *restrict end; |
254 | bool has_nils = false; |
255 | |
256 | assert(s && e); |
257 | start = (lng *) Tloc(s, 0); |
258 | end = (lng *) Tloc(e, 0); |
259 | |
260 | switch (tpe) { |
261 | case TYPE_bit: |
262 | ANALYTICAL_FIRST_IMP(bit); |
263 | break; |
264 | case TYPE_bte: |
265 | ANALYTICAL_FIRST_IMP(bte); |
266 | break; |
267 | case TYPE_sht: |
268 | ANALYTICAL_FIRST_IMP(sht); |
269 | break; |
270 | case TYPE_int: |
271 | ANALYTICAL_FIRST_IMP(int); |
272 | break; |
273 | case TYPE_lng: |
274 | ANALYTICAL_FIRST_IMP(lng); |
275 | break; |
276 | #ifdef HAVE_HGE |
277 | case TYPE_hge: |
278 | ANALYTICAL_FIRST_IMP(hge); |
279 | break; |
280 | #endif |
281 | case TYPE_flt: |
282 | ANALYTICAL_FIRST_IMP(flt); |
283 | break; |
284 | case TYPE_dbl: |
285 | ANALYTICAL_FIRST_IMP(dbl); |
286 | break; |
287 | default:{ |
288 | const void *restrict nil = ATOMnilptr(tpe); |
289 | int (*atomcmp) (const void *, const void *) = ATOMcompare(tpe); |
290 | BATiter bpi = bat_iterator(b); |
291 | void *curval; |
292 | |
293 | for (; i < cnt; i++) { |
294 | curval = (end[i] > start[i]) ? BUNtail(bpi, (BUN) start[i]) : (void *) nil; |
295 | if (BUNappend(r, curval, false) != GDK_SUCCEED) |
296 | goto allocation_error; |
297 | if (atomcmp(curval, nil) == 0) |
298 | has_nils = true; |
299 | } |
300 | } |
301 | } |
302 | BATsetcount(r, cnt); |
303 | r->tnonil = !has_nils; |
304 | r->tnil = has_nils; |
305 | return GDK_SUCCEED; |
306 | allocation_error: |
307 | GDKerror("GDKanalyticalfirst: malloc failure\n" ); |
308 | return GDK_FAIL; |
309 | } |
310 | |
311 | #define ANALYTICAL_LAST_IMP(TPE) \ |
312 | do { \ |
313 | TPE *bp, *bs, *be, curval, *restrict rb; \ |
314 | bp = (TPE*)Tloc(b, 0); \ |
315 | rb = (TPE*)Tloc(r, 0); \ |
316 | for (; i<cnt; i++, rb++) { \ |
317 | bs = bp + start[i]; \ |
318 | be = bp + end[i]; \ |
319 | curval = (be > bs) ? *(be - 1) : TPE##_nil; \ |
320 | *rb = curval; \ |
321 | if (is_##TPE##_nil(curval)) \ |
322 | has_nils = true; \ |
323 | } \ |
324 | } while (0) |
325 | |
326 | gdk_return |
327 | GDKanalyticallast(BAT *r, BAT *b, BAT *s, BAT *e, int tpe) |
328 | { |
329 | BUN i = 0, cnt = BATcount(b); |
330 | lng *restrict start, *restrict end; |
331 | bool has_nils = false; |
332 | |
333 | assert(s && e); |
334 | start = (lng *) Tloc(s, 0); |
335 | end = (lng *) Tloc(e, 0); |
336 | |
337 | switch (tpe) { |
338 | case TYPE_bit: |
339 | ANALYTICAL_LAST_IMP(bit); |
340 | break; |
341 | case TYPE_bte: |
342 | ANALYTICAL_LAST_IMP(bte); |
343 | break; |
344 | case TYPE_sht: |
345 | ANALYTICAL_LAST_IMP(sht); |
346 | break; |
347 | case TYPE_int: |
348 | ANALYTICAL_LAST_IMP(int); |
349 | break; |
350 | case TYPE_lng: |
351 | ANALYTICAL_LAST_IMP(lng); |
352 | break; |
353 | #ifdef HAVE_HGE |
354 | case TYPE_hge: |
355 | ANALYTICAL_LAST_IMP(hge); |
356 | break; |
357 | #endif |
358 | case TYPE_flt: |
359 | ANALYTICAL_LAST_IMP(flt); |
360 | break; |
361 | case TYPE_dbl: |
362 | ANALYTICAL_LAST_IMP(dbl); |
363 | break; |
364 | default:{ |
365 | const void *restrict nil = ATOMnilptr(tpe); |
366 | int (*atomcmp) (const void *, const void *) = ATOMcompare(tpe); |
367 | BATiter bpi = bat_iterator(b); |
368 | void *curval; |
369 | |
370 | for (; i < cnt; i++) { |
371 | curval = (end[i] > start[i]) ? BUNtail(bpi, (BUN) (end[i] - 1)) : (void *) nil; |
372 | if (BUNappend(r, curval, false) != GDK_SUCCEED) |
373 | goto allocation_error; |
374 | if (atomcmp(curval, nil) == 0) |
375 | has_nils = true; |
376 | } |
377 | } |
378 | } |
379 | BATsetcount(r, cnt); |
380 | r->tnonil = !has_nils; |
381 | r->tnil = has_nils; |
382 | return GDK_SUCCEED; |
383 | allocation_error: |
384 | GDKerror("GDKanalyticallast: malloc failure\n" ); |
385 | return GDK_FAIL; |
386 | } |
387 | |
388 | #define ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(TPE1) \ |
389 | do { \ |
390 | TPE1 *bp = (TPE1*)Tloc(b, 0), *bs, *be, curval, *restrict rb = (TPE1*)Tloc(r, 0); \ |
391 | if (is_lng_nil(nth)) { \ |
392 | has_nils = true; \ |
393 | for (; i < cnt; i++, rb++) \ |
394 | *rb = TPE1##_nil; \ |
395 | } else { \ |
396 | nth--; \ |
397 | for (; i < cnt; i++, rb++) { \ |
398 | bs = bp + start[i]; \ |
399 | be = bp + end[i]; \ |
400 | curval = (be > bs && nth < (end[i] - start[i])) ? *(bs + nth) : TPE1##_nil; \ |
401 | *rb = curval; \ |
402 | if (is_##TPE1##_nil(curval)) \ |
403 | has_nils = true; \ |
404 | } \ |
405 | } \ |
406 | } while (0) |
407 | |
408 | #define ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE1, TPE2, TPE3) \ |
409 | do { \ |
410 | TPE2 *restrict lp = (TPE2*)Tloc(l, 0); \ |
411 | for (; i < cnt; i++, rb++) { \ |
412 | TPE2 lnth = lp[i]; \ |
413 | bs = bp + start[i]; \ |
414 | be = bp + end[i]; \ |
415 | if (is_##TPE2##_nil(lnth) || be <= bs || (TPE3)(lnth - 1) > (TPE3)(end[i] - start[i])) \ |
416 | curval = TPE1##_nil; \ |
417 | else \ |
418 | curval = *(bs + lnth - 1); \ |
419 | *rb = curval; \ |
420 | if (is_##TPE1##_nil(curval)) \ |
421 | has_nils = true; \ |
422 | } \ |
423 | } while (0) |
424 | |
425 | #ifdef HAVE_HGE |
426 | #define ANALYTICAL_NTHVALUE_CALC_FIXED_HGE(TPE1) \ |
427 | case TYPE_hge: \ |
428 | ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE1, hge, hge); \ |
429 | break; |
430 | #else |
431 | #define ANALYTICAL_NTHVALUE_CALC_FIXED_HGE(TPE1) |
432 | #endif |
433 | |
434 | #define ANALYTICAL_NTHVALUE_CALC_FIXED(TPE1) \ |
435 | do { \ |
436 | TPE1 *bp, *bs, *be, curval, *restrict rb; \ |
437 | bp = (TPE1*)Tloc(b, 0); \ |
438 | rb = (TPE1*)Tloc(r, 0); \ |
439 | switch (tp2) { \ |
440 | case TYPE_bte: \ |
441 | ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE1, bte, lng); \ |
442 | break; \ |
443 | case TYPE_sht: \ |
444 | ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE1, sht, lng); \ |
445 | break; \ |
446 | case TYPE_int: \ |
447 | ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE1, int, lng); \ |
448 | break; \ |
449 | case TYPE_lng: \ |
450 | ANALYTICAL_NTHVALUE_IMP_MULTI_FIXED(TPE1, lng, lng); \ |
451 | break; \ |
452 | ANALYTICAL_NTHVALUE_CALC_FIXED_HGE(TPE1) \ |
453 | default: \ |
454 | goto nosupport; \ |
455 | } \ |
456 | } while (0) |
457 | |
458 | #define ANALYTICAL_NTHVALUE_IMP_MULTI_VARSIZED(TPE1, TPE2) \ |
459 | do { \ |
460 | TPE1 *restrict lp = (TPE1*)Tloc(l, 0); \ |
461 | for (; i < cnt; i++) { \ |
462 | TPE1 lnth = lp[i]; \ |
463 | if (is_##TPE1##_nil(lnth) || end[i] <= start[i] || (TPE2)(lnth - 1) > (TPE2)(end[i] - start[i])) \ |
464 | curval = (void *) nil; \ |
465 | else \ |
466 | curval = BUNtail(bpi, (BUN) (start[i] + lnth - 1)); \ |
467 | if (BUNappend(r, curval, false) != GDK_SUCCEED) \ |
468 | goto allocation_error; \ |
469 | if (atomcmp(curval, nil) == 0) \ |
470 | has_nils = true; \ |
471 | } \ |
472 | } while (0) |
473 | |
474 | gdk_return |
475 | GDKanalyticalnthvalue(BAT *r, BAT *b, BAT *s, BAT *e, BAT *l, const void *restrict bound, int tp1, int tp2) |
476 | { |
477 | BUN i = 0, cnt = BATcount(b); |
478 | lng *restrict start, *restrict end, nth = 0; |
479 | bool has_nils = false; |
480 | const void *restrict nil = ATOMnilptr(tp1); |
481 | int (*atomcmp) (const void *, const void *) = ATOMcompare(tp1); |
482 | void *curval; |
483 | |
484 | assert(s && e && ((l && !bound) || (!l && bound))); |
485 | start = (lng *) Tloc(s, 0); |
486 | end = (lng *) Tloc(e, 0); |
487 | |
488 | if (bound) { |
489 | switch (tp2) { |
490 | case TYPE_bte:{ |
491 | bte val = *(bte *) bound; |
492 | nth = !is_bte_nil(val) ? (lng) val : lng_nil; |
493 | } break; |
494 | case TYPE_sht:{ |
495 | sht val = *(sht *) bound; |
496 | nth = !is_sht_nil(val) ? (lng) val : lng_nil; |
497 | } break; |
498 | case TYPE_int:{ |
499 | int val = *(int *) bound; |
500 | nth = !is_int_nil(val) ? (lng) val : lng_nil; |
501 | } break; |
502 | case TYPE_lng:{ |
503 | nth = *(lng *) bound; |
504 | } break; |
505 | #ifdef HAVE_HGE |
506 | case TYPE_hge:{ |
507 | hge nval = *(hge *) bound; |
508 | nth = is_hge_nil(nval) ? lng_nil : (nval > (hge) GDK_lng_max) ? GDK_lng_max : (lng) nval; |
509 | } break; |
510 | #endif |
511 | default: |
512 | goto nosupport; |
513 | } |
514 | switch (tp1) { |
515 | case TYPE_bit: |
516 | ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(bit); |
517 | break; |
518 | case TYPE_bte: |
519 | ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(bte); |
520 | break; |
521 | case TYPE_sht: |
522 | ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(sht); |
523 | break; |
524 | case TYPE_int: |
525 | ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(int); |
526 | break; |
527 | case TYPE_lng: |
528 | ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(lng); |
529 | break; |
530 | #ifdef HAVE_HGE |
531 | case TYPE_hge: |
532 | ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(hge); |
533 | break; |
534 | #endif |
535 | case TYPE_flt: |
536 | ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(flt); |
537 | break; |
538 | case TYPE_dbl: |
539 | ANALYTICAL_NTHVALUE_IMP_SINGLE_FIXED(dbl); |
540 | break; |
541 | default:{ |
542 | BATiter bpi = bat_iterator(b); |
543 | if (is_lng_nil(nth)) { |
544 | has_nils = true; |
545 | for (; i < cnt; i++) |
546 | if (BUNappend(r, nil, false) != GDK_SUCCEED) |
547 | goto allocation_error; |
548 | } else { |
549 | nth--; |
550 | for (; i < cnt; i++) { |
551 | curval = (end[i] > start[i] && nth < (end[i] - start[i])) ? BUNtail(bpi, (BUN) (start[i] + nth)) : (void *) nil; |
552 | if (BUNappend(r, curval, false) != GDK_SUCCEED) |
553 | goto allocation_error; |
554 | if (atomcmp(curval, nil) == 0) |
555 | has_nils = true; |
556 | } |
557 | } |
558 | } |
559 | } |
560 | } else { |
561 | switch (tp1) { |
562 | case TYPE_bit: |
563 | ANALYTICAL_NTHVALUE_CALC_FIXED(bit); |
564 | break; |
565 | case TYPE_bte: |
566 | ANALYTICAL_NTHVALUE_CALC_FIXED(bte); |
567 | break; |
568 | case TYPE_sht: |
569 | ANALYTICAL_NTHVALUE_CALC_FIXED(sht); |
570 | break; |
571 | case TYPE_int: |
572 | ANALYTICAL_NTHVALUE_CALC_FIXED(int); |
573 | break; |
574 | case TYPE_lng: |
575 | ANALYTICAL_NTHVALUE_CALC_FIXED(lng); |
576 | break; |
577 | #ifdef HAVE_HGE |
578 | case TYPE_hge: |
579 | ANALYTICAL_NTHVALUE_CALC_FIXED(hge); |
580 | break; |
581 | #endif |
582 | case TYPE_flt: |
583 | ANALYTICAL_NTHVALUE_CALC_FIXED(flt); |
584 | break; |
585 | case TYPE_dbl: |
586 | ANALYTICAL_NTHVALUE_CALC_FIXED(dbl); |
587 | break; |
588 | default:{ |
589 | BATiter bpi = bat_iterator(b); |
590 | switch (tp2) { |
591 | case TYPE_bte: |
592 | ANALYTICAL_NTHVALUE_IMP_MULTI_VARSIZED(bte, lng); |
593 | break; |
594 | case TYPE_sht: |
595 | ANALYTICAL_NTHVALUE_IMP_MULTI_VARSIZED(sht, lng); |
596 | break; |
597 | case TYPE_int: |
598 | ANALYTICAL_NTHVALUE_IMP_MULTI_VARSIZED(int, lng); |
599 | break; |
600 | case TYPE_lng: |
601 | ANALYTICAL_NTHVALUE_IMP_MULTI_VARSIZED(lng, lng); |
602 | break; |
603 | #ifdef HAVE_HGE |
604 | case TYPE_hge: |
605 | ANALYTICAL_NTHVALUE_IMP_MULTI_VARSIZED(hge, hge); |
606 | break; |
607 | #endif |
608 | default: |
609 | goto nosupport; |
610 | } |
611 | } |
612 | } |
613 | } |
614 | BATsetcount(r, cnt); |
615 | r->tnonil = !has_nils; |
616 | r->tnil = has_nils; |
617 | return GDK_SUCCEED; |
618 | allocation_error: |
619 | GDKerror("GDKanalyticalnthvalue: malloc failure\n" ); |
620 | return GDK_FAIL; |
621 | nosupport: |
622 | GDKerror("GDKanalyticalnthvalue: type %s not supported for the nth_value.\n" , ATOMname(tp2)); |
623 | return GDK_FAIL; |
624 | } |
625 | |
626 | #define ANALYTICAL_LAG_CALC(TPE) \ |
627 | do { \ |
628 | for (i = 0; i < lag && rb < rp; i++, rb++) \ |
629 | *rb = def; \ |
630 | if (lag > 0 && is_##TPE##_nil(def)) \ |
631 | has_nils = true; \ |
632 | for (; rb < rp; rb++, bp++) { \ |
633 | next = *bp; \ |
634 | *rb = next; \ |
635 | if (is_##TPE##_nil(next)) \ |
636 | has_nils = true; \ |
637 | } \ |
638 | } while (0) |
639 | |
640 | #define ANALYTICAL_LAG_IMP(TPE) \ |
641 | do { \ |
642 | TPE *rp, *rb, *bp, *nbp, *rend, \ |
643 | def = *((TPE *) default_value), next; \ |
644 | bp = (TPE*)Tloc(b, 0); \ |
645 | rb = rp = (TPE*)Tloc(r, 0); \ |
646 | rend = rb + cnt; \ |
647 | if (lag == BUN_NONE) { \ |
648 | has_nils = true; \ |
649 | for (; rb < rend; rb++) \ |
650 | *rb = TPE##_nil; \ |
651 | } else if (p) { \ |
652 | pnp = np = (bit*)Tloc(p, 0); \ |
653 | end = np + cnt; \ |
654 | for (; np < end; np++) { \ |
655 | if (*np) { \ |
656 | ncnt = (np - pnp); \ |
657 | rp += ncnt; \ |
658 | nbp = bp + ncnt; \ |
659 | ANALYTICAL_LAG_CALC(TPE); \ |
660 | bp = nbp; \ |
661 | pnp = np; \ |
662 | } \ |
663 | } \ |
664 | rp += (np - pnp); \ |
665 | ANALYTICAL_LAG_CALC(TPE); \ |
666 | } else { \ |
667 | rp += cnt; \ |
668 | ANALYTICAL_LAG_CALC(TPE); \ |
669 | } \ |
670 | } while (0) |
671 | |
672 | #define ANALYTICAL_LAG_OTHERS \ |
673 | do { \ |
674 | for (i = 0; i < lag && k < j; i++, k++) { \ |
675 | if (BUNappend(r, default_value, false) != GDK_SUCCEED) \ |
676 | goto allocation_error; \ |
677 | } \ |
678 | if (lag > 0 && atomcmp(default_value, nil) == 0) \ |
679 | has_nils = true; \ |
680 | for (l = k - lag; k < j; k++, l++) { \ |
681 | curval = BUNtail(bpi, l); \ |
682 | if (BUNappend(r, curval, false) != GDK_SUCCEED) \ |
683 | goto allocation_error; \ |
684 | if (atomcmp(curval, nil) == 0) \ |
685 | has_nils = true; \ |
686 | } \ |
687 | } while (0) |
688 | |
689 | gdk_return |
690 | GDKanalyticallag(BAT *r, BAT *b, BAT *p, BUN lag, const void *restrict default_value, int tpe) |
691 | { |
692 | int (*atomcmp) (const void *, const void *); |
693 | const void *restrict nil; |
694 | BUN i = 0, j = 0, k = 0, l = 0, ncnt, cnt = BATcount(b); |
695 | bit *np, *pnp, *end; |
696 | bool has_nils = false; |
697 | |
698 | assert(default_value); |
699 | |
700 | switch (tpe) { |
701 | case TYPE_bit: |
702 | ANALYTICAL_LAG_IMP(bit); |
703 | break; |
704 | case TYPE_bte: |
705 | ANALYTICAL_LAG_IMP(bte); |
706 | break; |
707 | case TYPE_sht: |
708 | ANALYTICAL_LAG_IMP(sht); |
709 | break; |
710 | case TYPE_int: |
711 | ANALYTICAL_LAG_IMP(int); |
712 | break; |
713 | case TYPE_lng: |
714 | ANALYTICAL_LAG_IMP(lng); |
715 | break; |
716 | #ifdef HAVE_HGE |
717 | case TYPE_hge: |
718 | ANALYTICAL_LAG_IMP(hge); |
719 | break; |
720 | #endif |
721 | case TYPE_flt: |
722 | ANALYTICAL_LAG_IMP(flt); |
723 | break; |
724 | case TYPE_dbl: |
725 | ANALYTICAL_LAG_IMP(dbl); |
726 | break; |
727 | default:{ |
728 | BATiter bpi = bat_iterator(b); |
729 | const void *restrict curval; |
730 | nil = ATOMnilptr(tpe); |
731 | atomcmp = ATOMcompare(tpe); |
732 | if (lag == BUN_NONE) { |
733 | has_nils = true; |
734 | for (j = 0; j < cnt; j++) { |
735 | if (BUNappend(r, nil, false) != GDK_SUCCEED) |
736 | goto allocation_error; |
737 | } |
738 | } else if (p) { |
739 | pnp = np = (bit *) Tloc(p, 0); |
740 | end = np + cnt; |
741 | for (; np < end; np++) { |
742 | if (*np) { |
743 | j += (np - pnp); |
744 | ANALYTICAL_LAG_OTHERS; |
745 | pnp = np; |
746 | } |
747 | } |
748 | j += (np - pnp); |
749 | ANALYTICAL_LAG_OTHERS; |
750 | } else { |
751 | j += cnt; |
752 | ANALYTICAL_LAG_OTHERS; |
753 | } |
754 | } |
755 | } |
756 | BATsetcount(r, cnt); |
757 | r->tnonil = !has_nils; |
758 | r->tnil = has_nils; |
759 | return GDK_SUCCEED; |
760 | allocation_error: |
761 | GDKerror("GDKanalyticallag: malloc failure\n" ); |
762 | return GDK_FAIL; |
763 | } |
764 | |
765 | #define LEAD_CALC(TPE) \ |
766 | do { \ |
767 | if (lead < ncnt) { \ |
768 | bp += lead; \ |
769 | l = ncnt - lead; \ |
770 | for (i = 0; i < l; i++, rb++, bp++) { \ |
771 | next = *bp; \ |
772 | *rb = next; \ |
773 | if (is_##TPE##_nil(next)) \ |
774 | has_nils = true; \ |
775 | } \ |
776 | } else { \ |
777 | bp += ncnt; \ |
778 | } \ |
779 | for (;rb < rp; rb++) \ |
780 | *rb = def; \ |
781 | if (lead > 0 && is_##TPE##_nil(def)) \ |
782 | has_nils = true; \ |
783 | } while (0) |
784 | |
785 | #define ANALYTICAL_LEAD_IMP(TPE) \ |
786 | do { \ |
787 | TPE *rp, *rb, *bp, *rend, \ |
788 | def = *((TPE *) default_value), next; \ |
789 | bp = (TPE*)Tloc(b, 0); \ |
790 | rb = rp = (TPE*)Tloc(r, 0); \ |
791 | rend = rb + cnt; \ |
792 | if (lead == BUN_NONE) { \ |
793 | has_nils = true; \ |
794 | for (; rb < rend; rb++) \ |
795 | *rb = TPE##_nil; \ |
796 | } else if (p) { \ |
797 | pnp = np = (bit*)Tloc(p, 0); \ |
798 | end = np + cnt; \ |
799 | for (; np < end; np++) { \ |
800 | if (*np) { \ |
801 | ncnt = (np - pnp); \ |
802 | rp += ncnt; \ |
803 | LEAD_CALC(TPE); \ |
804 | pnp = np; \ |
805 | } \ |
806 | } \ |
807 | ncnt = (np - pnp); \ |
808 | rp += ncnt; \ |
809 | LEAD_CALC(TPE); \ |
810 | } else { \ |
811 | ncnt = cnt; \ |
812 | rp += ncnt; \ |
813 | LEAD_CALC(TPE); \ |
814 | } \ |
815 | } while (0) |
816 | |
817 | #define ANALYTICAL_LEAD_OTHERS \ |
818 | do { \ |
819 | j += ncnt; \ |
820 | if (lead < ncnt) { \ |
821 | m = ncnt - lead; \ |
822 | for (i = 0,n = k + lead; i < m; i++, n++) { \ |
823 | curval = BUNtail(bpi, n); \ |
824 | if (BUNappend(r, curval, false) != GDK_SUCCEED) \ |
825 | goto allocation_error; \ |
826 | if (atomcmp(curval, nil) == 0) \ |
827 | has_nils = true; \ |
828 | } \ |
829 | k += i; \ |
830 | } \ |
831 | for (; k < j; k++) { \ |
832 | if (BUNappend(r, default_value, false) != GDK_SUCCEED) \ |
833 | goto allocation_error; \ |
834 | } \ |
835 | if (lead > 0 && atomcmp(default_value, nil) == 0) \ |
836 | has_nils = true; \ |
837 | } while (0) |
838 | |
839 | gdk_return |
840 | GDKanalyticallead(BAT *r, BAT *b, BAT *p, BUN lead, const void *restrict default_value, int tpe) |
841 | { |
842 | int (*atomcmp) (const void *, const void *); |
843 | const void *restrict nil; |
844 | BUN i = 0, j = 0, k = 0, l = 0, ncnt, cnt = BATcount(b); |
845 | bit *np, *pnp, *end; |
846 | bool has_nils = false; |
847 | |
848 | assert(default_value); |
849 | |
850 | switch (tpe) { |
851 | case TYPE_bit: |
852 | ANALYTICAL_LEAD_IMP(bit); |
853 | break; |
854 | case TYPE_bte: |
855 | ANALYTICAL_LEAD_IMP(bte); |
856 | break; |
857 | case TYPE_sht: |
858 | ANALYTICAL_LEAD_IMP(sht); |
859 | break; |
860 | case TYPE_int: |
861 | ANALYTICAL_LEAD_IMP(int); |
862 | break; |
863 | case TYPE_lng: |
864 | ANALYTICAL_LEAD_IMP(lng); |
865 | break; |
866 | #ifdef HAVE_HGE |
867 | case TYPE_hge: |
868 | ANALYTICAL_LEAD_IMP(hge); |
869 | break; |
870 | #endif |
871 | case TYPE_flt: |
872 | ANALYTICAL_LEAD_IMP(flt); |
873 | break; |
874 | case TYPE_dbl: |
875 | ANALYTICAL_LEAD_IMP(dbl); |
876 | break; |
877 | default:{ |
878 | BUN m = 0, n = 0; |
879 | BATiter bpi = bat_iterator(b); |
880 | const void *restrict curval; |
881 | nil = ATOMnilptr(tpe); |
882 | atomcmp = ATOMcompare(tpe); |
883 | if (lead == BUN_NONE) { |
884 | has_nils = true; |
885 | for (j = 0; j < cnt; j++) { |
886 | if (BUNappend(r, nil, false) != GDK_SUCCEED) |
887 | goto allocation_error; |
888 | } |
889 | } else if (p) { |
890 | pnp = np = (bit *) Tloc(p, 0); |
891 | end = np + cnt; |
892 | for (; np < end; np++) { |
893 | if (*np) { |
894 | ncnt = (np - pnp); |
895 | ANALYTICAL_LEAD_OTHERS; |
896 | pnp = np; |
897 | } |
898 | } |
899 | ncnt = (np - pnp); |
900 | ANALYTICAL_LEAD_OTHERS; |
901 | } else { |
902 | ncnt = cnt; |
903 | ANALYTICAL_LEAD_OTHERS; |
904 | } |
905 | } |
906 | } |
907 | BATsetcount(r, cnt); |
908 | r->tnonil = !has_nils; |
909 | r->tnil = has_nils; |
910 | return GDK_SUCCEED; |
911 | allocation_error: |
912 | GDKerror("GDKanalyticallead: malloc failure\n" ); |
913 | return GDK_FAIL; |
914 | } |
915 | |
916 | #define ANALYTICAL_MIN_MAX_CALC(TPE, OP) \ |
917 | do { \ |
918 | TPE *bp = (TPE*)Tloc(b, 0), *bs, *be, v, \ |
919 | curval = TPE##_nil, *restrict rb = (TPE*)Tloc(r, 0); \ |
920 | for (; i < cnt; i++, rb++) { \ |
921 | bs = bp + start[i]; \ |
922 | be = bp + end[i]; \ |
923 | for (; bs < be; bs++) { \ |
924 | v = *bs; \ |
925 | if (!is_##TPE##_nil(v)) { \ |
926 | if (is_##TPE##_nil(curval)) \ |
927 | curval = v; \ |
928 | else \ |
929 | curval = OP(v, curval); \ |
930 | } \ |
931 | } \ |
932 | *rb = curval; \ |
933 | if (is_##TPE##_nil(curval)) \ |
934 | has_nils = true; \ |
935 | else \ |
936 | curval = TPE##_nil; \ |
937 | } \ |
938 | } while (0) |
939 | |
940 | #ifdef HAVE_HGE |
941 | #define ANALYTICAL_MIN_MAX_LIMIT(OP) \ |
942 | case TYPE_hge: \ |
943 | ANALYTICAL_MIN_MAX_CALC(hge, OP); \ |
944 | break; |
945 | #else |
946 | #define ANALYTICAL_MIN_MAX_LIMIT(OP) |
947 | #endif |
948 | |
949 | #define ANALYTICAL_MIN_MAX(OP, IMP, SIGN_OP) \ |
950 | gdk_return \ |
951 | GDKanalytical##OP(BAT *r, BAT *b, BAT *s, BAT *e, int tpe) \ |
952 | { \ |
953 | bool has_nils = false; \ |
954 | BUN i = 0, cnt = BATcount(b); \ |
955 | lng *restrict start, *restrict end, j = 0, l = 0; \ |
956 | \ |
957 | assert(s && e); \ |
958 | start = (lng*)Tloc(s, 0); \ |
959 | end = (lng*)Tloc(e, 0); \ |
960 | \ |
961 | switch (tpe) { \ |
962 | case TYPE_bit: \ |
963 | ANALYTICAL_MIN_MAX_CALC(bit, IMP); \ |
964 | break; \ |
965 | case TYPE_bte: \ |
966 | ANALYTICAL_MIN_MAX_CALC(bte, IMP); \ |
967 | break; \ |
968 | case TYPE_sht: \ |
969 | ANALYTICAL_MIN_MAX_CALC(sht, IMP); \ |
970 | break; \ |
971 | case TYPE_int: \ |
972 | ANALYTICAL_MIN_MAX_CALC(int, IMP); \ |
973 | break; \ |
974 | case TYPE_lng: \ |
975 | ANALYTICAL_MIN_MAX_CALC(lng, IMP); \ |
976 | break; \ |
977 | ANALYTICAL_MIN_MAX_LIMIT(IMP) \ |
978 | case TYPE_flt: \ |
979 | ANALYTICAL_MIN_MAX_CALC(flt, IMP); \ |
980 | break; \ |
981 | case TYPE_dbl: \ |
982 | ANALYTICAL_MIN_MAX_CALC(dbl, IMP); \ |
983 | break; \ |
984 | default: { \ |
985 | BATiter bpi = bat_iterator(b); \ |
986 | const void *nil = ATOMnilptr(tpe); \ |
987 | int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe); \ |
988 | void *curval; \ |
989 | for (; i < cnt; i++) { \ |
990 | j = start[i]; \ |
991 | l = end[i]; \ |
992 | curval = (void*)nil; \ |
993 | for (;j < l; j++) { \ |
994 | void *next = BUNtail(bpi, (BUN) j); \ |
995 | if (atomcmp(next, nil) != 0) { \ |
996 | if (atomcmp(curval, nil) == 0) \ |
997 | curval = next; \ |
998 | else \ |
999 | curval = atomcmp(next, curval) SIGN_OP 0 ? curval : next; \ |
1000 | } \ |
1001 | } \ |
1002 | if (BUNappend(r, curval, false) != GDK_SUCCEED) \ |
1003 | goto allocation_error; \ |
1004 | if (atomcmp(curval, nil) == 0) \ |
1005 | has_nils = true; \ |
1006 | } \ |
1007 | } \ |
1008 | } \ |
1009 | BATsetcount(r, cnt); \ |
1010 | r->tnonil = !has_nils; \ |
1011 | r->tnil = has_nils; \ |
1012 | return GDK_SUCCEED; \ |
1013 | allocation_error: \ |
1014 | GDKerror("GDKanalytical""OP"": malloc failure\n"); \ |
1015 | return GDK_FAIL; \ |
1016 | } |
1017 | |
1018 | ANALYTICAL_MIN_MAX(min, MIN, >) |
1019 | ANALYTICAL_MIN_MAX(max, MAX, <) |
1020 | |
1021 | #define ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(TPE) \ |
1022 | do { \ |
1023 | TPE *bp, *bs, *be; \ |
1024 | bp = (TPE*)Tloc(b, 0); \ |
1025 | for (; i < cnt; i++, rb++) { \ |
1026 | bs = bp + start[i]; \ |
1027 | be = bp + end[i]; \ |
1028 | for (; bs < be; bs++) \ |
1029 | curval += !is_##TPE##_nil(*bs); \ |
1030 | *rb = curval; \ |
1031 | curval = 0; \ |
1032 | } \ |
1033 | } while (0) |
1034 | |
1035 | #define ANALYTICAL_COUNT_NO_NIL_STR_IMP(TPE_CAST, OFFSET) \ |
1036 | do { \ |
1037 | for (; i < cnt; i++, rb++) { \ |
1038 | j = start[i]; \ |
1039 | l = end[i]; \ |
1040 | for (; j < l; j++) \ |
1041 | curval += base[(var_t) ((TPE_CAST) bp) OFFSET] != '\200'; \ |
1042 | *rb = curval; \ |
1043 | curval = 0; \ |
1044 | } \ |
1045 | } while (0) |
1046 | |
1047 | gdk_return |
1048 | GDKanalyticalcount(BAT *r, BAT *b, BAT *s, BAT *e, const bit *restrict ignore_nils, int tpe) |
1049 | { |
1050 | BUN i = 0, cnt = BATcount(b); |
1051 | lng *restrict rb = (lng *) Tloc(r, 0), *restrict start, *restrict end, curval = 0, j = 0, l = 0; |
1052 | |
1053 | assert(s && e && ignore_nils); |
1054 | start = (lng *) Tloc(s, 0); |
1055 | end = (lng *) Tloc(e, 0); |
1056 | |
1057 | if (!*ignore_nils || b->tnonil) { |
1058 | for (; i < cnt; i++, rb++) |
1059 | *rb = (end[i] > start[i]) ? (end[i] - start[i]) : 0; |
1060 | } else { |
1061 | switch (tpe) { |
1062 | case TYPE_bit: |
1063 | ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(bit); |
1064 | break; |
1065 | case TYPE_bte: |
1066 | ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(bte); |
1067 | break; |
1068 | case TYPE_sht: |
1069 | ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(sht); |
1070 | break; |
1071 | case TYPE_int: |
1072 | ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(int); |
1073 | break; |
1074 | case TYPE_lng: |
1075 | ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(lng); |
1076 | break; |
1077 | #ifdef HAVE_HGE |
1078 | case TYPE_hge: |
1079 | ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(hge); |
1080 | break; |
1081 | #endif |
1082 | case TYPE_flt: |
1083 | ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(flt); |
1084 | break; |
1085 | case TYPE_dbl: |
1086 | ANALYTICAL_COUNT_NO_NIL_FIXED_SIZE_IMP(dbl); |
1087 | break; |
1088 | case TYPE_str:{ |
1089 | const char *restrict base = b->tvheap->base; |
1090 | const void *restrict bp = Tloc(b, 0); |
1091 | switch (b->twidth) { |
1092 | case 1: |
1093 | ANALYTICAL_COUNT_NO_NIL_STR_IMP(const unsigned char *,[j] + GDK_VAROFFSET); |
1094 | break; |
1095 | case 2: |
1096 | ANALYTICAL_COUNT_NO_NIL_STR_IMP(const unsigned short *,[j] + GDK_VAROFFSET); |
1097 | break; |
1098 | #if SIZEOF_VAR_T != SIZEOF_INT |
1099 | case 4: |
1100 | ANALYTICAL_COUNT_NO_NIL_STR_IMP(const unsigned int *,[j]); |
1101 | break; |
1102 | #endif |
1103 | default: |
1104 | ANALYTICAL_COUNT_NO_NIL_STR_IMP(const var_t *,[j]); |
1105 | break; |
1106 | } |
1107 | break; |
1108 | } |
1109 | default:{ |
1110 | const void *restrict nil = ATOMnilptr(tpe); |
1111 | int (*cmp) (const void *, const void *) = ATOMcompare(tpe); |
1112 | if (b->tvarsized) { |
1113 | const char *restrict base = b->tvheap->base; |
1114 | const void *restrict bp = Tloc(b, 0); |
1115 | for (; i < cnt; i++, rb++) { |
1116 | j = start[i]; |
1117 | l = end[i]; |
1118 | for (; j < l; j++) |
1119 | curval += cmp(nil, base + ((const var_t *) bp)[j]) != 0; |
1120 | *rb = curval; |
1121 | curval = 0; |
1122 | } |
1123 | } else { |
1124 | for (; i < cnt; i++, rb++) { |
1125 | j = start[i]; |
1126 | l = end[i]; |
1127 | for (; j < l; j++) |
1128 | curval += cmp(Tloc(b, j), nil) != 0; |
1129 | *rb = curval; |
1130 | curval = 0; |
1131 | } |
1132 | } |
1133 | } |
1134 | } |
1135 | } |
1136 | BATsetcount(r, cnt); |
1137 | r->tnonil = true; |
1138 | r->tnil = false; |
1139 | return GDK_SUCCEED; |
1140 | } |
1141 | |
1142 | #define ANALYTICAL_SUM_IMP_NUM(TPE1, TPE2) \ |
1143 | do { \ |
1144 | TPE1 *bs, *be, v; \ |
1145 | for (; i < cnt; i++, rb++) { \ |
1146 | bs = bp + start[i]; \ |
1147 | be = bp + end[i]; \ |
1148 | for (; bs < be; bs++) { \ |
1149 | v = *bs; \ |
1150 | if (!is_##TPE1##_nil(v)) { \ |
1151 | if (is_##TPE2##_nil(curval)) \ |
1152 | curval = (TPE2) v; \ |
1153 | else \ |
1154 | ADD_WITH_CHECK(v, curval, TPE2, curval, GDK_##TPE2##_max, goto calc_overflow); \ |
1155 | } \ |
1156 | } \ |
1157 | *rb = curval; \ |
1158 | if (is_##TPE2##_nil(curval)) \ |
1159 | has_nils = true; \ |
1160 | else \ |
1161 | curval = TPE2##_nil; \ |
1162 | } \ |
1163 | } while (0) |
1164 | |
1165 | #define ANALYTICAL_SUM_IMP_FP(TPE1, TPE2) \ |
1166 | do { \ |
1167 | TPE1 *bs; \ |
1168 | BUN parcel; \ |
1169 | for (; i < cnt; i++, rb++) { \ |
1170 | if (end[i] > start[i]) { \ |
1171 | bs = bp + start[i]; \ |
1172 | parcel = (BUN)(end[i] - start[i]); \ |
1173 | if (dofsum(bs, 0, \ |
1174 | &(struct canditer){.tpe = cand_dense, .ncand = parcel,}, \ |
1175 | parcel, &curval, 1, TYPE_##TPE1, \ |
1176 | TYPE_##TPE2, NULL, 0, 0, true, \ |
1177 | false, true) == BUN_NONE) { \ |
1178 | goto bailout; \ |
1179 | } \ |
1180 | } \ |
1181 | *rb = curval; \ |
1182 | if (is_##TPE2##_nil(curval)) \ |
1183 | has_nils = true; \ |
1184 | else \ |
1185 | curval = TPE2##_nil; \ |
1186 | } \ |
1187 | } while (0) |
1188 | |
1189 | #define ANALYTICAL_SUM_CALC(TPE1, TPE2, IMP) \ |
1190 | do { \ |
1191 | TPE1 *bp = (TPE1*)Tloc(b, 0); \ |
1192 | TPE2 *restrict rb, curval = TPE2##_nil; \ |
1193 | rb = (TPE2*)Tloc(r, 0); \ |
1194 | IMP(TPE1, TPE2); \ |
1195 | } while (0) |
1196 | |
1197 | gdk_return |
1198 | GDKanalyticalsum(BAT *r, BAT *b, BAT *s, BAT *e, int tp1, int tp2) |
1199 | { |
1200 | bool has_nils = false; |
1201 | BUN i = 0, cnt = BATcount(b), nils = 0; |
1202 | int abort_on_error = 1; |
1203 | lng *restrict start, *restrict end; |
1204 | |
1205 | assert(s && e); |
1206 | start = (lng *) Tloc(s, 0); |
1207 | end = (lng *) Tloc(e, 0); |
1208 | |
1209 | switch (tp2) { |
1210 | case TYPE_bte:{ |
1211 | switch (tp1) { |
1212 | case TYPE_bte: |
1213 | ANALYTICAL_SUM_CALC(bte, bte, ANALYTICAL_SUM_IMP_NUM); |
1214 | break; |
1215 | default: |
1216 | goto nosupport; |
1217 | } |
1218 | break; |
1219 | } |
1220 | case TYPE_sht:{ |
1221 | switch (tp1) { |
1222 | case TYPE_bte: |
1223 | ANALYTICAL_SUM_CALC(bte, sht, ANALYTICAL_SUM_IMP_NUM); |
1224 | break; |
1225 | case TYPE_sht: |
1226 | ANALYTICAL_SUM_CALC(sht, sht, ANALYTICAL_SUM_IMP_NUM); |
1227 | break; |
1228 | default: |
1229 | goto nosupport; |
1230 | } |
1231 | break; |
1232 | } |
1233 | case TYPE_int:{ |
1234 | switch (tp1) { |
1235 | case TYPE_bte: |
1236 | ANALYTICAL_SUM_CALC(bte, int, ANALYTICAL_SUM_IMP_NUM); |
1237 | break; |
1238 | case TYPE_sht: |
1239 | ANALYTICAL_SUM_CALC(sht, int, ANALYTICAL_SUM_IMP_NUM); |
1240 | break; |
1241 | case TYPE_int: |
1242 | ANALYTICAL_SUM_CALC(int, int, ANALYTICAL_SUM_IMP_NUM); |
1243 | break; |
1244 | default: |
1245 | goto nosupport; |
1246 | } |
1247 | break; |
1248 | } |
1249 | case TYPE_lng:{ |
1250 | switch (tp1) { |
1251 | case TYPE_bte: |
1252 | ANALYTICAL_SUM_CALC(bte, lng, ANALYTICAL_SUM_IMP_NUM); |
1253 | break; |
1254 | case TYPE_sht: |
1255 | ANALYTICAL_SUM_CALC(sht, lng, ANALYTICAL_SUM_IMP_NUM); |
1256 | break; |
1257 | case TYPE_int: |
1258 | ANALYTICAL_SUM_CALC(int, lng, ANALYTICAL_SUM_IMP_NUM); |
1259 | break; |
1260 | case TYPE_lng: |
1261 | ANALYTICAL_SUM_CALC(lng, lng, ANALYTICAL_SUM_IMP_NUM); |
1262 | break; |
1263 | default: |
1264 | goto nosupport; |
1265 | } |
1266 | break; |
1267 | } |
1268 | #ifdef HAVE_HGE |
1269 | case TYPE_hge:{ |
1270 | switch (tp1) { |
1271 | case TYPE_bte: |
1272 | ANALYTICAL_SUM_CALC(bte, hge, ANALYTICAL_SUM_IMP_NUM); |
1273 | break; |
1274 | case TYPE_sht: |
1275 | ANALYTICAL_SUM_CALC(sht, hge, ANALYTICAL_SUM_IMP_NUM); |
1276 | break; |
1277 | case TYPE_int: |
1278 | ANALYTICAL_SUM_CALC(int, hge, ANALYTICAL_SUM_IMP_NUM); |
1279 | break; |
1280 | case TYPE_lng: |
1281 | ANALYTICAL_SUM_CALC(lng, hge, ANALYTICAL_SUM_IMP_NUM); |
1282 | break; |
1283 | case TYPE_hge: |
1284 | ANALYTICAL_SUM_CALC(hge, hge, ANALYTICAL_SUM_IMP_NUM); |
1285 | break; |
1286 | default: |
1287 | goto nosupport; |
1288 | } |
1289 | break; |
1290 | } |
1291 | #endif |
1292 | case TYPE_flt:{ |
1293 | switch (tp1) { |
1294 | case TYPE_flt: |
1295 | ANALYTICAL_SUM_CALC(flt, flt, ANALYTICAL_SUM_IMP_FP); |
1296 | break; |
1297 | default: |
1298 | goto nosupport; |
1299 | } |
1300 | break; |
1301 | } |
1302 | case TYPE_dbl:{ |
1303 | switch (tp1) { |
1304 | case TYPE_flt: |
1305 | ANALYTICAL_SUM_CALC(flt, dbl, ANALYTICAL_SUM_IMP_FP); |
1306 | break; |
1307 | case TYPE_dbl: |
1308 | ANALYTICAL_SUM_CALC(dbl, dbl, ANALYTICAL_SUM_IMP_FP); |
1309 | break; |
1310 | default: |
1311 | goto nosupport; |
1312 | } |
1313 | break; |
1314 | } |
1315 | default: |
1316 | goto nosupport; |
1317 | } |
1318 | BATsetcount(r, cnt); |
1319 | r->tnonil = !has_nils; |
1320 | r->tnil = has_nils; |
1321 | return GDK_SUCCEED; |
1322 | bailout: |
1323 | GDKerror("GDKanalyticalsum: error while calculating floating-point sum\n" ); |
1324 | return GDK_FAIL; |
1325 | nosupport: |
1326 | GDKerror("GDKanalyticalsum: type combination (sum(%s)->%s) not supported.\n" , ATOMname(tp1), ATOMname(tp2)); |
1327 | return GDK_FAIL; |
1328 | calc_overflow: |
1329 | GDKerror("22003!overflow in calculation.\n" ); |
1330 | return GDK_FAIL; |
1331 | } |
1332 | |
1333 | #define ANALYTICAL_PROD_CALC_NUM(TPE1, TPE2, TPE3) \ |
1334 | do { \ |
1335 | TPE1 *bp = (TPE1*)Tloc(b, 0), *bs, *be, v; \ |
1336 | TPE2 *restrict rb, curval = TPE2##_nil; \ |
1337 | rb = (TPE2*)Tloc(r, 0); \ |
1338 | for (; i < cnt; i++, rb++) { \ |
1339 | bs = bp + start[i]; \ |
1340 | be = bp + end[i]; \ |
1341 | for (; bs < be; bs++) { \ |
1342 | v = *bs; \ |
1343 | if (!is_##TPE1##_nil(v)) { \ |
1344 | if (is_##TPE2##_nil(curval)) \ |
1345 | curval = (TPE2) v; \ |
1346 | else \ |
1347 | MUL4_WITH_CHECK(v, curval, TPE2, curval, GDK_##TPE2##_max, TPE3, \ |
1348 | goto calc_overflow); \ |
1349 | } \ |
1350 | } \ |
1351 | *rb = curval; \ |
1352 | if (is_##TPE2##_nil(curval)) \ |
1353 | has_nils = true; \ |
1354 | else \ |
1355 | curval = TPE2##_nil; \ |
1356 | } \ |
1357 | } while (0) |
1358 | |
1359 | #define ANALYTICAL_PROD_CALC_NUM_LIMIT(TPE1, TPE2, REAL_IMP) \ |
1360 | do { \ |
1361 | TPE1 *bp = (TPE1*)Tloc(b, 0), *bs, *be, v; \ |
1362 | TPE2 *restrict rb, curval = TPE2##_nil; \ |
1363 | rb = (TPE2*)Tloc(r, 0); \ |
1364 | for (; i < cnt; i++, rb++) { \ |
1365 | bs = bp + start[i]; \ |
1366 | be = bp + end[i]; \ |
1367 | for (; bs < be; bs++) { \ |
1368 | v = *bs; \ |
1369 | if (!is_##TPE1##_nil(v)) { \ |
1370 | if (is_##TPE2##_nil(curval)) \ |
1371 | curval = (TPE2) v; \ |
1372 | else \ |
1373 | REAL_IMP(v, curval, curval, GDK_##TPE2##_max, goto calc_overflow); \ |
1374 | } \ |
1375 | } \ |
1376 | *rb = curval; \ |
1377 | if (is_##TPE2##_nil(curval)) \ |
1378 | has_nils = true; \ |
1379 | else \ |
1380 | curval = TPE2##_nil; \ |
1381 | } \ |
1382 | } while (0) |
1383 | |
1384 | #define ANALYTICAL_PROD_CALC_FP(TPE1, TPE2) \ |
1385 | do { \ |
1386 | TPE1 *bp = (TPE1*)Tloc(b, 0), *bs, *be, v; \ |
1387 | TPE2 *restrict rb, curval = TPE2##_nil; \ |
1388 | rb = (TPE2*)Tloc(r, 0); \ |
1389 | for (; i < cnt; i++, rb++) { \ |
1390 | bs = bp + start[i]; \ |
1391 | be = bp + end[i]; \ |
1392 | for (; bs < be; bs++) { \ |
1393 | v = *bs; \ |
1394 | if (!is_##TPE1##_nil(v)) { \ |
1395 | if (is_##TPE2##_nil(curval)) { \ |
1396 | curval = (TPE2) v; \ |
1397 | } else if (ABSOLUTE(curval) > 1 && GDK_##TPE2##_max / ABSOLUTE(v) < ABSOLUTE(curval)) { \ |
1398 | if (abort_on_error) \ |
1399 | goto calc_overflow; \ |
1400 | curval = TPE2##_nil; \ |
1401 | nils++; \ |
1402 | } else { \ |
1403 | curval *= v; \ |
1404 | } \ |
1405 | } \ |
1406 | } \ |
1407 | *rb = curval; \ |
1408 | if (is_##TPE2##_nil(curval)) \ |
1409 | has_nils = true; \ |
1410 | else \ |
1411 | curval = TPE2##_nil; \ |
1412 | } \ |
1413 | } while (0) |
1414 | |
1415 | gdk_return |
1416 | GDKanalyticalprod(BAT *r, BAT *b, BAT *s, BAT *e, int tp1, int tp2) |
1417 | { |
1418 | bool has_nils = false; |
1419 | BUN i = 0, cnt = BATcount(b), nils = 0; |
1420 | int abort_on_error = 1; |
1421 | lng *restrict start, *restrict end; |
1422 | |
1423 | assert(s && e); |
1424 | start = (lng *) Tloc(s, 0); |
1425 | end = (lng *) Tloc(e, 0); |
1426 | |
1427 | switch (tp2) { |
1428 | case TYPE_bte:{ |
1429 | switch (tp1) { |
1430 | case TYPE_bte: |
1431 | ANALYTICAL_PROD_CALC_NUM(bte, bte, sht); |
1432 | break; |
1433 | default: |
1434 | goto nosupport; |
1435 | } |
1436 | break; |
1437 | } |
1438 | case TYPE_sht:{ |
1439 | switch (tp1) { |
1440 | case TYPE_bte: |
1441 | ANALYTICAL_PROD_CALC_NUM(bte, sht, int); |
1442 | break; |
1443 | case TYPE_sht: |
1444 | ANALYTICAL_PROD_CALC_NUM(sht, sht, int); |
1445 | break; |
1446 | default: |
1447 | goto nosupport; |
1448 | } |
1449 | break; |
1450 | } |
1451 | case TYPE_int:{ |
1452 | switch (tp1) { |
1453 | case TYPE_bte: |
1454 | ANALYTICAL_PROD_CALC_NUM(bte, int, lng); |
1455 | break; |
1456 | case TYPE_sht: |
1457 | ANALYTICAL_PROD_CALC_NUM(sht, int, lng); |
1458 | break; |
1459 | case TYPE_int: |
1460 | ANALYTICAL_PROD_CALC_NUM(int, int, lng); |
1461 | break; |
1462 | default: |
1463 | goto nosupport; |
1464 | } |
1465 | break; |
1466 | } |
1467 | #ifdef HAVE_HGE |
1468 | case TYPE_lng:{ |
1469 | switch (tp1) { |
1470 | case TYPE_bte: |
1471 | ANALYTICAL_PROD_CALC_NUM(bte, lng, hge); |
1472 | break; |
1473 | case TYPE_sht: |
1474 | ANALYTICAL_PROD_CALC_NUM(sht, lng, hge); |
1475 | break; |
1476 | case TYPE_int: |
1477 | ANALYTICAL_PROD_CALC_NUM(int, lng, hge); |
1478 | break; |
1479 | case TYPE_lng: |
1480 | ANALYTICAL_PROD_CALC_NUM(lng, lng, hge); |
1481 | break; |
1482 | default: |
1483 | goto nosupport; |
1484 | } |
1485 | break; |
1486 | } |
1487 | case TYPE_hge:{ |
1488 | switch (tp1) { |
1489 | case TYPE_bte: |
1490 | ANALYTICAL_PROD_CALC_NUM_LIMIT(bte, hge, HGEMUL_CHECK); |
1491 | break; |
1492 | case TYPE_sht: |
1493 | ANALYTICAL_PROD_CALC_NUM_LIMIT(sht, hge, HGEMUL_CHECK); |
1494 | break; |
1495 | case TYPE_int: |
1496 | ANALYTICAL_PROD_CALC_NUM_LIMIT(int, hge, HGEMUL_CHECK); |
1497 | break; |
1498 | case TYPE_lng: |
1499 | ANALYTICAL_PROD_CALC_NUM_LIMIT(lng, hge, HGEMUL_CHECK); |
1500 | break; |
1501 | case TYPE_hge: |
1502 | ANALYTICAL_PROD_CALC_NUM_LIMIT(hge, hge, HGEMUL_CHECK); |
1503 | break; |
1504 | default: |
1505 | goto nosupport; |
1506 | } |
1507 | break; |
1508 | } |
1509 | #else |
1510 | case TYPE_lng:{ |
1511 | switch (tp1) { |
1512 | case TYPE_bte: |
1513 | ANALYTICAL_PROD_CALC_NUM_LIMIT(bte, lng, LNGMUL_CHECK); |
1514 | break; |
1515 | case TYPE_sht: |
1516 | ANALYTICAL_PROD_CALC_NUM_LIMIT(sht, lng, LNGMUL_CHECK); |
1517 | break; |
1518 | case TYPE_int: |
1519 | ANALYTICAL_PROD_CALC_NUM_LIMIT(int, lng, LNGMUL_CHECK); |
1520 | break; |
1521 | case TYPE_lng: |
1522 | ANALYTICAL_PROD_CALC_NUM_LIMIT(lng, lng, LNGMUL_CHECK); |
1523 | break; |
1524 | default: |
1525 | goto nosupport; |
1526 | } |
1527 | break; |
1528 | } |
1529 | #endif |
1530 | case TYPE_flt:{ |
1531 | switch (tp1) { |
1532 | case TYPE_flt: |
1533 | ANALYTICAL_PROD_CALC_FP(flt, flt); |
1534 | break; |
1535 | default: |
1536 | goto nosupport; |
1537 | } |
1538 | break; |
1539 | } |
1540 | case TYPE_dbl:{ |
1541 | switch (tp1) { |
1542 | case TYPE_flt: |
1543 | ANALYTICAL_PROD_CALC_FP(flt, dbl); |
1544 | break; |
1545 | case TYPE_dbl: |
1546 | ANALYTICAL_PROD_CALC_FP(dbl, dbl); |
1547 | break; |
1548 | default: |
1549 | goto nosupport; |
1550 | } |
1551 | break; |
1552 | } |
1553 | default: |
1554 | goto nosupport; |
1555 | } |
1556 | BATsetcount(r, cnt); |
1557 | r->tnonil = !has_nils; |
1558 | r->tnil = has_nils; |
1559 | return GDK_SUCCEED; |
1560 | nosupport: |
1561 | GDKerror("GDKanalyticalprod: type combination (prod(%s)->%s) not supported.\n" , ATOMname(tp1), ATOMname(tp2)); |
1562 | return GDK_FAIL; |
1563 | calc_overflow: |
1564 | GDKerror("22003!overflow in calculation.\n" ); |
1565 | return GDK_FAIL; |
1566 | } |
1567 | |
1568 | #define ANALYTICAL_AVERAGE_CALC_NUM(TPE,lng_hge) \ |
1569 | do { \ |
1570 | TPE *bp = (TPE*)Tloc(b, 0), *bs, *be, v, a = 0; \ |
1571 | for (; i < cnt; i++, rb++) { \ |
1572 | bs = bp + start[i]; \ |
1573 | be = bp + end[i]; \ |
1574 | for (; bs < be; bs++) { \ |
1575 | v = *bs; \ |
1576 | if (!is_##TPE##_nil(v)) { \ |
1577 | ADD_WITH_CHECK(v, sum, lng_hge, sum, GDK_##lng_hge##_max, goto avg_overflow##TPE); \ |
1578 | /* count only when no overflow occurs */ \ |
1579 | n++; \ |
1580 | } \ |
1581 | } \ |
1582 | if (0) { \ |
1583 | avg_overflow##TPE: \ |
1584 | assert(n > 0); \ |
1585 | if (sum >= 0) { \ |
1586 | a = (TPE) (sum / (lng_hge) n); \ |
1587 | rr = (BUN) (sum % (SBUN) n); \ |
1588 | } else { \ |
1589 | sum = -sum; \ |
1590 | a = - (TPE) (sum / (lng_hge) n); \ |
1591 | rr = (BUN) (sum % (SBUN) n); \ |
1592 | if (r) { \ |
1593 | a--; \ |
1594 | rr = n - rr; \ |
1595 | } \ |
1596 | } \ |
1597 | for (; bs < be; bs++) { \ |
1598 | v = *bs; \ |
1599 | if (is_##TPE##_nil(v)) \ |
1600 | continue; \ |
1601 | AVERAGE_ITER(TPE, v, a, rr, n); \ |
1602 | } \ |
1603 | curval = a + (dbl) rr / n; \ |
1604 | goto calc_done##TPE; \ |
1605 | } \ |
1606 | curval = n > 0 ? (dbl) sum / n : dbl_nil; \ |
1607 | calc_done##TPE: \ |
1608 | *rb = curval; \ |
1609 | has_nils = has_nils || (n == 0); \ |
1610 | n = 0; \ |
1611 | sum = 0; \ |
1612 | } \ |
1613 | } while (0) |
1614 | |
1615 | #ifdef HAVE_HGE |
1616 | #define ANALYTICAL_AVERAGE_LNG_HGE(TPE) ANALYTICAL_AVERAGE_CALC_NUM(TPE,hge) |
1617 | #else |
1618 | #define ANALYTICAL_AVERAGE_LNG_HGE(TPE) ANALYTICAL_AVERAGE_CALC_NUM(TPE,lng) |
1619 | #endif |
1620 | |
1621 | #define ANALYTICAL_AVERAGE_CALC_FP(TPE) \ |
1622 | do { \ |
1623 | TPE *bp = (TPE*)Tloc(b, 0), *bs, *be, v; \ |
1624 | dbl a = 0; \ |
1625 | for (; i < cnt; i++, rb++) { \ |
1626 | bs = bp + start[i]; \ |
1627 | be = bp + end[i]; \ |
1628 | for (; bs < be; bs++) { \ |
1629 | v = *bs; \ |
1630 | if (!is_##TPE##_nil(v)) \ |
1631 | AVERAGE_ITER_FLOAT(TPE, v, a, n); \ |
1632 | } \ |
1633 | curval = (n > 0) ? a : dbl_nil; \ |
1634 | *rb = curval; \ |
1635 | has_nils = has_nils || (n == 0); \ |
1636 | n = 0; \ |
1637 | a = 0; \ |
1638 | } \ |
1639 | } while (0) |
1640 | |
1641 | gdk_return |
1642 | GDKanalyticalavg(BAT *r, BAT *b, BAT *s, BAT *e, int tpe) |
1643 | { |
1644 | bool has_nils = false; |
1645 | BUN i = 0, cnt = BATcount(b), nils = 0, n = 0, rr = 0; |
1646 | bool abort_on_error = true; |
1647 | lng *restrict start, *restrict end; |
1648 | dbl *restrict rb = (dbl *) Tloc(r, 0), curval; |
1649 | #ifdef HAVE_HGE |
1650 | hge sum = 0; |
1651 | #else |
1652 | lng sum = 0; |
1653 | #endif |
1654 | |
1655 | assert(s && e); |
1656 | start = (lng *) Tloc(s, 0); |
1657 | end = (lng *) Tloc(e, 0); |
1658 | |
1659 | switch (tpe) { |
1660 | case TYPE_bte: |
1661 | ANALYTICAL_AVERAGE_LNG_HGE(bte); |
1662 | break; |
1663 | case TYPE_sht: |
1664 | ANALYTICAL_AVERAGE_LNG_HGE(sht); |
1665 | break; |
1666 | case TYPE_int: |
1667 | ANALYTICAL_AVERAGE_LNG_HGE(int); |
1668 | break; |
1669 | case TYPE_lng: |
1670 | ANALYTICAL_AVERAGE_LNG_HGE(lng); |
1671 | break; |
1672 | #ifdef HAVE_HGE |
1673 | case TYPE_hge: |
1674 | ANALYTICAL_AVERAGE_LNG_HGE(hge); |
1675 | break; |
1676 | #endif |
1677 | case TYPE_flt: |
1678 | ANALYTICAL_AVERAGE_CALC_FP(flt); |
1679 | break; |
1680 | case TYPE_dbl: |
1681 | ANALYTICAL_AVERAGE_CALC_FP(dbl); |
1682 | break; |
1683 | default: |
1684 | GDKerror("GDKanalyticalavg: average of type %s unsupported.\n" , ATOMname(tpe)); |
1685 | return GDK_FAIL; |
1686 | } |
1687 | BATsetcount(r, cnt); |
1688 | r->tnonil = !has_nils; |
1689 | r->tnil = has_nils; |
1690 | return GDK_SUCCEED; |
1691 | } |
1692 | |