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
63gdk_return
64GDKanalyticaldiff(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
197gdk_return
198GDKanalyticalntile(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
249gdk_return
250GDKanalyticalfirst(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
326gdk_return
327GDKanalyticallast(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
474gdk_return
475GDKanalyticalnthvalue(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
689gdk_return
690GDKanalyticallag(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
839gdk_return
840GDKanalyticallead(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) \
950gdk_return \
951GDKanalytical##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
1018ANALYTICAL_MIN_MAX(min, MIN, >)
1019ANALYTICAL_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
1047gdk_return
1048GDKanalyticalcount(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
1197gdk_return
1198GDKanalyticalsum(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
1415gdk_return
1416GDKanalyticalprod(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) { \
1583avg_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; \
1607calc_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
1641gdk_return
1642GDKanalyticalavg(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