Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 : #include "gdk.h"
15 : #include "gdk_private.h"
16 : #include "gdk_calc_private.h"
17 :
18 : /* Generally, the functions return a new BAT aligned with the input
19 : * BAT(s). If there are multiple input BATs, they must be aligned.
20 : * If there is a candidate list, the calculations are only done for
21 : * the candidates, all other values are NIL (so that the output is
22 : * still aligned). */
23 :
24 : static inline gdk_return
25 2925 : checkbats(BATiter *b1i, BATiter *b2i, const char *func)
26 : {
27 2925 : if (b1i->count != b2i->count) {
28 0 : GDKerror("%s: inputs not the same size.\n", func);
29 0 : return GDK_FAIL;
30 : }
31 : return GDK_SUCCEED;
32 : }
33 :
34 : /* ---------------------------------------------------------------------- */
35 : /* logical (for type bit) or bitwise (for integral types) NOT */
36 :
37 : #define NOT(x) (~(x))
38 : #define NOTBIT(x) (!(x))
39 :
40 : BAT *
41 1118 : BATcalcnot(BAT *b, BAT *s)
42 : {
43 1118 : lng t0 = 0;
44 1118 : BAT *bn;
45 1118 : BUN nils = 0;
46 1118 : BUN i;
47 1118 : oid x, bhseqbase;
48 1118 : struct canditer ci;
49 :
50 1118 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
51 :
52 1118 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
53 :
54 1118 : BATcheck(b, NULL);
55 :
56 1118 : bhseqbase = b->hseqbase;
57 1118 : canditer_init(&ci, b, s);
58 1118 : if (ci.ncand == 0)
59 510 : return BATconstant(ci.hseq, b->ttype,
60 510 : ATOMnilptr(b->ttype), ci.ncand, TRANSIENT);
61 :
62 608 : bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
63 608 : if (bn == NULL)
64 : return NULL;
65 :
66 608 : BATiter bi = bat_iterator(b);
67 608 : switch (ATOMbasetype(bi.type)) {
68 0 : case TYPE_msk:
69 0 : if (ci.tpe == cand_dense) {
70 0 : const uint32_t *restrict src = (const uint32_t *) bi.base + (ci.seq - b->hseqbase) / 32;
71 0 : uint32_t *restrict dst = Tloc(bn, 0);
72 0 : int bits = (ci.seq - b->hseqbase) % 32;
73 0 : BUN ncand = (ci.ncand + 31) / 32;
74 0 : if (bits == 0) {
75 0 : TIMEOUT_LOOP_IDX(i, ncand, qry_ctx) {
76 0 : dst[i] = ~src[i];
77 : }
78 0 : TIMEOUT_CHECK(qry_ctx,
79 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
80 : } else {
81 0 : TIMEOUT_LOOP_IDX(i, ncand, qry_ctx) {
82 0 : dst[i] = (~src[i] >> bits) | ~(src[i + 1] >> (32 - bits));
83 : }
84 0 : TIMEOUT_CHECK(qry_ctx,
85 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
86 : }
87 0 : if (ci.ncand % 32 != 0)
88 0 : dst[ci.ncand / 32] &= (1U << (ci.ncand % 32)) - 1;
89 : } else {
90 0 : TIMEOUT_LOOP_IDX(i, ci.ncand, qry_ctx) {
91 0 : x = canditer_next(&ci) - bhseqbase;
92 0 : mskSetVal(bn, i, !Tmskval(&bi, x));
93 : }
94 0 : TIMEOUT_CHECK(qry_ctx,
95 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
96 : }
97 : break;
98 608 : case TYPE_bte:
99 608 : if (bi.type == TYPE_bit) {
100 4827460 : UNARY_2TYPE_FUNC(bit, bit, NOTBIT);
101 : } else {
102 0 : UNARY_2TYPE_FUNC_nilcheck(bte, bte, NOT, ON_OVERFLOW1(bte, "NOT"));
103 : }
104 : break;
105 0 : case TYPE_sht:
106 0 : UNARY_2TYPE_FUNC_nilcheck(sht, sht, NOT, ON_OVERFLOW1(sht, "NOT"));
107 : break;
108 0 : case TYPE_int:
109 0 : UNARY_2TYPE_FUNC_nilcheck(int, int, NOT, ON_OVERFLOW1(int, "NOT"));
110 : break;
111 0 : case TYPE_lng:
112 0 : UNARY_2TYPE_FUNC_nilcheck(lng, lng, NOT, ON_OVERFLOW1(lng, "NOT"));
113 : break;
114 : #ifdef HAVE_HGE
115 0 : case TYPE_hge:
116 0 : UNARY_2TYPE_FUNC_nilcheck(hge, hge, NOT, ON_OVERFLOW1(hge, "NOT"));
117 : break;
118 : #endif
119 0 : default:
120 0 : GDKerror("type %s not supported.\n", ATOMname(bi.type));
121 0 : goto bailout;
122 : }
123 :
124 607 : BATsetcount(bn, ci.ncand);
125 :
126 : /* NOT reverses the order, but NILs mess it up */
127 607 : bn->tsorted = nils == 0 && bi.revsorted;
128 607 : bn->trevsorted = nils == 0 && bi.sorted;
129 607 : bn->tnil = nils != 0;
130 607 : bn->tnonil = nils == 0;
131 607 : bn->tkey = bi.key && nils <= 1;
132 607 : bat_iterator_end(&bi);
133 :
134 608 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
135 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
136 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
137 : ALGOOPTBATPAR(bn), GDKusec() - t0);
138 :
139 : return bn;
140 :
141 0 : bailout:
142 0 : bat_iterator_end(&bi);
143 0 : BBPunfix(bn->batCacheid);
144 0 : return NULL;
145 : }
146 :
147 : gdk_return
148 1175945 : VARcalcnot(ValPtr ret, const ValRecord *v)
149 : {
150 1175945 : *ret = (ValRecord) {.vtype = v->vtype};
151 1175948 : switch (ATOMbasetype(v->vtype)) {
152 0 : case TYPE_msk:
153 0 : ret->val.mval = !v->val.mval;
154 0 : break;
155 1175945 : case TYPE_bte:
156 1175945 : if (is_bit_nil(v->val.btval))
157 7993 : ret->val.btval = bit_nil;
158 1167952 : else if (v->vtype == TYPE_bit)
159 1167949 : ret->val.btval = !v->val.btval;
160 : else {
161 3 : ret->val.btval = ~v->val.btval;
162 3 : if (is_bte_nil(ret->val.btval)) {
163 0 : GDKerror("22003!overflow in calculation "
164 : "NOT(" FMTbte ").\n", v->val.btval);
165 0 : return GDK_FAIL;
166 : }
167 : }
168 : break;
169 0 : case TYPE_sht:
170 0 : if (is_sht_nil(v->val.shval))
171 0 : ret->val.shval = sht_nil;
172 : else {
173 0 : ret->val.shval = ~v->val.shval;
174 0 : if (is_sht_nil(ret->val.shval)) {
175 0 : GDKerror("22003!overflow in calculation "
176 : "NOT(" FMTsht ").\n", v->val.shval);
177 0 : return GDK_FAIL;
178 : }
179 : }
180 : break;
181 0 : case TYPE_int:
182 0 : if (is_int_nil(v->val.ival))
183 0 : ret->val.ival = int_nil;
184 : else {
185 0 : ret->val.ival = ~v->val.ival;
186 0 : if (is_int_nil(ret->val.ival)) {
187 0 : GDKerror("22003!overflow in calculation "
188 : "NOT(" FMTint ").\n", v->val.ival);
189 0 : return GDK_FAIL;
190 : }
191 : }
192 : break;
193 0 : case TYPE_lng:
194 0 : if (is_lng_nil(v->val.lval))
195 0 : ret->val.lval = lng_nil;
196 : else {
197 0 : ret->val.lval = ~v->val.lval;
198 0 : if (is_lng_nil(ret->val.lval)) {
199 0 : GDKerror("22003!overflow in calculation "
200 : "NOT(" FMTlng ").\n", v->val.lval);
201 0 : return GDK_FAIL;
202 : }
203 : }
204 : break;
205 : #ifdef HAVE_HGE
206 0 : case TYPE_hge:
207 0 : if (is_hge_nil(v->val.hval))
208 0 : ret->val.hval = hge_nil;
209 : else {
210 0 : ret->val.hval = ~v->val.hval;
211 0 : if (is_hge_nil(ret->val.hval)) {
212 0 : GDKerror("22003!overflow in calculation "
213 : "NOT(" FMThge ").\n",
214 : CSThge v->val.hval);
215 0 : return GDK_FAIL;
216 : }
217 : }
218 : break;
219 : #endif
220 0 : default:
221 0 : GDKerror("bad input type %s.\n", ATOMname(v->vtype));
222 0 : return GDK_FAIL;
223 : }
224 : return GDK_SUCCEED;
225 : }
226 :
227 : /* ---------------------------------------------------------------------- */
228 : /* negate value (any numeric type) */
229 :
230 : #define NEGATE(x) (-(x))
231 :
232 : BAT *
233 195 : BATcalcnegate(BAT *b, BAT *s)
234 : {
235 195 : lng t0 = 0;
236 195 : BAT *bn;
237 195 : BUN nils = 0;
238 195 : BUN i;
239 195 : oid x, bhseqbase;
240 195 : struct canditer ci;
241 :
242 195 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
243 :
244 :
245 195 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
246 :
247 195 : BATcheck(b, NULL);
248 :
249 195 : bhseqbase = b->hseqbase;
250 195 : canditer_init(&ci, b, s);
251 195 : if (ci.ncand == 0)
252 23 : return BATconstant(ci.hseq, b->ttype,
253 23 : ATOMnilptr(b->ttype), ci.ncand, TRANSIENT);
254 :
255 172 : bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
256 172 : if (bn == NULL)
257 : return NULL;
258 :
259 172 : BATiter bi = bat_iterator(b);
260 344 : switch (ATOMbasetype(bi.type)) {
261 6 : case TYPE_bte:
262 89 : UNARY_2TYPE_FUNC(bte, bte, NEGATE);
263 : break;
264 5 : case TYPE_sht:
265 117 : UNARY_2TYPE_FUNC(sht, sht, NEGATE);
266 : break;
267 100 : case TYPE_int:
268 674 : UNARY_2TYPE_FUNC(int, int, NEGATE);
269 : break;
270 23 : case TYPE_lng:
271 322 : UNARY_2TYPE_FUNC(lng, lng, NEGATE);
272 : break;
273 : #ifdef HAVE_HGE
274 21 : case TYPE_hge:
275 336 : UNARY_2TYPE_FUNC(hge, hge, NEGATE);
276 : break;
277 : #endif
278 0 : case TYPE_flt:
279 0 : UNARY_2TYPE_FUNC(flt, flt, NEGATE);
280 : break;
281 17 : case TYPE_dbl:
282 123 : UNARY_2TYPE_FUNC(dbl, dbl, NEGATE);
283 : break;
284 0 : default:
285 0 : GDKerror("type %s not supported.\n", ATOMname(bi.type));
286 0 : goto bailout;
287 : }
288 :
289 172 : BATsetcount(bn, ci.ncand);
290 :
291 : /* unary - reverses the order, but NILs mess it up */
292 172 : bn->tsorted = nils == 0 && bi.revsorted;
293 172 : bn->trevsorted = nils == 0 && bi.sorted;
294 172 : bn->tnil = nils != 0;
295 172 : bn->tnonil = nils == 0;
296 172 : bn->tkey = bi.key && nils <= 1;
297 172 : bat_iterator_end(&bi);
298 :
299 172 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
300 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
301 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
302 : ALGOOPTBATPAR(bn), GDKusec() - t0);
303 :
304 : return bn;
305 0 : bailout:
306 0 : bat_iterator_end(&bi);
307 0 : BBPunfix(bn->batCacheid);
308 0 : return NULL;
309 : }
310 :
311 : gdk_return
312 9877 : VARcalcnegate(ValPtr ret, const ValRecord *v)
313 : {
314 9877 : *ret = (ValRecord) {.vtype = v->vtype};
315 19754 : switch (ATOMbasetype(v->vtype)) {
316 7296 : case TYPE_bte:
317 7296 : if (is_bte_nil(v->val.btval))
318 4 : ret->val.btval = bte_nil;
319 : else
320 7292 : ret->val.btval = -v->val.btval;
321 : break;
322 274 : case TYPE_sht:
323 274 : if (is_sht_nil(v->val.shval))
324 2 : ret->val.shval = sht_nil;
325 : else
326 272 : ret->val.shval = -v->val.shval;
327 : break;
328 806 : case TYPE_int:
329 806 : if (is_int_nil(v->val.ival))
330 13 : ret->val.ival = int_nil;
331 : else
332 793 : ret->val.ival = -v->val.ival;
333 : break;
334 1314 : case TYPE_lng:
335 1314 : if (is_lng_nil(v->val.lval))
336 6 : ret->val.lval = lng_nil;
337 : else
338 1308 : ret->val.lval = -v->val.lval;
339 : break;
340 : #ifdef HAVE_HGE
341 87 : case TYPE_hge:
342 87 : if (is_hge_nil(v->val.hval))
343 2 : ret->val.hval = hge_nil;
344 : else
345 85 : ret->val.hval = -v->val.hval;
346 : break;
347 : #endif
348 8 : case TYPE_flt:
349 8 : if (is_flt_nil(v->val.fval))
350 8 : ret->val.fval = flt_nil;
351 : else
352 0 : ret->val.fval = -v->val.fval;
353 : break;
354 92 : case TYPE_dbl:
355 92 : if (is_dbl_nil(v->val.dval))
356 4 : ret->val.dval = dbl_nil;
357 : else
358 88 : ret->val.dval = -v->val.dval;
359 : break;
360 0 : default:
361 0 : GDKerror("bad input type %s.\n", ATOMname(v->vtype));
362 0 : return GDK_FAIL;
363 : }
364 : return GDK_SUCCEED;
365 : }
366 :
367 : /* ---------------------------------------------------------------------- */
368 : /* absolute value (any numeric type) */
369 :
370 : BAT *
371 4529 : BATcalcabsolute(BAT *b, BAT *s)
372 : {
373 4529 : lng t0 = 0;
374 4529 : BAT *bn;
375 4529 : BUN nils = 0;
376 4529 : BUN i;
377 4529 : oid x, bhseqbase;
378 4529 : struct canditer ci;
379 :
380 4529 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
381 :
382 :
383 4529 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
384 :
385 4529 : BATcheck(b, NULL);
386 :
387 4529 : bhseqbase = b->hseqbase;
388 4529 : canditer_init(&ci, b, s);
389 4529 : if (ci.ncand == 0)
390 744 : return BATconstant(ci.hseq, b->ttype,
391 744 : ATOMnilptr(b->ttype), ci.ncand, TRANSIENT);
392 :
393 3785 : bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
394 3785 : if (bn == NULL)
395 : return NULL;
396 :
397 3785 : BATiter bi = bat_iterator(b);
398 7570 : switch (ATOMbasetype(bi.type)) {
399 3 : case TYPE_bte:
400 13 : UNARY_2TYPE_FUNC(bte, bte, (bte) abs);
401 : break;
402 4 : case TYPE_sht:
403 17 : UNARY_2TYPE_FUNC(sht, sht, (sht) abs);
404 : break;
405 2138 : case TYPE_int:
406 26087 : UNARY_2TYPE_FUNC(int, int, abs);
407 : break;
408 1625 : case TYPE_lng:
409 18503 : UNARY_2TYPE_FUNC(lng, lng, llabs);
410 : break;
411 : #ifdef HAVE_HGE
412 5 : case TYPE_hge:
413 85518 : UNARY_2TYPE_FUNC(hge, hge, ABSOLUTE);
414 : break;
415 : #endif
416 1 : case TYPE_flt:
417 10 : UNARY_2TYPE_FUNC(flt, flt, fabsf);
418 : break;
419 9 : case TYPE_dbl:
420 60 : UNARY_2TYPE_FUNC(dbl, dbl, fabs);
421 : break;
422 0 : default:
423 0 : GDKerror("bad input type %s.\n", ATOMname(bi.type));
424 0 : goto bailout;
425 : }
426 3785 : bat_iterator_end(&bi);
427 :
428 3785 : BATsetcount(bn, ci.ncand);
429 :
430 : /* ABSOLUTE messes up order (unless all values were negative
431 : * or all values were positive, but we don't know anything
432 : * about that) */
433 3785 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
434 3785 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
435 3785 : bn->tkey = ci.ncand <= 1;
436 3785 : bn->tnil = nils != 0;
437 3785 : bn->tnonil = nils == 0;
438 :
439 3785 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
440 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
441 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
442 : ALGOOPTBATPAR(bn), GDKusec() - t0);
443 :
444 : return bn;
445 0 : bailout:
446 0 : bat_iterator_end(&bi);
447 0 : BBPunfix(bn->batCacheid);
448 0 : return NULL;
449 : }
450 :
451 : gdk_return
452 265 : VARcalcabsolute(ValPtr ret, const ValRecord *v)
453 : {
454 265 : *ret = (ValRecord) {.vtype = v->vtype};
455 530 : switch (ATOMbasetype(v->vtype)) {
456 32 : case TYPE_bte:
457 32 : if (is_bte_nil(v->val.btval))
458 3 : ret->val.btval = bte_nil;
459 : else
460 29 : ret->val.btval = (bte) abs(v->val.btval);
461 : break;
462 10 : case TYPE_sht:
463 10 : if (is_sht_nil(v->val.shval))
464 0 : ret->val.shval = sht_nil;
465 : else
466 10 : ret->val.shval = (sht) abs(v->val.shval);
467 : break;
468 210 : case TYPE_int:
469 210 : if (is_int_nil(v->val.ival))
470 0 : ret->val.ival = int_nil;
471 : else
472 210 : ret->val.ival = abs(v->val.ival);
473 : break;
474 7 : case TYPE_lng:
475 7 : if (is_lng_nil(v->val.lval))
476 0 : ret->val.lval = lng_nil;
477 : else
478 7 : ret->val.lval = llabs(v->val.lval);
479 : break;
480 : #ifdef HAVE_HGE
481 0 : case TYPE_hge:
482 0 : if (is_hge_nil(v->val.hval))
483 0 : ret->val.hval = hge_nil;
484 : else
485 0 : ret->val.hval = ABSOLUTE(v->val.hval);
486 : break;
487 : #endif
488 1 : case TYPE_flt:
489 1 : if (is_flt_nil(v->val.fval))
490 0 : ret->val.fval = flt_nil;
491 : else
492 1 : ret->val.fval = fabsf(v->val.fval);
493 : break;
494 5 : case TYPE_dbl:
495 5 : if (is_dbl_nil(v->val.dval))
496 0 : ret->val.dval = dbl_nil;
497 : else
498 5 : ret->val.dval = fabs(v->val.dval);
499 : break;
500 0 : default:
501 0 : GDKerror("bad input type %s.\n", ATOMname(v->vtype));
502 0 : return GDK_FAIL;
503 : }
504 : return GDK_SUCCEED;
505 : }
506 :
507 : /* ---------------------------------------------------------------------- */
508 : /* is the value equal to zero (any numeric type) */
509 :
510 : #define ISZERO(x) ((bit) ((x) == 0))
511 :
512 : BAT *
513 0 : BATcalciszero(BAT *b, BAT *s)
514 : {
515 0 : lng t0 = 0;
516 0 : BAT *bn;
517 0 : BUN nils = 0;
518 0 : BUN i;
519 0 : oid x, bhseqbase;
520 0 : struct canditer ci;
521 :
522 0 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
523 :
524 0 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
525 :
526 0 : BATcheck(b, NULL);
527 :
528 0 : bhseqbase = b->hseqbase;
529 0 : canditer_init(&ci, b, s);
530 0 : if (ci.ncand == 0)
531 0 : return BATconstant(ci.hseq, TYPE_bit,
532 : ATOMnilptr(TYPE_bit), ci.ncand, TRANSIENT);
533 :
534 0 : bn = COLnew(ci.hseq, TYPE_bit, ci.ncand, TRANSIENT);
535 0 : if (bn == NULL)
536 : return NULL;
537 :
538 0 : BATiter bi = bat_iterator(b);
539 0 : switch (ATOMbasetype(bi.type)) {
540 0 : case TYPE_bte:
541 0 : UNARY_2TYPE_FUNC(bte, bit, ISZERO);
542 : break;
543 0 : case TYPE_sht:
544 0 : UNARY_2TYPE_FUNC(sht, bit, ISZERO);
545 : break;
546 0 : case TYPE_int:
547 0 : UNARY_2TYPE_FUNC(int, bit, ISZERO);
548 : break;
549 0 : case TYPE_lng:
550 0 : UNARY_2TYPE_FUNC(lng, bit, ISZERO);
551 : break;
552 : #ifdef HAVE_HGE
553 0 : case TYPE_hge:
554 0 : UNARY_2TYPE_FUNC(hge, bit, ISZERO);
555 : break;
556 : #endif
557 0 : case TYPE_flt:
558 0 : UNARY_2TYPE_FUNC(flt, bit, ISZERO);
559 : break;
560 0 : case TYPE_dbl:
561 0 : UNARY_2TYPE_FUNC(dbl, bit, ISZERO);
562 : break;
563 0 : default:
564 0 : GDKerror("bad input type %s.\n", ATOMname(bi.type));
565 0 : goto bailout;
566 : }
567 0 : bat_iterator_end(&bi);
568 :
569 0 : BATsetcount(bn, ci.ncand);
570 :
571 0 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
572 0 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
573 0 : bn->tkey = ci.ncand <= 1;
574 0 : bn->tnil = nils != 0;
575 0 : bn->tnonil = nils == 0;
576 :
577 0 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
578 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
579 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
580 : ALGOOPTBATPAR(bn), GDKusec() - t0);
581 :
582 : return bn;
583 0 : bailout:
584 0 : bat_iterator_end(&bi);
585 0 : BBPunfix(bn->batCacheid);
586 0 : return NULL;
587 : }
588 :
589 : gdk_return
590 0 : VARcalciszero(ValPtr ret, const ValRecord *v)
591 : {
592 0 : *ret = (ValRecord) {.vtype = TYPE_bit};
593 0 : switch (ATOMbasetype(v->vtype)) {
594 0 : case TYPE_bte:
595 0 : if (is_bte_nil(v->val.btval))
596 0 : ret->val.btval = bit_nil;
597 : else
598 0 : ret->val.btval = ISZERO(v->val.btval);
599 : break;
600 0 : case TYPE_sht:
601 0 : if (is_sht_nil(v->val.shval))
602 0 : ret->val.btval = bit_nil;
603 : else
604 0 : ret->val.btval = ISZERO(v->val.shval);
605 : break;
606 0 : case TYPE_int:
607 0 : if (is_int_nil(v->val.ival))
608 0 : ret->val.btval = bit_nil;
609 : else
610 0 : ret->val.btval = ISZERO(v->val.ival);
611 : break;
612 0 : case TYPE_lng:
613 0 : if (is_lng_nil(v->val.lval))
614 0 : ret->val.btval = bit_nil;
615 : else
616 0 : ret->val.btval = ISZERO(v->val.lval);
617 : break;
618 : #ifdef HAVE_HGE
619 0 : case TYPE_hge:
620 0 : if (is_hge_nil(v->val.hval))
621 0 : ret->val.btval = bit_nil;
622 : else
623 0 : ret->val.btval = ISZERO(v->val.hval);
624 : break;
625 : #endif
626 0 : case TYPE_flt:
627 0 : if (is_flt_nil(v->val.fval))
628 0 : ret->val.btval = bit_nil;
629 : else
630 0 : ret->val.btval = ISZERO(v->val.fval);
631 : break;
632 0 : case TYPE_dbl:
633 0 : if (is_dbl_nil(v->val.dval))
634 0 : ret->val.btval = bit_nil;
635 : else
636 0 : ret->val.btval = ISZERO(v->val.dval);
637 : break;
638 0 : default:
639 0 : GDKerror("bad input type %s.\n", ATOMname(v->vtype));
640 0 : return GDK_FAIL;
641 : }
642 : return GDK_SUCCEED;
643 : }
644 :
645 : /* ---------------------------------------------------------------------- */
646 : /* sign of value (-1 for negative, 0 for 0, +1 for positive; any
647 : * numeric type) */
648 :
649 : #define SIGN(x) ((bte) ((x) < 0 ? -1 : (x) > 0))
650 :
651 : BAT *
652 14 : BATcalcsign(BAT *b, BAT *s)
653 : {
654 14 : lng t0 = 0;
655 14 : BAT *bn;
656 14 : BUN nils = 0;
657 14 : BUN i;
658 14 : oid x, bhseqbase;
659 14 : struct canditer ci;
660 :
661 14 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
662 :
663 14 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
664 :
665 14 : BATcheck(b, NULL);
666 :
667 14 : bhseqbase = b->hseqbase;
668 14 : canditer_init(&ci, b, s);
669 14 : if (ci.ncand == 0)
670 0 : return BATconstant(ci.hseq, TYPE_bte,
671 : ATOMnilptr(TYPE_bte), ci.ncand, TRANSIENT);
672 :
673 14 : bn = COLnew(ci.hseq, TYPE_bte, ci.ncand, TRANSIENT);
674 14 : if (bn == NULL)
675 : return NULL;
676 :
677 14 : BATiter bi = bat_iterator(b);
678 28 : switch (ATOMbasetype(bi.type)) {
679 1 : case TYPE_bte:
680 9 : UNARY_2TYPE_FUNC(bte, bte, SIGN);
681 : break;
682 1 : case TYPE_sht:
683 9 : UNARY_2TYPE_FUNC(sht, bte, SIGN);
684 : break;
685 6 : case TYPE_int:
686 33 : UNARY_2TYPE_FUNC(int, bte, SIGN);
687 : break;
688 2 : case TYPE_lng:
689 18 : UNARY_2TYPE_FUNC(lng, bte, SIGN);
690 : break;
691 : #ifdef HAVE_HGE
692 0 : case TYPE_hge:
693 0 : UNARY_2TYPE_FUNC(hge, bte, SIGN);
694 : break;
695 : #endif
696 1 : case TYPE_flt:
697 10 : UNARY_2TYPE_FUNC(flt, bte, SIGN);
698 : break;
699 3 : case TYPE_dbl:
700 17 : UNARY_2TYPE_FUNC(dbl, bte, SIGN);
701 : break;
702 0 : default:
703 0 : GDKerror("bad input type %s.\n", ATOMname(bi.type));
704 0 : goto bailout;
705 : }
706 :
707 14 : BATsetcount(bn, ci.ncand);
708 :
709 : /* SIGN is ordered if the input is ordered (negative comes
710 : * first, positive comes after) and NILs stay in the same
711 : * position */
712 14 : bn->tsorted = bi.sorted || ci.ncand <= 1 || nils == ci.ncand;
713 14 : bn->trevsorted = bi.revsorted || ci.ncand <= 1 || nils == ci.ncand;
714 14 : bn->tkey = ci.ncand <= 1;
715 14 : bn->tnil = nils != 0;
716 14 : bn->tnonil = nils == 0;
717 14 : bat_iterator_end(&bi);
718 :
719 14 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
720 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
721 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
722 : ALGOOPTBATPAR(bn), GDKusec() - t0);
723 :
724 : return bn;
725 0 : bailout:
726 0 : bat_iterator_end(&bi);
727 0 : BBPunfix(bn->batCacheid);
728 0 : return NULL;
729 : }
730 :
731 : gdk_return
732 22322 : VARcalcsign(ValPtr ret, const ValRecord *v)
733 : {
734 22322 : *ret = (ValRecord) {.vtype = TYPE_bte};
735 44644 : switch (ATOMbasetype(v->vtype)) {
736 18945 : case TYPE_bte:
737 18945 : if (is_bte_nil(v->val.btval))
738 0 : ret->val.btval = bte_nil;
739 : else
740 18945 : ret->val.btval = SIGN(v->val.btval);
741 : break;
742 2153 : case TYPE_sht:
743 2153 : if (is_sht_nil(v->val.shval))
744 0 : ret->val.btval = bte_nil;
745 : else
746 2153 : ret->val.btval = SIGN(v->val.shval);
747 : break;
748 125 : case TYPE_int:
749 125 : if (is_int_nil(v->val.ival))
750 6 : ret->val.btval = bte_nil;
751 : else
752 119 : ret->val.btval = SIGN(v->val.ival);
753 : break;
754 1018 : case TYPE_lng:
755 1018 : if (is_lng_nil(v->val.lval))
756 0 : ret->val.btval = bte_nil;
757 : else
758 1018 : ret->val.btval = SIGN(v->val.lval);
759 : break;
760 : #ifdef HAVE_HGE
761 3 : case TYPE_hge:
762 3 : if (is_hge_nil(v->val.hval))
763 0 : ret->val.btval = bte_nil;
764 : else
765 3 : ret->val.btval = SIGN(v->val.hval);
766 : break;
767 : #endif
768 2 : case TYPE_flt:
769 2 : if (is_flt_nil(v->val.fval))
770 1 : ret->val.btval = bte_nil;
771 : else
772 1 : ret->val.btval = SIGN(v->val.fval);
773 : break;
774 76 : case TYPE_dbl:
775 76 : if (is_dbl_nil(v->val.dval))
776 0 : ret->val.btval = bte_nil;
777 : else
778 76 : ret->val.btval = SIGN(v->val.dval);
779 : break;
780 0 : default:
781 0 : GDKerror("bad input type %s.\n",
782 : ATOMname(v->vtype));
783 0 : return GDK_FAIL;
784 : }
785 : return GDK_SUCCEED;
786 : }
787 :
788 : /* ---------------------------------------------------------------------- */
789 : /* is the value nil (any type) */
790 :
791 : #define ISNIL_TYPE(TYPE, NOTNIL) \
792 : do { \
793 : const TYPE *restrict src = (const TYPE *) bi.base; \
794 : TIMEOUT_LOOP_IDX(i, ci.ncand, qry_ctx) { \
795 : x = canditer_next(&ci) - bhseqbase; \
796 : dst[i] = (bit) (is_##TYPE##_nil(src[x]) ^ NOTNIL); \
797 : } \
798 : TIMEOUT_CHECK(qry_ctx, GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
799 : } while (0)
800 :
801 : static BAT *
802 6572 : BATcalcisnil_implementation(BAT *b, BAT *s, bool notnil)
803 : {
804 6572 : lng t0 = 0;
805 6572 : BAT *bn;
806 6572 : BUN i;
807 6572 : oid x;
808 6572 : struct canditer ci;
809 6572 : bit *restrict dst;
810 6572 : BUN nils = 0;
811 6572 : oid bhseqbase;
812 :
813 6572 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
814 :
815 6572 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
816 :
817 6572 : BATcheck(b, NULL);
818 :
819 6572 : bhseqbase = b->hseqbase;
820 6572 : canditer_init(&ci, b, s);
821 :
822 6572 : if (b->tnonil || BATtdense(b)) {
823 1768 : return BATconstant(ci.hseq, TYPE_bit, &(bit){notnil},
824 : ci.ncand, TRANSIENT);
825 4804 : } else if (b->ttype == TYPE_void) {
826 : /* non-nil handled above */
827 49 : assert(is_oid_nil(b->tseqbase));
828 49 : return BATconstant(ci.hseq, TYPE_bit, &(bit){!notnil},
829 : ci.ncand, TRANSIENT);
830 : }
831 :
832 4755 : bn = COLnew(ci.hseq, TYPE_bit, ci.ncand, TRANSIENT);
833 4755 : if (bn == NULL)
834 : return NULL;
835 :
836 4755 : dst = (bit *) Tloc(bn, 0);
837 :
838 4755 : BATiter bi = bat_iterator(b);
839 9156 : switch (ATOMbasetype(bi.type)) {
840 693 : case TYPE_bte:
841 35744427 : ISNIL_TYPE(bte, notnil);
842 : break;
843 84 : case TYPE_sht:
844 8999716 : ISNIL_TYPE(sht, notnil);
845 : break;
846 1758 : case TYPE_int:
847 13253892 : ISNIL_TYPE(int, notnil);
848 : break;
849 1915 : case TYPE_lng:
850 24038579 : ISNIL_TYPE(lng, notnil);
851 : break;
852 : #ifdef HAVE_HGE
853 51 : case TYPE_hge:
854 6069136 : ISNIL_TYPE(hge, notnil);
855 : break;
856 : #endif
857 5 : case TYPE_flt:
858 25 : ISNIL_TYPE(flt, notnil);
859 : break;
860 29 : case TYPE_dbl:
861 304 : ISNIL_TYPE(dbl, notnil);
862 : break;
863 1 : case TYPE_uuid:
864 5 : ISNIL_TYPE(uuid, notnil);
865 : break;
866 219 : default:
867 : {
868 219 : int (*atomcmp)(const void *, const void *) = ATOMcompare(bi.type);
869 219 : const void *nil = ATOMnilptr(bi.type);
870 :
871 7425872 : TIMEOUT_LOOP_IDX(i, ci.ncand, qry_ctx) {
872 7424956 : x = canditer_next(&ci) - bhseqbase;
873 7425037 : dst[i] = (bit) (((*atomcmp)(BUNtail(bi, x), nil) == 0) ^ notnil);
874 : }
875 219 : TIMEOUT_CHECK(qry_ctx, GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
876 : break;
877 : }
878 : }
879 :
880 4753 : BATsetcount(bn, ci.ncand);
881 :
882 : /* If b sorted, all nils are at the start, i.e. bn starts with
883 : * 1's and ends with 0's, hence bn is revsorted. Similarly
884 : * for revsorted. At the notnil case, these properties remain the same */
885 4754 : if (notnil) {
886 2393 : bn->tsorted = bi.sorted;
887 2393 : bn->trevsorted = bi.revsorted;
888 : } else {
889 2361 : bn->tsorted = bi.revsorted;
890 2361 : bn->trevsorted = bi.sorted;
891 : }
892 4754 : bn->tnil = nils != 0;
893 4754 : bn->tnonil = nils == 0;
894 4754 : bn->tkey = ci.ncand <= 1;
895 4754 : bat_iterator_end(&bi);
896 :
897 4754 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
898 : ",notnil=%s -> " ALGOOPTBATFMT " " LLFMT "usec\n",
899 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
900 : notnil ? "true" : "false", ALGOOPTBATPAR(bn), GDKusec() - t0);
901 :
902 : return bn;
903 0 : bailout:
904 0 : bat_iterator_end(&bi);
905 0 : BBPreclaim(bn);
906 0 : return NULL;
907 : }
908 :
909 : BAT *
910 3698 : BATcalcisnil(BAT *b, BAT *s)
911 : {
912 3698 : return BATcalcisnil_implementation(b, s, false);
913 : }
914 :
915 : BAT *
916 2874 : BATcalcisnotnil(BAT *b, BAT *s)
917 : {
918 2874 : return BATcalcisnil_implementation(b, s, true);
919 : }
920 :
921 : gdk_return
922 1193904 : VARcalcisnil(ValPtr ret, const ValRecord *v)
923 : {
924 2387808 : *ret = (ValRecord) {
925 : .vtype = TYPE_bit,
926 1193904 : .val.btval = (bat) VALisnil(v),
927 : };
928 1193904 : return GDK_SUCCEED;
929 : }
930 :
931 : gdk_return
932 377 : VARcalcisnotnil(ValPtr ret, const ValRecord *v)
933 : {
934 754 : *ret = (ValRecord) {
935 : .vtype = TYPE_bit,
936 377 : .val.btval = (bat) !VALisnil(v),
937 : };
938 377 : return GDK_SUCCEED;
939 : }
940 :
941 : #define MINMAX_TYPE(TYPE, OP) \
942 : do { \
943 : TYPE *tb1 = b1i.base, *tb2 = b2i.base, *restrict tbn = Tloc(bn, 0); \
944 : if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) { \
945 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) { \
946 : oid x1 = canditer_next_dense(&ci1) - b1hseqbase; \
947 : oid x2 = canditer_next_dense(&ci2) - b2hseqbase; \
948 : TYPE p1 = tb1[x1], p2 = tb2[x2]; \
949 : if (is_##TYPE##_nil(p1) || is_##TYPE##_nil(p2)) { \
950 : nils = true; \
951 : tbn[i] = TYPE##_nil; \
952 : } else { \
953 : tbn[i] = p1 OP p2 ? p1 : p2; \
954 : } \
955 : } \
956 : TIMEOUT_CHECK(qry_ctx, \
957 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
958 : } else { \
959 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) { \
960 : oid x1 = canditer_next(&ci1) - b1hseqbase; \
961 : oid x2 = canditer_next(&ci2) - b2hseqbase; \
962 : TYPE p1 = tb1[x1], p2 = tb2[x2]; \
963 : if (is_##TYPE##_nil(p1) || is_##TYPE##_nil(p2)) { \
964 : nils = true; \
965 : tbn[i] = TYPE##_nil; \
966 : } else { \
967 : tbn[i] = p1 OP p2 ? p1 : p2; \
968 : } \
969 : } \
970 : TIMEOUT_CHECK(qry_ctx, \
971 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
972 : } \
973 : } while (0)
974 :
975 : BAT *
976 388 : BATcalcmin(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
977 : {
978 388 : lng t0 = 0;
979 388 : BAT *bn;
980 388 : bool nils = false;
981 388 : struct canditer ci1, ci2;
982 388 : oid b1hseqbase, b2hseqbase;
983 :
984 388 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
985 :
986 388 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
987 :
988 388 : BATcheck(b1, NULL);
989 388 : BATcheck(b2, NULL);
990 :
991 388 : b1hseqbase = b1->hseqbase;
992 388 : b2hseqbase = b2->hseqbase;
993 1164 : if (ATOMtype(b1->ttype) != ATOMtype(b2->ttype)) {
994 0 : GDKerror("inputs have incompatible types\n");
995 0 : return NULL;
996 : }
997 :
998 388 : canditer_init(&ci1, b1, s1);
999 388 : canditer_init(&ci2, b2, s2);
1000 388 : if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
1001 0 : GDKerror("inputs not the same size.\n");
1002 0 : return NULL;
1003 : }
1004 :
1005 776 : bn = COLnew(ci1.hseq, ATOMtype(b1->ttype), ci1.ncand, TRANSIENT);
1006 388 : if (bn == NULL)
1007 : return NULL;
1008 :
1009 388 : BATiter b1i = bat_iterator(b1);
1010 388 : BATiter b2i = bat_iterator(b2);
1011 774 : switch (ATOMbasetype(b1i.type)) {
1012 1 : case TYPE_bte:
1013 4 : MINMAX_TYPE(bte, <);
1014 : break;
1015 0 : case TYPE_sht:
1016 0 : MINMAX_TYPE(sht, <);
1017 : break;
1018 14 : case TYPE_int:
1019 44 : MINMAX_TYPE(int, <);
1020 : break;
1021 373 : case TYPE_lng:
1022 32533 : MINMAX_TYPE(lng, <);
1023 : break;
1024 : #ifdef HAVE_HGE
1025 0 : case TYPE_hge:
1026 0 : MINMAX_TYPE(hge, <);
1027 : break;
1028 : #endif
1029 0 : case TYPE_flt:
1030 0 : MINMAX_TYPE(flt, <);
1031 : break;
1032 0 : case TYPE_dbl:
1033 0 : MINMAX_TYPE(dbl, <);
1034 : break;
1035 0 : default: {
1036 0 : const void *restrict nil = ATOMnilptr(b1i.type);
1037 0 : int (*cmp)(const void *, const void *) = ATOMcompare(b1i.type);
1038 :
1039 0 : if (ATOMvarsized(b1i.type)) {
1040 0 : if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
1041 0 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1042 0 : oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
1043 0 : oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
1044 0 : const void *p1 = BUNtvar(b1i, x1);
1045 0 : const void *p2 = BUNtvar(b2i, x2);
1046 0 : if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
1047 : nils = true;
1048 : p1 = nil;
1049 : } else {
1050 0 : p1 = cmp(p1, p2) < 0 ? p1 : p2;
1051 : }
1052 0 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
1053 0 : goto bailout;
1054 : }
1055 : }
1056 0 : TIMEOUT_CHECK(qry_ctx,
1057 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1058 : } else {
1059 0 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1060 0 : oid x1 = canditer_next(&ci1) - b1hseqbase;
1061 0 : oid x2 = canditer_next(&ci2) - b2hseqbase;
1062 0 : const void *p1 = BUNtvar(b1i, x1);
1063 0 : const void *p2 = BUNtvar(b2i, x2);
1064 0 : if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
1065 : nils = true;
1066 : p1 = nil;
1067 : } else {
1068 0 : p1 = cmp(p1, p2) < 0 ? p1 : p2;
1069 : }
1070 0 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
1071 0 : goto bailout;
1072 : }
1073 : }
1074 0 : TIMEOUT_CHECK(qry_ctx,
1075 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1076 : }
1077 : } else {
1078 0 : uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
1079 0 : uint16_t width = bn->twidth;
1080 0 : if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
1081 0 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1082 0 : oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
1083 0 : oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
1084 0 : const void *p1 = BUNtloc(b1i, x1);
1085 0 : const void *p2 = BUNtloc(b2i, x2);
1086 0 : if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
1087 : nils = true;
1088 : p1 = nil;
1089 : } else {
1090 0 : p1 = cmp(p1, p2) < 0 ? p1 : p2;
1091 : }
1092 0 : memcpy(bcast, p1, width);
1093 0 : bcast += width;
1094 : }
1095 0 : TIMEOUT_CHECK(qry_ctx,
1096 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1097 : } else {
1098 0 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1099 0 : oid x1 = canditer_next(&ci1) - b1hseqbase;
1100 0 : oid x2 = canditer_next(&ci2) - b2hseqbase;
1101 0 : const void *p1 = BUNtloc(b1i, x1);
1102 0 : const void *p2 = BUNtloc(b2i, x2);
1103 0 : if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
1104 : nils = true;
1105 : p1 = nil;
1106 : } else {
1107 0 : p1 = cmp(p1, p2) < 0 ? p1 : p2;
1108 : }
1109 0 : memcpy(bcast, p1, width);
1110 0 : bcast += width;
1111 : }
1112 0 : TIMEOUT_CHECK(qry_ctx,
1113 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1114 : }
1115 : }
1116 : }
1117 : }
1118 :
1119 388 : bn->tnil = nils;
1120 388 : bn->tnonil = !nils;
1121 388 : BATsetcount(bn, ci1.ncand);
1122 388 : if (ci1.ncand <= 1) {
1123 303 : bn->tsorted = true;
1124 303 : bn->trevsorted = true;
1125 303 : bn->tkey = true;
1126 303 : bn->tseqbase = ATOMtype(b1i.type) == TYPE_oid ? ci1.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
1127 : } else {
1128 85 : bn->tsorted = false;
1129 85 : bn->trevsorted = false;
1130 85 : bn->tkey = false;
1131 85 : bn->tseqbase = oid_nil;
1132 : }
1133 388 : bat_iterator_end(&b1i);
1134 388 : bat_iterator_end(&b2i);
1135 :
1136 388 : TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
1137 : ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
1138 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
1139 : ALGOBATPAR(b1), ALGOBATPAR(b2),
1140 : ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
1141 : ALGOOPTBATPAR(bn), GDKusec() - t0);
1142 :
1143 : return bn;
1144 0 : bailout:
1145 0 : bat_iterator_end(&b1i);
1146 0 : bat_iterator_end(&b2i);
1147 0 : BBPreclaim(bn);
1148 0 : return NULL;
1149 : }
1150 :
1151 : #define MINMAX_NONIL_TYPE(TYPE, OP) \
1152 : do { \
1153 : TYPE *tb1 = b1i.base, *tb2 = b2i.base, *restrict tbn = Tloc(bn, 0); \
1154 : if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) { \
1155 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) { \
1156 : oid x1 = canditer_next_dense(&ci1) - b1hseqbase; \
1157 : oid x2 = canditer_next_dense(&ci2) - b2hseqbase; \
1158 : TYPE p1 = tb1[x1], p2 = tb2[x2]; \
1159 : if (is_##TYPE##_nil(p1)) { \
1160 : if (is_##TYPE##_nil(p2)) { \
1161 : tbn[i] = TYPE##_nil; \
1162 : nils = true; \
1163 : } else { \
1164 : tbn[i] = p2; \
1165 : } \
1166 : } else { \
1167 : tbn[i] = !is_##TYPE##_nil(p2) && p2 OP p1 ? p2 : p1; \
1168 : } \
1169 : } \
1170 : TIMEOUT_CHECK(qry_ctx, \
1171 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
1172 : } else { \
1173 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) { \
1174 : oid x1 = canditer_next(&ci1) - b1hseqbase; \
1175 : oid x2 = canditer_next(&ci2) - b2hseqbase; \
1176 : TYPE p1 = tb1[x1], p2 = tb2[x2]; \
1177 : if (is_##TYPE##_nil(p1)) { \
1178 : if (is_##TYPE##_nil(p2)) { \
1179 : tbn[i] = TYPE##_nil; \
1180 : nils = true; \
1181 : } else { \
1182 : tbn[i] = p2; \
1183 : } \
1184 : } else { \
1185 : tbn[i] = !is_##TYPE##_nil(p2) && p2 OP p1 ? p2 : p1; \
1186 : } \
1187 : } \
1188 : TIMEOUT_CHECK(qry_ctx, \
1189 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
1190 : } \
1191 : } while (0)
1192 :
1193 : BAT *
1194 41 : BATcalcmin_no_nil(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
1195 : {
1196 41 : lng t0 = 0;
1197 41 : BAT *bn;
1198 41 : bool nils = false;
1199 41 : struct canditer ci1, ci2;
1200 41 : oid b1hseqbase, b2hseqbase;
1201 :
1202 41 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
1203 :
1204 41 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
1205 :
1206 41 : BATcheck(b1, NULL);
1207 41 : BATcheck(b2, NULL);
1208 :
1209 41 : b1hseqbase = b1->hseqbase;
1210 41 : b2hseqbase = b2->hseqbase;
1211 123 : if (ATOMtype(b1->ttype) != ATOMtype(b2->ttype)) {
1212 0 : GDKerror("inputs have incompatible types\n");
1213 0 : return NULL;
1214 : }
1215 :
1216 41 : canditer_init(&ci1, b1, s1);
1217 41 : canditer_init(&ci2, b2, s2);
1218 41 : if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
1219 0 : GDKerror("inputs not the same size.\n");
1220 0 : return NULL;
1221 : }
1222 :
1223 82 : bn = COLnew(ci1.hseq, ATOMtype(b1->ttype), ci1.ncand, TRANSIENT);
1224 41 : if (bn == NULL)
1225 : return NULL;
1226 :
1227 41 : BATiter b1i = bat_iterator(b1);
1228 41 : BATiter b2i = bat_iterator(b2);
1229 70 : switch (ATOMbasetype(b1i.type)) {
1230 16 : case TYPE_bte:
1231 1074 : MINMAX_NONIL_TYPE(bte, <);
1232 : break;
1233 9 : case TYPE_sht:
1234 441 : MINMAX_NONIL_TYPE(sht, <);
1235 : break;
1236 0 : case TYPE_int:
1237 0 : MINMAX_NONIL_TYPE(int, <);
1238 : break;
1239 3 : case TYPE_lng:
1240 31 : MINMAX_NONIL_TYPE(lng, <);
1241 : break;
1242 : #ifdef HAVE_HGE
1243 4 : case TYPE_hge:
1244 272 : MINMAX_NONIL_TYPE(hge, <);
1245 : break;
1246 : #endif
1247 0 : case TYPE_flt:
1248 0 : MINMAX_NONIL_TYPE(flt, <);
1249 : break;
1250 0 : case TYPE_dbl:
1251 0 : MINMAX_NONIL_TYPE(dbl, <);
1252 : break;
1253 9 : default: {
1254 9 : const void *restrict nil = ATOMnilptr(b1i.type);
1255 9 : int (*cmp)(const void *, const void *) = ATOMcompare(b1i.type);
1256 :
1257 9 : if (ATOMvarsized(b1i.type)) {
1258 9 : if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
1259 141 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1260 114 : oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
1261 114 : oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
1262 114 : const void *p1 = BUNtvar(b1i, x1);
1263 114 : const void *p2 = BUNtvar(b2i, x2);
1264 114 : if (cmp(p1, nil) == 0) {
1265 48 : if (cmp(p2, nil) == 0) {
1266 : /* both values are nil */
1267 : nils = true;
1268 : } else {
1269 0 : p1 = p2;
1270 : }
1271 : } else {
1272 66 : p1 = cmp(p2, nil) != 0 && cmp(p2, p1) < 0 ? p2 : p1;
1273 : }
1274 114 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
1275 0 : goto bailout;
1276 : }
1277 : }
1278 9 : TIMEOUT_CHECK(qry_ctx,
1279 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1280 : } else {
1281 0 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1282 0 : oid x1 = canditer_next(&ci1) - b1hseqbase;
1283 0 : oid x2 = canditer_next(&ci2) - b2hseqbase;
1284 0 : const void *p1 = BUNtvar(b1i, x1);
1285 0 : const void *p2 = BUNtvar(b2i, x2);
1286 0 : if (cmp(p1, nil) == 0) {
1287 0 : if (cmp(p2, nil) == 0) {
1288 : /* both values are nil */
1289 : nils = true;
1290 : } else {
1291 0 : p1 = p2;
1292 : }
1293 : } else {
1294 0 : p1 = cmp(p2, nil) != 0 && cmp(p2, p1) < 0 ? p2 : p1;
1295 : }
1296 0 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
1297 0 : goto bailout;
1298 : }
1299 : }
1300 0 : TIMEOUT_CHECK(qry_ctx,
1301 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1302 : }
1303 : } else {
1304 0 : uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
1305 0 : uint16_t width = bn->twidth;
1306 0 : if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
1307 0 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1308 0 : oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
1309 0 : oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
1310 0 : const void *p1 = BUNtloc(b1i, x1);
1311 0 : const void *p2 = BUNtloc(b2i, x2);
1312 0 : if (cmp(p1, nil) == 0) {
1313 0 : if (cmp(p2, nil) == 0) {
1314 : /* both values are nil */
1315 : nils = true;
1316 : } else {
1317 0 : p1 = p2;
1318 : }
1319 : } else {
1320 0 : p1 = cmp(p2, nil) != 0 && cmp(p2, p1) < 0 ? p2 : p1;
1321 : }
1322 0 : memcpy(bcast, p1, width);
1323 0 : bcast += width;
1324 : }
1325 0 : TIMEOUT_CHECK(qry_ctx,
1326 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1327 : } else {
1328 0 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1329 0 : oid x1 = canditer_next(&ci1) - b1hseqbase;
1330 0 : oid x2 = canditer_next(&ci2) - b2hseqbase;
1331 0 : const void *p1 = BUNtloc(b1i, x1);
1332 0 : const void *p2 = BUNtloc(b2i, x2);
1333 0 : if (cmp(p1, nil) == 0) {
1334 0 : if (cmp(p2, nil) == 0) {
1335 : /* both values are nil */
1336 : nils = true;
1337 : } else {
1338 0 : p1 = p2;
1339 : }
1340 : } else {
1341 0 : p1 = cmp(p2, nil) != 0 && cmp(p2, p1) < 0 ? p2 : p1;
1342 : }
1343 0 : memcpy(bcast, p1, width);
1344 0 : bcast += width;
1345 : }
1346 0 : TIMEOUT_CHECK(qry_ctx,
1347 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1348 : }
1349 : }
1350 : }
1351 : }
1352 :
1353 41 : bn->tnil = nils;
1354 41 : bn->tnonil = !nils;
1355 41 : BATsetcount(bn, ci1.ncand);
1356 41 : if (ci1.ncand <= 1) {
1357 3 : bn->tsorted = true;
1358 3 : bn->trevsorted = true;
1359 3 : bn->tkey = true;
1360 3 : bn->tseqbase = ATOMtype(b1i.type) == TYPE_oid ? ci1.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
1361 : } else {
1362 38 : bn->tsorted = false;
1363 38 : bn->trevsorted = false;
1364 38 : bn->tkey = false;
1365 38 : bn->tseqbase = oid_nil;
1366 : }
1367 41 : bat_iterator_end(&b1i);
1368 41 : bat_iterator_end(&b2i);
1369 :
1370 41 : TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
1371 : ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
1372 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
1373 : ALGOBATPAR(b1), ALGOBATPAR(b2),
1374 : ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
1375 : ALGOOPTBATPAR(bn), GDKusec() - t0);
1376 :
1377 : return bn;
1378 0 : bailout:
1379 0 : bat_iterator_end(&b1i);
1380 0 : bat_iterator_end(&b2i);
1381 0 : BBPreclaim(bn);
1382 0 : return NULL;
1383 : }
1384 :
1385 : #define MINMAX_CST_TYPE(TYPE, OP) \
1386 : do { \
1387 : TYPE *restrict tb = bi.base, *restrict tbn = Tloc(bn, 0), pp2 = *(TYPE*) p2; \
1388 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) { \
1389 : oid x = canditer_next(&ci) - bhseqbase; \
1390 : TYPE p1 = tb[x]; \
1391 : if (is_##TYPE##_nil(p1)) { \
1392 : nils = true; \
1393 : tbn[i] = TYPE##_nil; \
1394 : } else { \
1395 : tbn[i] = p1 OP pp2 ? p1 : pp2; \
1396 : } \
1397 : } \
1398 : TIMEOUT_CHECK(qry_ctx, \
1399 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
1400 : } while (0)
1401 :
1402 : BAT *
1403 7 : BATcalcmincst(BAT *b, const ValRecord *v, BAT *s)
1404 : {
1405 7 : lng t0 = 0;
1406 7 : BAT *bn;
1407 7 : bool nils = false;
1408 7 : struct canditer ci;
1409 7 : const void *p2;
1410 7 : const void *restrict nil;
1411 7 : int (*cmp)(const void *, const void *);
1412 7 : oid bhseqbase;
1413 :
1414 7 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
1415 :
1416 6 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
1417 :
1418 6 : BATcheck(b, NULL);
1419 :
1420 6 : nil = ATOMnilptr(b->ttype);
1421 6 : cmp = ATOMcompare(b->ttype);
1422 6 : bhseqbase = b->hseqbase;
1423 12 : if (ATOMtype(b->ttype) != v->vtype) {
1424 0 : GDKerror("inputs have incompatible types\n");
1425 0 : return NULL;
1426 : }
1427 :
1428 6 : canditer_init(&ci, b, s);
1429 7 : p2 = VALptr(v);
1430 10 : if (ci.ncand == 0 ||
1431 3 : cmp(p2, nil) == 0 ||
1432 3 : (b->ttype == TYPE_void && is_oid_nil(b->tseqbase)))
1433 4 : return BATconstantV(ci.hseq, b->ttype, nil, ci.ncand, TRANSIENT);
1434 :
1435 6 : bn = COLnew(ci.hseq, ATOMtype(b->ttype), ci.ncand, TRANSIENT);
1436 3 : if (bn == NULL)
1437 : return NULL;
1438 :
1439 3 : BATiter bi = bat_iterator(b);
1440 6 : switch (ATOMbasetype(bi.type)) {
1441 0 : case TYPE_bte:
1442 0 : MINMAX_CST_TYPE(bte, <);
1443 : break;
1444 0 : case TYPE_sht:
1445 0 : MINMAX_CST_TYPE(sht, <);
1446 : break;
1447 0 : case TYPE_int:
1448 0 : MINMAX_CST_TYPE(int, <);
1449 : break;
1450 0 : case TYPE_lng:
1451 0 : MINMAX_CST_TYPE(lng, <);
1452 : break;
1453 : #ifdef HAVE_HGE
1454 0 : case TYPE_hge:
1455 0 : MINMAX_CST_TYPE(hge, <);
1456 : break;
1457 : #endif
1458 0 : case TYPE_flt:
1459 0 : MINMAX_CST_TYPE(flt, <);
1460 : break;
1461 0 : case TYPE_dbl:
1462 0 : MINMAX_CST_TYPE(dbl, <);
1463 : break;
1464 3 : default:
1465 3 : if (ATOMvarsized(bi.type)) {
1466 18 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) {
1467 12 : oid x = canditer_next(&ci) - bhseqbase;
1468 12 : const void *restrict p1 = BUNtvar(bi, x);
1469 12 : if (cmp(p1, nil) == 0) {
1470 : nils = true;
1471 : p1 = nil;
1472 : } else {
1473 12 : p1 = cmp(p1, p2) < 0 ? p1 : p2;
1474 : }
1475 12 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
1476 0 : goto bailout;
1477 : }
1478 : }
1479 2 : TIMEOUT_CHECK(qry_ctx,
1480 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1481 : } else {
1482 1 : uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
1483 1 : uint16_t width = bn->twidth;
1484 5 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) {
1485 2 : oid x = canditer_next(&ci) - bhseqbase;
1486 2 : const void *restrict p1 = BUNtloc(bi, x);
1487 2 : if (cmp(p1, nil) == 0) {
1488 : nils = true;
1489 : p1 = nil;
1490 : } else {
1491 2 : p1 = cmp(p1, p2) < 0 ? p1 : p2;
1492 : }
1493 2 : memcpy(bcast, p1, width);
1494 2 : bcast += width;
1495 : }
1496 1 : TIMEOUT_CHECK(qry_ctx,
1497 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1498 : }
1499 : }
1500 3 : bat_iterator_end(&bi);
1501 :
1502 3 : bn->tnil = nils;
1503 3 : bn->tnonil = !nils;
1504 3 : BATsetcount(bn, ci.ncand);
1505 3 : if (ci.ncand <= 1) {
1506 0 : bn->tsorted = true;
1507 0 : bn->trevsorted = true;
1508 0 : bn->tkey = true;
1509 0 : bn->tseqbase = ATOMtype(bn->ttype) == TYPE_oid ? ci.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
1510 : } else {
1511 3 : bn->tsorted = false;
1512 3 : bn->trevsorted = false;
1513 3 : bn->tkey = false;
1514 3 : bn->tseqbase = oid_nil;
1515 : }
1516 :
1517 3 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
1518 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
1519 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
1520 : ALGOOPTBATPAR(bn), GDKusec() - t0);
1521 :
1522 : return bn;
1523 0 : bailout:
1524 0 : bat_iterator_end(&bi);
1525 0 : BBPreclaim(bn);
1526 0 : return NULL;
1527 : }
1528 :
1529 : BAT *
1530 0 : BATcalccstmin(const ValRecord *v, BAT *b, BAT *s)
1531 : {
1532 0 : return BATcalcmincst(b, v, s);
1533 : }
1534 :
1535 : #define MINMAX_NONIL_CST_TYPE(TYPE, OP) \
1536 : do { \
1537 : TYPE *restrict tb = bi.base, *restrict tbn = Tloc(bn, 0), pp2 = *(TYPE*) p2; \
1538 : if (is_##TYPE##_nil(pp2)) { \
1539 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) { \
1540 : oid x = canditer_next(&ci) - bhseqbase; \
1541 : TYPE p1 = tb[x]; \
1542 : nils |= is_##TYPE##_nil(p1); \
1543 : tbn[i] = p1; \
1544 : } \
1545 : TIMEOUT_CHECK(qry_ctx, \
1546 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
1547 : } else { \
1548 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) { \
1549 : oid x = canditer_next(&ci) - bhseqbase; \
1550 : TYPE p1 = tb[x]; \
1551 : if (is_##TYPE##_nil(p1)) { \
1552 : tbn[i] = pp2; \
1553 : } else { \
1554 : tbn[i] = p1 OP pp2 ? p1 : pp2; \
1555 : } \
1556 : } \
1557 : TIMEOUT_CHECK(qry_ctx, \
1558 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
1559 : } \
1560 : } while (0)
1561 :
1562 : BAT *
1563 47 : BATcalcmincst_no_nil(BAT *b, const ValRecord *v, BAT *s)
1564 : {
1565 47 : lng t0 = 0;
1566 47 : BAT *bn;
1567 47 : bool nils = false;
1568 47 : struct canditer ci;
1569 47 : const void *p2;
1570 47 : const void *restrict nil;
1571 47 : int (*cmp)(const void *, const void *);
1572 47 : oid bhseqbase;
1573 :
1574 47 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
1575 :
1576 47 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
1577 :
1578 47 : BATcheck(b, NULL);
1579 :
1580 47 : nil = ATOMnilptr(b->ttype);
1581 47 : cmp = ATOMcompare(b->ttype);
1582 47 : bhseqbase = b->hseqbase;
1583 94 : if (ATOMtype(b->ttype) != v->vtype) {
1584 0 : GDKerror("inputs have incompatible types\n");
1585 0 : return NULL;
1586 : }
1587 :
1588 47 : canditer_init(&ci, b, s);
1589 47 : if (ci.ncand == 0)
1590 6 : return BATconstantV(ci.hseq, b->ttype, nil, ci.ncand, TRANSIENT);
1591 :
1592 41 : p2 = VALptr(v);
1593 41 : if (b->ttype == TYPE_void &&
1594 0 : is_oid_nil(b->tseqbase) &&
1595 0 : is_oid_nil(* (const oid *) p2))
1596 0 : return BATconstant(ci.hseq, TYPE_void, &oid_nil, ci.ncand, TRANSIENT);
1597 :
1598 82 : bn = COLnew(ci.hseq, ATOMtype(b->ttype), ci.ncand, TRANSIENT);
1599 41 : if (bn == NULL)
1600 : return NULL;
1601 :
1602 41 : BATiter bi = bat_iterator(b);
1603 78 : switch (ATOMbasetype(bi.type)) {
1604 4 : case TYPE_bte:
1605 37 : MINMAX_NONIL_CST_TYPE(bte, <);
1606 : break;
1607 5 : case TYPE_sht:
1608 22 : MINMAX_NONIL_CST_TYPE(sht, <);
1609 : break;
1610 8 : case TYPE_int:
1611 466 : MINMAX_NONIL_CST_TYPE(int, <);
1612 : break;
1613 2 : case TYPE_lng:
1614 40 : MINMAX_NONIL_CST_TYPE(lng, <);
1615 : break;
1616 : #ifdef HAVE_HGE
1617 8 : case TYPE_hge:
1618 24 : MINMAX_NONIL_CST_TYPE(hge, <);
1619 : break;
1620 : #endif
1621 0 : case TYPE_flt:
1622 0 : MINMAX_NONIL_CST_TYPE(flt, <);
1623 : break;
1624 9 : case TYPE_dbl:
1625 58 : MINMAX_NONIL_CST_TYPE(dbl, <);
1626 : break;
1627 5 : default:
1628 5 : if (ATOMvarsized(bi.type)) {
1629 4 : if (cmp(p2, nil) == 0) {
1630 0 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) {
1631 0 : oid x = canditer_next(&ci) - bhseqbase;
1632 0 : const void *restrict p1 = BUNtvar(bi, x);
1633 0 : nils |= cmp(p1, nil) == 0;
1634 0 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
1635 0 : goto bailout;
1636 : }
1637 : }
1638 0 : TIMEOUT_CHECK(qry_ctx,
1639 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1640 : } else {
1641 62 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) {
1642 54 : oid x = canditer_next(&ci) - bhseqbase;
1643 54 : const void *restrict p1 = BUNtvar(bi, x);
1644 54 : p1 = cmp(p1, nil) == 0 || cmp(p2, p1) < 0 ? p2 : p1;
1645 54 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
1646 0 : goto bailout;
1647 : }
1648 : }
1649 4 : TIMEOUT_CHECK(qry_ctx,
1650 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1651 : }
1652 : } else {
1653 1 : uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
1654 1 : uint16_t width = bn->twidth;
1655 1 : if (cmp(p2, nil) == 0) {
1656 0 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) {
1657 0 : oid x = canditer_next(&ci) - bhseqbase;
1658 0 : const void *restrict p1 = BUNtloc(bi, x);
1659 0 : nils |= cmp(p1, nil) == 0;
1660 0 : memcpy(bcast, p1, width);
1661 0 : bcast += width;
1662 : }
1663 0 : TIMEOUT_CHECK(qry_ctx,
1664 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1665 : } else {
1666 7 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) {
1667 4 : oid x = canditer_next(&ci) - bhseqbase;
1668 4 : const void *restrict p1 = BUNtloc(bi, x);
1669 4 : p1 = cmp(p1, nil) == 0 || cmp(p2, p1) < 0 ? p2 : p1;
1670 4 : memcpy(bcast, p1, width);
1671 4 : bcast += width;
1672 : }
1673 1 : TIMEOUT_CHECK(qry_ctx,
1674 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1675 : }
1676 : }
1677 : }
1678 41 : bat_iterator_end(&bi);
1679 :
1680 41 : bn->tnil = nils;
1681 41 : bn->tnonil = !nils;
1682 41 : BATsetcount(bn, ci.ncand);
1683 41 : if (ci.ncand <= 1) {
1684 12 : bn->tsorted = true;
1685 12 : bn->trevsorted = true;
1686 12 : bn->tkey = true;
1687 12 : bn->tseqbase = ATOMtype(bn->ttype) == TYPE_oid ? ci.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
1688 : } else {
1689 29 : bn->tsorted = false;
1690 29 : bn->trevsorted = false;
1691 29 : bn->tkey = false;
1692 29 : bn->tseqbase = oid_nil;
1693 : }
1694 :
1695 41 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
1696 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
1697 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
1698 : ALGOOPTBATPAR(bn), GDKusec() - t0);
1699 :
1700 : return bn;
1701 0 : bailout:
1702 0 : bat_iterator_end(&bi);
1703 0 : BBPreclaim(bn);
1704 0 : return NULL;
1705 : }
1706 :
1707 : BAT *
1708 32 : BATcalccstmin_no_nil(const ValRecord *v, BAT *b, BAT *s)
1709 : {
1710 32 : return BATcalcmincst_no_nil(b, v, s);
1711 : }
1712 :
1713 : BAT *
1714 6 : BATcalcmax(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
1715 : {
1716 6 : lng t0 = 0;
1717 6 : BAT *bn;
1718 6 : bool nils = false;
1719 6 : struct canditer ci1, ci2;
1720 6 : oid b1hseqbase, b2hseqbase;
1721 :
1722 6 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
1723 :
1724 6 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
1725 :
1726 6 : BATcheck(b1, NULL);
1727 6 : BATcheck(b2, NULL);
1728 :
1729 6 : b1hseqbase = b1->hseqbase;
1730 6 : b2hseqbase = b2->hseqbase;
1731 18 : if (ATOMtype(b1->ttype) != ATOMtype(b2->ttype)) {
1732 0 : GDKerror("inputs have incompatible types\n");
1733 0 : return NULL;
1734 : }
1735 :
1736 6 : canditer_init(&ci1, b1, s1);
1737 6 : canditer_init(&ci2, b2, s2);
1738 6 : if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
1739 0 : GDKerror("inputs not the same size.\n");
1740 0 : return NULL;
1741 : }
1742 :
1743 12 : bn = COLnew(ci1.hseq, ATOMtype(b1->ttype), ci1.ncand, TRANSIENT);
1744 6 : if (bn == NULL)
1745 : return NULL;
1746 :
1747 6 : BATiter b1i = bat_iterator(b1);
1748 6 : BATiter b2i = bat_iterator(b2);
1749 12 : switch (ATOMbasetype(b1i.type)) {
1750 0 : case TYPE_bte:
1751 0 : MINMAX_TYPE(bte, >);
1752 : break;
1753 0 : case TYPE_sht:
1754 0 : MINMAX_TYPE(sht, >);
1755 : break;
1756 1 : case TYPE_int:
1757 10 : MINMAX_TYPE(int, >);
1758 : break;
1759 0 : case TYPE_lng:
1760 0 : MINMAX_TYPE(lng, >);
1761 : break;
1762 : #ifdef HAVE_HGE
1763 0 : case TYPE_hge:
1764 0 : MINMAX_TYPE(hge, >);
1765 : break;
1766 : #endif
1767 0 : case TYPE_flt:
1768 0 : MINMAX_TYPE(flt, >);
1769 : break;
1770 0 : case TYPE_dbl:
1771 0 : MINMAX_TYPE(dbl, >);
1772 : break;
1773 5 : default: {
1774 5 : const void *restrict nil = ATOMnilptr(b1i.type);
1775 5 : int (*cmp)(const void *, const void *) = ATOMcompare(b1i.type);
1776 :
1777 5 : if (ATOMvarsized(b1i.type)) {
1778 4 : if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
1779 75 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1780 63 : oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
1781 63 : oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
1782 63 : const void *p1 = BUNtvar(b1i, x1);
1783 63 : const void *p2 = BUNtvar(b2i, x2);
1784 63 : if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
1785 : nils = true;
1786 : p1 = nil;
1787 : } else {
1788 21 : p1 = cmp(p1, p2) > 0 ? p1 : p2;
1789 : }
1790 63 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
1791 0 : goto bailout;
1792 : }
1793 : }
1794 4 : TIMEOUT_CHECK(qry_ctx,
1795 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1796 : } else {
1797 0 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1798 0 : oid x1 = canditer_next(&ci1) - b1hseqbase;
1799 0 : oid x2 = canditer_next(&ci2) - b2hseqbase;
1800 0 : const void *p1 = BUNtvar(b1i, x1);
1801 0 : const void *p2 = BUNtvar(b2i, x2);
1802 0 : if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
1803 : nils = true;
1804 : p1 = nil;
1805 : } else {
1806 0 : p1 = cmp(p1, p2) > 0 ? p1 : p2;
1807 : }
1808 0 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
1809 0 : goto bailout;
1810 : }
1811 : }
1812 0 : TIMEOUT_CHECK(qry_ctx,
1813 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1814 : }
1815 : } else {
1816 1 : uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
1817 1 : uint16_t width = bn->twidth;
1818 1 : if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
1819 5 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1820 2 : oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
1821 2 : oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
1822 2 : const void *p1 = BUNtloc(b1i, x1);
1823 2 : const void *p2 = BUNtloc(b2i, x2);
1824 2 : if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
1825 : nils = true;
1826 : p1 = nil;
1827 : } else {
1828 2 : p1 = cmp(p1, p2) > 0 ? p1 : p2;
1829 : }
1830 2 : memcpy(bcast, p1, width);
1831 2 : bcast += width;
1832 : }
1833 1 : TIMEOUT_CHECK(qry_ctx,
1834 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1835 : } else {
1836 0 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1837 0 : oid x1 = canditer_next(&ci1) - b1hseqbase;
1838 0 : oid x2 = canditer_next(&ci2) - b2hseqbase;
1839 0 : const void *p1 = BUNtloc(b1i, x1);
1840 0 : const void *p2 = BUNtloc(b2i, x2);
1841 0 : if (cmp(p1, nil) == 0 || cmp(p2, nil) == 0) {
1842 : nils = true;
1843 : p1 = nil;
1844 : } else {
1845 0 : p1 = cmp(p1, p2) > 0 ? p1 : p2;
1846 : }
1847 0 : memcpy(bcast, p1, width);
1848 0 : bcast += width;
1849 : }
1850 0 : TIMEOUT_CHECK(qry_ctx,
1851 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1852 : }
1853 : }
1854 : }
1855 : }
1856 :
1857 6 : bn->tnil = nils;
1858 6 : bn->tnonil = !nils;
1859 6 : BATsetcount(bn, ci1.ncand);
1860 6 : if (ci1.ncand <= 1) {
1861 0 : bn->tsorted = true;
1862 0 : bn->trevsorted = true;
1863 0 : bn->tkey = true;
1864 0 : bn->tseqbase = ATOMtype(b1i.type) == TYPE_oid ? ci1.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
1865 : } else {
1866 6 : bn->tsorted = false;
1867 6 : bn->trevsorted = false;
1868 6 : bn->tkey = false;
1869 6 : bn->tseqbase = oid_nil;
1870 : }
1871 6 : bat_iterator_end(&b1i);
1872 6 : bat_iterator_end(&b2i);
1873 :
1874 6 : TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
1875 : ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
1876 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
1877 : ALGOBATPAR(b1), ALGOBATPAR(b2),
1878 : ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
1879 : ALGOOPTBATPAR(bn), GDKusec() - t0);
1880 :
1881 : return bn;
1882 0 : bailout:
1883 0 : bat_iterator_end(&b1i);
1884 0 : bat_iterator_end(&b2i);
1885 0 : BBPreclaim(bn);
1886 0 : return NULL;
1887 : }
1888 :
1889 : BAT *
1890 8 : BATcalcmax_no_nil(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
1891 : {
1892 8 : lng t0 = 0;
1893 8 : BAT *bn;
1894 8 : bool nils = false;
1895 8 : struct canditer ci1, ci2;
1896 8 : oid b1hseqbase, b2hseqbase;
1897 :
1898 8 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
1899 :
1900 8 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
1901 :
1902 8 : BATcheck(b1, NULL);
1903 8 : BATcheck(b2, NULL);
1904 :
1905 8 : b1hseqbase = b1->hseqbase;
1906 8 : b2hseqbase = b2->hseqbase;
1907 24 : if (ATOMtype(b1->ttype) != ATOMtype(b2->ttype)) {
1908 0 : GDKerror("inputs have incompatible types\n");
1909 0 : return NULL;
1910 : }
1911 :
1912 8 : canditer_init(&ci1, b1, s1);
1913 8 : canditer_init(&ci2, b2, s2);
1914 8 : if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
1915 0 : GDKerror("inputs not the same size.\n");
1916 0 : return NULL;
1917 : }
1918 :
1919 16 : bn = COLnew(ci1.hseq, ATOMtype(b1->ttype), ci1.ncand, TRANSIENT);
1920 8 : if (bn == NULL)
1921 : return NULL;
1922 :
1923 8 : BATiter b1i = bat_iterator(b1);
1924 8 : BATiter b2i = bat_iterator(b2);
1925 16 : switch (ATOMbasetype(b1i.type)) {
1926 0 : case TYPE_bte:
1927 0 : MINMAX_NONIL_TYPE(bte, >);
1928 : break;
1929 0 : case TYPE_sht:
1930 0 : MINMAX_NONIL_TYPE(sht, >);
1931 : break;
1932 1 : case TYPE_int:
1933 4 : MINMAX_NONIL_TYPE(int, >);
1934 : break;
1935 1 : case TYPE_lng:
1936 16 : MINMAX_NONIL_TYPE(lng, >);
1937 : break;
1938 : #ifdef HAVE_HGE
1939 0 : case TYPE_hge:
1940 0 : MINMAX_NONIL_TYPE(hge, >);
1941 : break;
1942 : #endif
1943 0 : case TYPE_flt:
1944 0 : MINMAX_NONIL_TYPE(flt, >);
1945 : break;
1946 2 : case TYPE_dbl:
1947 6086 : MINMAX_NONIL_TYPE(dbl, >);
1948 : break;
1949 4 : default: {
1950 4 : const void *restrict nil = ATOMnilptr(b1i.type);
1951 4 : int (*cmp)(const void *, const void *) = ATOMcompare(b1i.type);
1952 :
1953 4 : if (ATOMvarsized(b1i.type)) {
1954 3 : if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
1955 18 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1956 9 : oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
1957 9 : oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
1958 9 : const void *p1, *p2;
1959 9 : p1 = BUNtvar(b1i, x1);
1960 9 : p2 = BUNtvar(b2i, x2);
1961 9 : if (cmp(p1, nil) == 0) {
1962 0 : if (cmp(p2, nil) == 0) {
1963 : /* both values are nil */
1964 : nils = true;
1965 : } else {
1966 0 : p1 = p2;
1967 : }
1968 : } else {
1969 9 : p1 = cmp(p2, nil) != 0 && cmp(p2, p1) > 0 ? p2 : p1;
1970 : }
1971 9 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
1972 0 : goto bailout;
1973 : }
1974 : }
1975 3 : TIMEOUT_CHECK(qry_ctx,
1976 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
1977 : } else {
1978 0 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
1979 0 : oid x1 = canditer_next(&ci1) - b1hseqbase;
1980 0 : oid x2 = canditer_next(&ci2) - b2hseqbase;
1981 0 : const void *p1, *p2;
1982 0 : p1 = BUNtvar(b1i, x1);
1983 0 : p2 = BUNtvar(b2i, x2);
1984 0 : if (cmp(p1, nil) == 0) {
1985 0 : if (cmp(p2, nil) == 0) {
1986 : /* both values are nil */
1987 : nils = true;
1988 : } else {
1989 0 : p1 = p2;
1990 : }
1991 : } else {
1992 0 : p1 = cmp(p2, nil) != 0 && cmp(p2, p1) > 0 ? p2 : p1;
1993 : }
1994 0 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
1995 0 : goto bailout;
1996 : }
1997 : }
1998 0 : TIMEOUT_CHECK(qry_ctx,
1999 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
2000 : }
2001 : } else {
2002 1 : uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
2003 1 : uint16_t width = bn->twidth;
2004 1 : if (ci1.tpe == cand_dense && ci2.tpe == cand_dense) {
2005 4 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
2006 1 : oid x1 = canditer_next_dense(&ci1) - b1hseqbase;
2007 1 : oid x2 = canditer_next_dense(&ci2) - b2hseqbase;
2008 1 : const void *p1, *p2;
2009 1 : p1 = BUNtloc(b1i, x1);
2010 1 : p2 = BUNtloc(b2i, x2);
2011 1 : if (cmp(p1, nil) == 0) {
2012 0 : if (cmp(p2, nil) == 0) {
2013 : /* both values are nil */
2014 : nils = true;
2015 : } else {
2016 0 : p1 = p2;
2017 : }
2018 : } else {
2019 1 : p1 = cmp(p2, nil) != 0 && cmp(p2, p1) > 0 ? p2 : p1;
2020 : }
2021 1 : memcpy(bcast, p1, width);
2022 1 : bcast += width;
2023 : }
2024 1 : TIMEOUT_CHECK(qry_ctx,
2025 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
2026 : } else {
2027 0 : TIMEOUT_LOOP_IDX_DECL(i, ci1.ncand, qry_ctx) {
2028 0 : oid x1 = canditer_next(&ci1) - b1hseqbase;
2029 0 : oid x2 = canditer_next(&ci2) - b2hseqbase;
2030 0 : const void *p1, *p2;
2031 0 : p1 = BUNtloc(b1i, x1);
2032 0 : p2 = BUNtloc(b2i, x2);
2033 0 : if (cmp(p1, nil) == 0) {
2034 0 : if (cmp(p2, nil) == 0) {
2035 : /* both values are nil */
2036 : nils = true;
2037 : } else {
2038 0 : p1 = p2;
2039 : }
2040 : } else {
2041 0 : p1 = cmp(p2, nil) != 0 && cmp(p2, p1) > 0 ? p2 : p1;
2042 : }
2043 0 : memcpy(bcast, p1, width);
2044 0 : bcast += width;
2045 : }
2046 0 : TIMEOUT_CHECK(qry_ctx,
2047 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
2048 : }
2049 : }
2050 : }
2051 : }
2052 :
2053 8 : bn->tnil = nils;
2054 8 : bn->tnonil = !nils;
2055 8 : BATsetcount(bn, ci1.ncand);
2056 8 : if (ci1.ncand <= 1) {
2057 2 : bn->tsorted = true;
2058 2 : bn->trevsorted = true;
2059 2 : bn->tkey = true;
2060 2 : bn->tseqbase = ATOMtype(b1i.type) == TYPE_oid ? ci1.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
2061 : } else {
2062 6 : bn->tsorted = false;
2063 6 : bn->trevsorted = false;
2064 6 : bn->tkey = false;
2065 6 : bn->tseqbase = oid_nil;
2066 : }
2067 8 : bat_iterator_end(&b1i);
2068 8 : bat_iterator_end(&b2i);
2069 :
2070 8 : TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
2071 : ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
2072 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
2073 : ALGOBATPAR(b1), ALGOBATPAR(b2),
2074 : ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
2075 : ALGOOPTBATPAR(bn), GDKusec() - t0);
2076 :
2077 : return bn;
2078 0 : bailout:
2079 0 : bat_iterator_end(&b1i);
2080 0 : bat_iterator_end(&b2i);
2081 0 : BBPreclaim(bn);
2082 0 : return NULL;
2083 : }
2084 :
2085 : BAT *
2086 4 : BATcalcmaxcst(BAT *b, const ValRecord *v, BAT *s)
2087 : {
2088 4 : lng t0 = 0;
2089 4 : BAT *bn;
2090 4 : bool nils = false;
2091 4 : struct canditer ci;
2092 4 : const void *p2;
2093 4 : const void *restrict nil;
2094 4 : int (*cmp)(const void *, const void *);
2095 4 : oid bhseqbase;
2096 :
2097 4 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
2098 :
2099 4 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
2100 :
2101 4 : BATcheck(b, NULL);
2102 :
2103 4 : nil = ATOMnilptr(b->ttype);
2104 4 : cmp = ATOMcompare(b->ttype);
2105 4 : bhseqbase = b->hseqbase;
2106 8 : if (ATOMtype(b->ttype) != v->vtype) {
2107 0 : GDKerror("inputs have incompatible types\n");
2108 0 : return NULL;
2109 : }
2110 :
2111 4 : canditer_init(&ci, b, s);
2112 4 : p2 = VALptr(v);
2113 8 : if (ci.ncand == 0 ||
2114 4 : cmp(p2, nil) == 0 ||
2115 4 : (b->ttype == TYPE_void && is_oid_nil(b->tseqbase)))
2116 0 : return BATconstantV(ci.hseq, b->ttype, nil, ci.ncand, TRANSIENT);
2117 :
2118 8 : bn = COLnew(ci.hseq, ATOMtype(b->ttype), ci.ncand, TRANSIENT);
2119 4 : if (bn == NULL)
2120 : return NULL;
2121 :
2122 4 : BATiter bi = bat_iterator(b);
2123 6 : switch (ATOMbasetype(bi.type)) {
2124 2 : case TYPE_bte:
2125 8 : MINMAX_CST_TYPE(bte, >);
2126 : break;
2127 0 : case TYPE_sht:
2128 0 : MINMAX_CST_TYPE(sht, >);
2129 : break;
2130 0 : case TYPE_int:
2131 0 : MINMAX_CST_TYPE(int, >);
2132 : break;
2133 1 : case TYPE_lng:
2134 16 : MINMAX_CST_TYPE(lng, >);
2135 : break;
2136 : #ifdef HAVE_HGE
2137 0 : case TYPE_hge:
2138 0 : MINMAX_CST_TYPE(hge, >);
2139 : break;
2140 : #endif
2141 0 : case TYPE_flt:
2142 0 : MINMAX_CST_TYPE(flt, >);
2143 : break;
2144 0 : case TYPE_dbl:
2145 0 : MINMAX_CST_TYPE(dbl, >);
2146 : break;
2147 1 : default:
2148 1 : if (ATOMvarsized(bi.type)) {
2149 4 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) {
2150 1 : oid x = canditer_next(&ci) - bhseqbase;
2151 1 : const void *restrict p1 = BUNtvar(bi, x);
2152 1 : if (cmp(p1, nil) == 0) {
2153 : nils = true;
2154 : p1 = nil;
2155 : } else {
2156 0 : p1 = cmp(p1, p2) > 0 ? p1 : p2;
2157 : }
2158 1 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
2159 0 : goto bailout;
2160 : }
2161 : }
2162 1 : TIMEOUT_CHECK(qry_ctx,
2163 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
2164 : } else {
2165 0 : uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
2166 0 : uint16_t width = bn->twidth;
2167 0 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) {
2168 0 : oid x = canditer_next(&ci) - bhseqbase;
2169 0 : const void *restrict p1 = BUNtloc(bi, x);
2170 0 : if (cmp(p1, nil) == 0) {
2171 : nils = true;
2172 : p1 = nil;
2173 : } else {
2174 0 : p1 = cmp(p1, p2) > 0 ? p1 : p2;
2175 : }
2176 0 : memcpy(bcast, p1, width);
2177 0 : bcast += width;
2178 : }
2179 0 : TIMEOUT_CHECK(qry_ctx,
2180 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
2181 : }
2182 : }
2183 4 : bat_iterator_end(&bi);
2184 :
2185 4 : bn->tnil = nils;
2186 4 : bn->tnonil = !nils;
2187 4 : BATsetcount(bn, ci.ncand);
2188 4 : if (ci.ncand <= 1) {
2189 3 : bn->tsorted = true;
2190 3 : bn->trevsorted = true;
2191 3 : bn->tkey = true;
2192 3 : bn->tseqbase = ATOMtype(bn->ttype) == TYPE_oid ? ci.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
2193 : } else {
2194 1 : bn->tsorted = false;
2195 1 : bn->trevsorted = false;
2196 1 : bn->tkey = false;
2197 1 : bn->tseqbase = oid_nil;
2198 : }
2199 :
2200 4 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
2201 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
2202 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
2203 : ALGOOPTBATPAR(bn), GDKusec() - t0);
2204 :
2205 : return bn;
2206 0 : bailout:
2207 0 : bat_iterator_end(&bi);
2208 0 : BBPreclaim(bn);
2209 0 : return NULL;
2210 : }
2211 :
2212 : BAT *
2213 4 : BATcalccstmax(const ValRecord *v, BAT *b, BAT *s)
2214 : {
2215 4 : return BATcalcmaxcst(b, v, s);
2216 : }
2217 :
2218 : BAT *
2219 10 : BATcalcmaxcst_no_nil(BAT *b, const ValRecord *v, BAT *s)
2220 : {
2221 10 : lng t0 = 0;
2222 10 : BAT *bn;
2223 10 : bool nils = false;
2224 10 : struct canditer ci;
2225 10 : const void *p2;
2226 10 : const void *restrict nil;
2227 10 : int (*cmp)(const void *, const void *);
2228 10 : oid bhseqbase;
2229 :
2230 10 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
2231 :
2232 10 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
2233 :
2234 10 : BATcheck(b, NULL);
2235 :
2236 10 : nil = ATOMnilptr(b->ttype);
2237 10 : cmp = ATOMcompare(b->ttype);
2238 10 : bhseqbase = b->hseqbase;
2239 20 : if (ATOMtype(b->ttype) != v->vtype) {
2240 0 : GDKerror("inputs have incompatible types\n");
2241 0 : return NULL;
2242 : }
2243 :
2244 10 : canditer_init(&ci, b, s);
2245 10 : if (ci.ncand == 0)
2246 1 : return BATconstantV(ci.hseq, b->ttype, nil, ci.ncand, TRANSIENT);
2247 :
2248 9 : cmp = ATOMcompare(b->ttype);
2249 9 : p2 = VALptr(v);
2250 9 : if (b->ttype == TYPE_void &&
2251 0 : is_oid_nil(b->tseqbase) &&
2252 0 : is_oid_nil(* (const oid *) p2))
2253 0 : return BATconstant(ci.hseq, TYPE_void, &oid_nil, ci.ncand, TRANSIENT);
2254 :
2255 18 : bn = COLnew(ci.hseq, ATOMtype(b->ttype), ci.ncand, TRANSIENT);
2256 9 : if (bn == NULL)
2257 : return NULL;
2258 :
2259 9 : BATiter bi = bat_iterator(b);
2260 13 : switch (ATOMbasetype(bi.type)) {
2261 5 : case TYPE_bte:
2262 15 : MINMAX_NONIL_CST_TYPE(bte, >);
2263 : break;
2264 0 : case TYPE_sht:
2265 0 : MINMAX_NONIL_CST_TYPE(sht, >);
2266 : break;
2267 2 : case TYPE_int:
2268 8 : MINMAX_NONIL_CST_TYPE(int, >);
2269 : break;
2270 2 : case TYPE_lng:
2271 66 : MINMAX_NONIL_CST_TYPE(lng, >);
2272 : break;
2273 : #ifdef HAVE_HGE
2274 0 : case TYPE_hge:
2275 0 : MINMAX_NONIL_CST_TYPE(hge, >);
2276 : break;
2277 : #endif
2278 0 : case TYPE_flt:
2279 0 : MINMAX_NONIL_CST_TYPE(flt, >);
2280 : break;
2281 0 : case TYPE_dbl:
2282 0 : MINMAX_NONIL_CST_TYPE(dbl, >);
2283 : break;
2284 0 : default:
2285 0 : if (ATOMvarsized(bi.type)) {
2286 0 : if (cmp(p2, nil) == 0) {
2287 0 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) {
2288 0 : oid x = canditer_next(&ci) - bhseqbase;
2289 0 : const void *restrict p1 = BUNtvar(bi, x);
2290 0 : nils |= cmp(p1, nil) == 0;
2291 0 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
2292 0 : goto bailout;
2293 : }
2294 : }
2295 0 : TIMEOUT_CHECK(qry_ctx,
2296 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
2297 : } else {
2298 0 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) {
2299 0 : oid x = canditer_next(&ci) - bhseqbase;
2300 0 : const void *restrict p1 = BUNtvar(bi, x);
2301 0 : p1 = cmp(p1, nil) == 0 || cmp(p2, p1) > 0 ? p2 : p1;
2302 0 : if (tfastins_nocheckVAR(bn, i, p1) != GDK_SUCCEED) {
2303 0 : goto bailout;
2304 : }
2305 : }
2306 0 : TIMEOUT_CHECK(qry_ctx,
2307 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
2308 : }
2309 : } else {
2310 0 : uint8_t *restrict bcast = (uint8_t *) Tloc(bn, 0);
2311 0 : uint16_t width = bn->twidth;
2312 0 : if (cmp(p2, nil) == 0) {
2313 0 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) {
2314 0 : oid x = canditer_next(&ci) - bhseqbase;
2315 0 : const void *restrict p1 = BUNtloc(bi, x);
2316 0 : nils |= cmp(p1, nil) == 0;
2317 0 : memcpy(bcast, p1, width);
2318 0 : bcast += width;
2319 : }
2320 0 : TIMEOUT_CHECK(qry_ctx,
2321 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
2322 : } else {
2323 0 : TIMEOUT_LOOP_IDX_DECL(i, ci.ncand, qry_ctx) {
2324 0 : oid x = canditer_next(&ci) - bhseqbase;
2325 0 : const void *restrict p1 = BUNtloc(bi, x);
2326 0 : p1 = cmp(p1, nil) == 0 || cmp(p2, p1) > 0 ? p2 : p1;
2327 0 : memcpy(bcast, p1, width);
2328 0 : bcast += width;
2329 : }
2330 0 : TIMEOUT_CHECK(qry_ctx,
2331 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
2332 : }
2333 : }
2334 : }
2335 9 : bat_iterator_end(&bi);
2336 :
2337 9 : bn->tnil = nils;
2338 9 : bn->tnonil = !nils;
2339 9 : BATsetcount(bn, ci.ncand);
2340 9 : if (ci.ncand <= 1) {
2341 5 : bn->tsorted = true;
2342 5 : bn->trevsorted = true;
2343 5 : bn->tkey = true;
2344 5 : bn->tseqbase = ATOMtype(bn->ttype) == TYPE_oid ? ci.ncand == 1 ? *(oid*)Tloc(bn,0) : 0 : oid_nil;
2345 : } else {
2346 4 : bn->tsorted = false;
2347 4 : bn->trevsorted = false;
2348 4 : bn->tkey = false;
2349 4 : bn->tseqbase = oid_nil;
2350 : }
2351 :
2352 9 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
2353 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
2354 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
2355 : ALGOOPTBATPAR(bn), GDKusec() - t0);
2356 :
2357 : return bn;
2358 0 : bailout:
2359 0 : bat_iterator_end(&bi);
2360 0 : BBPreclaim(bn);
2361 0 : return NULL;
2362 : }
2363 :
2364 : BAT *
2365 0 : BATcalccstmax_no_nil(const ValRecord *v, BAT *b, BAT *s)
2366 : {
2367 0 : return BATcalcmaxcst_no_nil(b, v, s);
2368 : }
2369 :
2370 : /* ---------------------------------------------------------------------- */
2371 : /* logical (for type bit) or bitwise (for integral types) exclusive OR */
2372 :
2373 : #define XOR(a, b) ((a) ^ (b))
2374 : #define XORBIT(a, b) (((a) == 0) != ((b) == 0))
2375 :
2376 : static BUN
2377 33 : xor_typeswitchloop(const void *lft, bool incr1,
2378 : const void *rgt, bool incr2,
2379 : void *restrict dst, int tp,
2380 : struct canditer *restrict ci1,
2381 : struct canditer *restrict ci2,
2382 : oid candoff1, oid candoff2,
2383 : bool nonil, const char *func)
2384 : {
2385 33 : BUN i, j, k;
2386 33 : BUN nils = 0;
2387 :
2388 33 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
2389 :
2390 65 : switch (ATOMbasetype(tp)) {
2391 17 : case TYPE_bte:
2392 17 : if (tp == TYPE_bit) {
2393 1 : if (nonil)
2394 0 : BINARY_3TYPE_FUNC_nonil(bit, bit, bit, XORBIT);
2395 : else
2396 12 : BINARY_3TYPE_FUNC(bit, bit, bit, XORBIT);
2397 : } else {
2398 16 : if (nonil)
2399 13 : BINARY_3TYPE_FUNC_nonil_nilcheck(bte, bte, bte, XOR, ON_OVERFLOW(bte, bte, "XOR"));
2400 : else
2401 82 : BINARY_3TYPE_FUNC_nilcheck(bte, bte, bte, XOR, ON_OVERFLOW(bte, bte, "XOR"));
2402 : }
2403 : break;
2404 1 : case TYPE_sht:
2405 1 : if (nonil)
2406 0 : BINARY_3TYPE_FUNC_nonil_nilcheck(sht, sht, sht, XOR, ON_OVERFLOW(sht, sht, "XOR"));
2407 : else
2408 4 : BINARY_3TYPE_FUNC_nilcheck(sht, sht, sht, XOR, ON_OVERFLOW(sht, sht, "XOR"));
2409 : break;
2410 10 : case TYPE_int:
2411 10 : if (nonil)
2412 0 : BINARY_3TYPE_FUNC_nonil_nilcheck(int, int, int, XOR, ON_OVERFLOW(int, int, "XOR"));
2413 : else
2414 40 : BINARY_3TYPE_FUNC_nilcheck(int, int, int, XOR, ON_OVERFLOW(int, int, "XOR"));
2415 : break;
2416 2 : case TYPE_lng:
2417 2 : if (nonil)
2418 1 : BINARY_3TYPE_FUNC_nonil_nilcheck(lng, lng, lng, XOR, ON_OVERFLOW(lng, lng, "XOR"));
2419 : else
2420 1 : BINARY_3TYPE_FUNC_nilcheck(lng, lng, lng, XOR, ON_OVERFLOW(lng, lng, "XOR"));
2421 : break;
2422 : #ifdef HAVE_HGE
2423 3 : case TYPE_hge:
2424 3 : if (nonil)
2425 0 : BINARY_3TYPE_FUNC_nonil_nilcheck(hge, hge, hge, XOR, ON_OVERFLOW(hge, hge, "XOR"));
2426 : else
2427 32781 : BINARY_3TYPE_FUNC_nilcheck(hge, hge, hge, XOR, ON_OVERFLOW(hge, hge, "XOR"));
2428 : break;
2429 : #endif
2430 0 : default:
2431 0 : GDKerror("%s: bad input type %s.\n", func, ATOMname(tp));
2432 0 : return BUN_NONE;
2433 : }
2434 :
2435 : return nils;
2436 : }
2437 :
2438 : BAT *
2439 11 : BATcalcxor(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
2440 : {
2441 11 : lng t0 = 0;
2442 11 : BAT *bn;
2443 11 : BUN nils;
2444 11 : struct canditer ci1, ci2;
2445 :
2446 11 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
2447 :
2448 11 : BATcheck(b1, NULL);
2449 11 : BATcheck(b2, NULL);
2450 :
2451 31 : if (ATOMbasetype(b1->ttype) != ATOMbasetype(b2->ttype)) {
2452 0 : GDKerror("incompatible input types.\n");
2453 0 : return NULL;
2454 : }
2455 :
2456 11 : canditer_init(&ci1, b1, s1);
2457 11 : canditer_init(&ci2, b2, s2);
2458 11 : if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
2459 0 : GDKerror("inputs not the same size.\n");
2460 0 : return NULL;
2461 : }
2462 :
2463 11 : bn = COLnew(ci1.hseq, b1->ttype, ci1.ncand, TRANSIENT);
2464 11 : if (bn == NULL)
2465 : return NULL;
2466 11 : if (ci1.ncand == 0)
2467 : return bn;
2468 :
2469 1 : BATiter b1i = bat_iterator(b1);
2470 1 : BATiter b2i = bat_iterator(b2);
2471 3 : nils = xor_typeswitchloop(b1i.base, true,
2472 1 : b2i.base, true,
2473 1 : Tloc(bn, 0),
2474 1 : b1i.type,
2475 : &ci1, &ci2,
2476 : b1->hseqbase, b2->hseqbase,
2477 1 : b1i.nonil && b2i.nonil,
2478 : __func__);
2479 1 : bat_iterator_end(&b1i);
2480 1 : bat_iterator_end(&b2i);
2481 :
2482 1 : if (nils == BUN_NONE) {
2483 0 : BBPunfix(bn->batCacheid);
2484 0 : return NULL;
2485 : }
2486 :
2487 1 : BATsetcount(bn, ci1.ncand);
2488 :
2489 1 : bn->tsorted = ci1.ncand <= 1 || nils == ci1.ncand;
2490 1 : bn->trevsorted = ci1.ncand <= 1 || nils == ci1.ncand;
2491 1 : bn->tkey = ci1.ncand <= 1;
2492 1 : bn->tnil = nils != 0;
2493 1 : bn->tnonil = nils == 0;
2494 :
2495 1 : TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
2496 : ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
2497 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
2498 : ALGOBATPAR(b1), ALGOBATPAR(b2),
2499 : ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
2500 : ALGOOPTBATPAR(bn), GDKusec() - t0);
2501 :
2502 : return bn;
2503 : }
2504 :
2505 : BAT *
2506 6 : BATcalcxorcst(BAT *b, const ValRecord *v, BAT *s)
2507 : {
2508 6 : lng t0 = 0;
2509 6 : BAT *bn;
2510 6 : BUN nils;
2511 6 : struct canditer ci;
2512 :
2513 6 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
2514 :
2515 6 : BATcheck(b, NULL);
2516 :
2517 18 : if (ATOMbasetype(b->ttype) != ATOMbasetype(v->vtype)) {
2518 0 : GDKerror("incompatible input types.\n");
2519 0 : return NULL;
2520 : }
2521 :
2522 6 : canditer_init(&ci, b, s);
2523 :
2524 6 : bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
2525 6 : if (bn == NULL)
2526 : return NULL;
2527 6 : if (ci.ncand == 0)
2528 : return bn;
2529 :
2530 6 : BATiter bi = bat_iterator(b);
2531 18 : nils = xor_typeswitchloop(bi.base, true,
2532 : VALptr(v), false,
2533 6 : Tloc(bn, 0), bi.type,
2534 : &ci,
2535 6 : &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
2536 : b->hseqbase, 0,
2537 6 : bi.nonil && ATOMcmp(v->vtype, VALptr(v), ATOMnilptr(v->vtype)) != 0,
2538 : __func__);
2539 6 : bat_iterator_end(&bi);
2540 :
2541 6 : if (nils == BUN_NONE) {
2542 2 : BBPunfix(bn->batCacheid);
2543 2 : return NULL;
2544 : }
2545 :
2546 4 : BATsetcount(bn, ci.ncand);
2547 :
2548 4 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
2549 4 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
2550 4 : bn->tkey = ci.ncand <= 1;
2551 4 : bn->tnil = nils != 0;
2552 4 : bn->tnonil = nils == 0;
2553 :
2554 4 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
2555 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
2556 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
2557 : ALGOOPTBATPAR(bn), GDKusec() - t0);
2558 :
2559 : return bn;
2560 : }
2561 :
2562 : BAT *
2563 0 : BATcalccstxor(const ValRecord *v, BAT *b, BAT *s)
2564 : {
2565 0 : return BATcalcxorcst(b, v, s);
2566 : }
2567 :
2568 : gdk_return
2569 26 : VARcalcxor(ValPtr ret, const ValRecord *lft, const ValRecord *rgt)
2570 : {
2571 78 : if (ATOMbasetype(lft->vtype) != ATOMbasetype(rgt->vtype)) {
2572 0 : GDKerror("incompatible input types.\n");
2573 0 : return GDK_FAIL;
2574 : }
2575 :
2576 26 : ret->bat = false;
2577 26 : if (xor_typeswitchloop(VALptr(lft), false,
2578 : VALptr(rgt), false,
2579 : VALget(ret), lft->vtype,
2580 26 : &(struct canditer){.tpe=cand_dense, .ncand=1},
2581 26 : &(struct canditer){.tpe=cand_dense, .ncand=1},
2582 : 0, 0, false, __func__) == BUN_NONE)
2583 0 : return GDK_FAIL;
2584 26 : return GDK_SUCCEED;
2585 : }
2586 :
2587 : /* ---------------------------------------------------------------------- */
2588 : /* logical (for type bit) or bitwise (for integral types) OR */
2589 :
2590 : #define or3(a,b) ((a) == 1 || (b) == 1 ? 1 : is_bit_nil(a) || is_bit_nil(b) ? bit_nil : 0)
2591 :
2592 : #define OR(a, b) ((a) | (b))
2593 :
2594 : static BUN
2595 1205506 : or_typeswitchloop(const void *lft, bool incr1,
2596 : const void *rgt, bool incr2,
2597 : void *restrict dst, int tp,
2598 : struct canditer *restrict ci1,
2599 : struct canditer *restrict ci2,
2600 : oid candoff1, oid candoff2,
2601 : bool nonil, const char *func)
2602 : {
2603 1205506 : BUN i = 0, j = 0, k;
2604 1205506 : BUN nils = 0;
2605 :
2606 1205506 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
2607 :
2608 : /* note, we don't have to check whether the result is equal to
2609 : * NIL when using bitwise OR: there is only a single bit set in
2610 : * NIL, which means that at least one of the operands must have
2611 : * only that single bit set (and the other either also or
2612 : * no bits set), so that that operand is already NIL */
2613 1205519 : switch (ATOMbasetype(tp)) {
2614 1205496 : case TYPE_bte:
2615 1205496 : if (tp == TYPE_bit) {
2616 : /* implement tri-Boolean algebra */
2617 20001424 : TIMEOUT_LOOP_IDX(k, ci1->ncand, qry_ctx) {
2618 16383986 : if (incr1)
2619 15179648 : i = canditer_next(ci1) - candoff1;
2620 16384314 : if (incr2)
2621 15179942 : j = canditer_next(ci2) - candoff2;
2622 16383985 : bit v1 = ((const bit *) lft)[i];
2623 16383985 : bit v2 = ((const bit *) rgt)[j];
2624 16383985 : ((bit *) dst)[k] = or3(v1, v2);
2625 16383985 : nils += is_bit_nil(((bit *) dst)[k]);
2626 : }
2627 1205493 : TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx));
2628 : } else {
2629 3 : if (nonil)
2630 0 : BINARY_3TYPE_FUNC_nonil(bte, bte, bte, OR);
2631 : else
2632 12 : BINARY_3TYPE_FUNC(bte, bte, bte, OR);
2633 : }
2634 : break;
2635 0 : case TYPE_sht:
2636 0 : if (nonil)
2637 0 : BINARY_3TYPE_FUNC_nonil(sht, sht, sht, OR);
2638 : else
2639 0 : BINARY_3TYPE_FUNC(sht, sht, sht, OR);
2640 : break;
2641 8 : case TYPE_int:
2642 8 : if (nonil)
2643 14 : BINARY_3TYPE_FUNC_nonil(int, int, int, OR);
2644 : else
2645 136 : BINARY_3TYPE_FUNC(int, int, int, OR);
2646 : break;
2647 2 : case TYPE_lng:
2648 2 : if (nonil)
2649 39 : BINARY_3TYPE_FUNC_nonil(lng, lng, lng, OR);
2650 : else
2651 4 : BINARY_3TYPE_FUNC(lng, lng, lng, OR);
2652 : break;
2653 : #ifdef HAVE_HGE
2654 0 : case TYPE_hge:
2655 0 : if (nonil)
2656 0 : BINARY_3TYPE_FUNC_nonil(hge, hge, hge, OR);
2657 : else
2658 0 : BINARY_3TYPE_FUNC(hge, hge, hge, OR);
2659 : break;
2660 : #endif
2661 0 : default:
2662 0 : GDKerror("%s: bad input type %s.\n", func, ATOMname(tp));
2663 0 : return BUN_NONE;
2664 : }
2665 :
2666 : return nils;
2667 : }
2668 :
2669 : BAT *
2670 1633 : BATcalcor(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
2671 : {
2672 1633 : lng t0 = 0;
2673 1633 : BAT *bn;
2674 1633 : BUN nils;
2675 1633 : struct canditer ci1, ci2;
2676 :
2677 1633 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
2678 :
2679 1633 : BATcheck(b1, NULL);
2680 1633 : BATcheck(b2, NULL);
2681 :
2682 1645 : if (ATOMbasetype(b1->ttype) != ATOMbasetype(b2->ttype)) {
2683 0 : GDKerror("incompatible input types.\n");
2684 0 : return NULL;
2685 : }
2686 :
2687 1633 : canditer_init(&ci1, b1, s1);
2688 1633 : canditer_init(&ci2, b2, s2);
2689 1633 : if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
2690 0 : GDKerror("inputs not the same size.\n");
2691 0 : return NULL;
2692 : }
2693 :
2694 1633 : bn = COLnew(ci1.hseq, b1->ttype, ci1.ncand, TRANSIENT);
2695 1633 : if (bn == NULL)
2696 : return NULL;
2697 1633 : if (ci1.ncand == 0)
2698 : return bn;
2699 :
2700 1356 : BATiter b1i = bat_iterator(b1);
2701 1356 : BATiter b2i = bat_iterator(b2);
2702 4068 : nils = or_typeswitchloop(b1i.base, true,
2703 1356 : b2i.base, true,
2704 1356 : Tloc(bn, 0),
2705 1356 : b1i.type,
2706 : &ci1, &ci2, b1->hseqbase, b2->hseqbase,
2707 1356 : b1i.nonil && b2i.nonil,
2708 : __func__);
2709 1356 : bat_iterator_end(&b1i);
2710 1356 : bat_iterator_end(&b2i);
2711 :
2712 1356 : if (nils == BUN_NONE) {
2713 0 : BBPunfix(bn->batCacheid);
2714 0 : return NULL;
2715 : }
2716 :
2717 1356 : BATsetcount(bn, ci1.ncand);
2718 :
2719 1356 : bn->tsorted = ci1.ncand <= 1 || nils == ci1.ncand;
2720 1356 : bn->trevsorted = ci1.ncand <= 1 || nils == ci1.ncand;
2721 1356 : bn->tkey = ci1.ncand <= 1;
2722 1356 : bn->tnil = nils != 0;
2723 1356 : bn->tnonil = nils == 0;
2724 :
2725 1356 : TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
2726 : ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
2727 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
2728 : ALGOBATPAR(b1), ALGOBATPAR(b2),
2729 : ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
2730 : ALGOOPTBATPAR(bn), GDKusec() - t0);
2731 :
2732 : return bn;
2733 : }
2734 :
2735 : BAT *
2736 67 : BATcalcorcst(BAT *b, const ValRecord *v, BAT *s)
2737 : {
2738 67 : lng t0 = 0;
2739 67 : BAT *bn;
2740 67 : BUN nils;
2741 67 : struct canditer ci;
2742 :
2743 67 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
2744 :
2745 67 : BATcheck(b, NULL);
2746 :
2747 69 : if (ATOMbasetype(b->ttype) != ATOMbasetype(v->vtype)) {
2748 0 : GDKerror("incompatible input types.\n");
2749 0 : return NULL;
2750 : }
2751 :
2752 67 : canditer_init(&ci, b, s);
2753 :
2754 67 : if (b->ttype == TYPE_bit && v->vtype == TYPE_bit && v->val.btval == 1) {
2755 : /* true OR anything (including NIL) equals true */
2756 28 : return BATconstant(ci.hseq, TYPE_bit, &(bit){1},
2757 : ci.ncand, TRANSIENT);
2758 : }
2759 :
2760 39 : bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
2761 39 : if (bn == NULL)
2762 : return NULL;
2763 39 : if (ci.ncand == 0)
2764 : return bn;
2765 :
2766 28 : BATiter bi = bat_iterator(b);
2767 84 : nils = or_typeswitchloop(bi.base, true,
2768 : VALptr(v), false,
2769 28 : Tloc(bn, 0), bi.type,
2770 : &ci,
2771 28 : &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
2772 : b->hseqbase, 0,
2773 28 : bi.nonil && ATOMcmp(v->vtype, VALptr(v), ATOMnilptr(v->vtype)) != 0,
2774 : __func__);
2775 28 : bat_iterator_end(&bi);
2776 :
2777 28 : if (nils == BUN_NONE) {
2778 0 : BBPunfix(bn->batCacheid);
2779 0 : return NULL;
2780 : }
2781 :
2782 28 : BATsetcount(bn, ci.ncand);
2783 :
2784 28 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
2785 28 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
2786 28 : bn->tkey = ci.ncand <= 1;
2787 28 : bn->tnil = nils != 0;
2788 28 : bn->tnonil = nils == 0;
2789 :
2790 28 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
2791 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
2792 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
2793 : ALGOOPTBATPAR(bn), GDKusec() - t0);
2794 :
2795 : return bn;
2796 : }
2797 :
2798 : BAT *
2799 19 : BATcalccstor(const ValRecord *v, BAT *b, BAT *s)
2800 : {
2801 19 : return BATcalcorcst(b, v, s);
2802 : }
2803 :
2804 : gdk_return
2805 1204122 : VARcalcor(ValPtr ret, const ValRecord *lft, const ValRecord *rgt)
2806 : {
2807 1204134 : if (ATOMbasetype(lft->vtype) != ATOMbasetype(rgt->vtype)) {
2808 0 : GDKerror("incompatible input types.\n");
2809 0 : return GDK_FAIL;
2810 : }
2811 :
2812 1204122 : ret->bat = false;
2813 1204122 : if (or_typeswitchloop(VALptr(lft), false,
2814 : VALptr(rgt), false,
2815 : VALget(ret), lft->vtype,
2816 1204122 : &(struct canditer){.tpe=cand_dense, .ncand=1},
2817 1204122 : &(struct canditer){.tpe=cand_dense, .ncand=1},
2818 : 0, 0, false, __func__) == BUN_NONE)
2819 0 : return GDK_FAIL;
2820 1204122 : return GDK_SUCCEED;
2821 : }
2822 :
2823 : /* ---------------------------------------------------------------------- */
2824 : /* logical (for type bit) or bitwise (for integral types) exclusive AND */
2825 :
2826 : #define and3(a,b) ((a) == 0 || (b) == 0 ? 0 : is_bit_nil(a) || is_bit_nil(b) ? bit_nil : 1)
2827 :
2828 : #define AND(a, b) ((a) & (b))
2829 :
2830 : static BUN
2831 2259198 : and_typeswitchloop(const void *lft, bool incr1,
2832 : const void *rgt, bool incr2,
2833 : void *restrict dst, int tp,
2834 : struct canditer *restrict ci1,
2835 : struct canditer *restrict ci2,
2836 : oid candoff1, oid candoff2,
2837 : bool nonil, const char *func)
2838 : {
2839 2259198 : BUN i = 0, j = 0, k;
2840 2259198 : BUN nils = 0;
2841 :
2842 2259198 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
2843 :
2844 2259262 : switch (ATOMbasetype(tp)) {
2845 2259150 : case TYPE_bte:
2846 2259150 : if (tp == TYPE_bit) {
2847 : /* implement tri-Boolean algebra */
2848 11913042 : TIMEOUT_LOOP_IDX(k, ci1->ncand, qry_ctx) {
2849 5135424 : if (incr1)
2850 2876819 : i = canditer_next(ci1) - candoff1;
2851 5135414 : if (incr2)
2852 2876994 : j = canditer_next(ci2) - candoff2;
2853 5135421 : bit v1 = ((const bit *) lft)[i];
2854 5135421 : bit v2 = ((const bit *) rgt)[j];
2855 5135421 : ((bit *) dst)[k] = and3(v1, v2);
2856 5135421 : nils += is_bit_nil(((bit *) dst)[k]);
2857 : }
2858 2259131 : TIMEOUT_CHECK(qry_ctx, TIMEOUT_HANDLER(BUN_NONE, qry_ctx));
2859 : } else {
2860 16 : if (nonil)
2861 21 : BINARY_3TYPE_FUNC_nonil_nilcheck(bte, bte, bte, AND, ON_OVERFLOW(bte, bte, "AND"));
2862 : else
2863 44 : BINARY_3TYPE_FUNC_nilcheck(bte, bte, bte, AND, ON_OVERFLOW(bte, bte, "AND"));
2864 : }
2865 : break;
2866 6 : case TYPE_sht:
2867 6 : if (nonil)
2868 21 : BINARY_3TYPE_FUNC_nonil_nilcheck(sht, sht, sht, AND, ON_OVERFLOW(sht, sht, "AND"));
2869 : else
2870 4 : BINARY_3TYPE_FUNC_nilcheck(sht, sht, sht, AND, ON_OVERFLOW(sht, sht, "AND"));
2871 : break;
2872 37 : case TYPE_int:
2873 37 : if (nonil)
2874 262 : BINARY_3TYPE_FUNC_nonil_nilcheck(int, int, int, AND, ON_OVERFLOW(int, int, "AND"));
2875 : else
2876 52 : BINARY_3TYPE_FUNC_nilcheck(int, int, int, AND, ON_OVERFLOW(int, int, "AND"));
2877 : break;
2878 2 : case TYPE_lng:
2879 2 : if (nonil)
2880 0 : BINARY_3TYPE_FUNC_nonil_nilcheck(lng, lng, lng, AND, ON_OVERFLOW(lng, lng, "AND"));
2881 : else
2882 8 : BINARY_3TYPE_FUNC_nilcheck(lng, lng, lng, AND, ON_OVERFLOW(lng, lng, "AND"));
2883 : break;
2884 : #ifdef HAVE_HGE
2885 3 : case TYPE_hge:
2886 3 : if (nonil)
2887 6 : BINARY_3TYPE_FUNC_nonil_nilcheck(hge, hge, hge, AND, ON_OVERFLOW(hge, hge, "AND"));
2888 : else
2889 8 : BINARY_3TYPE_FUNC_nilcheck(hge, hge, hge, AND, ON_OVERFLOW(hge, hge, "AND"));
2890 : break;
2891 : #endif
2892 0 : default:
2893 0 : GDKerror("%s: bad input type %s.\n", func, ATOMname(tp));
2894 0 : return BUN_NONE;
2895 : }
2896 :
2897 : return nils;
2898 : }
2899 :
2900 : BAT *
2901 2259 : BATcalcand(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
2902 : {
2903 2259 : lng t0 = 0;
2904 2259 : BAT *bn;
2905 2259 : BUN nils;
2906 2259 : struct canditer ci1, ci2;
2907 :
2908 2259 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
2909 :
2910 2259 : BATcheck(b1, NULL);
2911 2259 : BATcheck(b2, NULL);
2912 :
2913 2281 : if (ATOMbasetype(b1->ttype) != ATOMbasetype(b2->ttype)) {
2914 0 : GDKerror("incompatible input types.\n");
2915 0 : return NULL;
2916 : }
2917 :
2918 2259 : canditer_init(&ci1, b1, s1);
2919 2259 : canditer_init(&ci2, b2, s2);
2920 2259 : if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
2921 0 : GDKerror("inputs not the same size.\n");
2922 0 : return NULL;
2923 : }
2924 :
2925 2259 : bn = COLnew(ci1.hseq, b1->ttype, ci1.ncand, TRANSIENT);
2926 2258 : if (bn == NULL)
2927 : return NULL;
2928 2258 : if (ci1.ncand == 0)
2929 : return bn;
2930 :
2931 905 : BATiter b1i = bat_iterator(b1);
2932 904 : BATiter b2i = bat_iterator(b2);
2933 2712 : nils = and_typeswitchloop(b1i.base, true,
2934 905 : b2i.base, true,
2935 905 : Tloc(bn, 0),
2936 905 : b1i.type,
2937 : &ci1, &ci2, b1->hseqbase, b2->hseqbase,
2938 905 : b1i.nonil && b2i.nonil,
2939 : __func__);
2940 902 : bat_iterator_end(&b1i);
2941 905 : bat_iterator_end(&b2i);
2942 :
2943 904 : if (nils == BUN_NONE) {
2944 0 : BBPunfix(bn->batCacheid);
2945 0 : return NULL;
2946 : }
2947 :
2948 904 : BATsetcount(bn, ci1.ncand);
2949 :
2950 903 : bn->tsorted = ci1.ncand <= 1 || nils == ci1.ncand;
2951 903 : bn->trevsorted = ci1.ncand <= 1 || nils == ci1.ncand;
2952 903 : bn->tkey = ci1.ncand <= 1;
2953 903 : bn->tnil = nils != 0;
2954 903 : bn->tnonil = nils == 0;
2955 :
2956 903 : TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
2957 : ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
2958 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
2959 : ALGOBATPAR(b1), ALGOBATPAR(b2),
2960 : ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
2961 : ALGOOPTBATPAR(bn), GDKusec() - t0);
2962 :
2963 : return bn;
2964 : }
2965 :
2966 : BAT *
2967 1183 : BATcalcandcst(BAT *b, const ValRecord *v, BAT *s)
2968 : {
2969 1183 : lng t0 = 0;
2970 1183 : BAT *bn;
2971 1183 : BUN nils;
2972 1183 : struct canditer ci;
2973 :
2974 1183 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
2975 :
2976 1183 : BATcheck(b, NULL);
2977 :
2978 3473 : if (ATOMbasetype(b->ttype) != ATOMbasetype(v->vtype)) {
2979 0 : GDKerror("incompatible input types.\n");
2980 0 : return NULL;
2981 : }
2982 :
2983 1183 : canditer_init(&ci, b, s);
2984 :
2985 1183 : if (b->ttype == TYPE_bit && v->vtype == TYPE_bit && v->val.btval == 0) {
2986 : /* false AND anything (including NIL) equals false */
2987 23 : return BATconstant(ci.hseq, TYPE_bit, &(bit){0},
2988 : ci.ncand, TRANSIENT);
2989 : }
2990 :
2991 1160 : bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
2992 1160 : if (bn == NULL)
2993 : return NULL;
2994 1160 : if (ci.ncand == 0)
2995 : return bn;
2996 :
2997 40 : BATiter bi = bat_iterator(b);
2998 120 : nils = and_typeswitchloop(bi.base, true,
2999 : VALptr(v), false,
3000 40 : Tloc(bn, 0), bi.type,
3001 : &ci,
3002 40 : &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
3003 : b->hseqbase, 0,
3004 40 : bi.nonil && ATOMcmp(v->vtype, VALptr(v), ATOMnilptr(v->vtype)) != 0,
3005 : __func__);
3006 40 : bat_iterator_end(&bi);
3007 :
3008 40 : if (nils == BUN_NONE) {
3009 0 : BBPunfix(bn->batCacheid);
3010 0 : return NULL;
3011 : }
3012 :
3013 40 : BATsetcount(bn, ci.ncand);
3014 :
3015 40 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
3016 40 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
3017 40 : bn->tkey = ci.ncand <= 1;
3018 40 : bn->tnil = nils != 0;
3019 40 : bn->tnonil = nils == 0;
3020 :
3021 40 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
3022 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
3023 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
3024 : ALGOOPTBATPAR(bn), GDKusec() - t0);
3025 :
3026 : return bn;
3027 : }
3028 :
3029 : BAT *
3030 9 : BATcalccstand(const ValRecord *v, BAT *b, BAT *s)
3031 : {
3032 9 : return BATcalcandcst(b, v, s);
3033 : }
3034 :
3035 : gdk_return
3036 2258253 : VARcalcand(ValPtr ret, const ValRecord *lft, const ValRecord *rgt)
3037 : {
3038 2258311 : if (ATOMbasetype(lft->vtype) != ATOMbasetype(rgt->vtype)) {
3039 0 : GDKerror("incompatible input types.\n");
3040 0 : return GDK_FAIL;
3041 : }
3042 :
3043 2258253 : ret->bat = false;
3044 2258253 : if (and_typeswitchloop(VALptr(lft), false,
3045 : VALptr(rgt), false,
3046 : VALget(ret), lft->vtype,
3047 2258253 : &(struct canditer){.tpe=cand_dense, .ncand=1},
3048 2258253 : &(struct canditer){.tpe=cand_dense, .ncand=1},
3049 : 0, 0, false, __func__) == BUN_NONE)
3050 0 : return GDK_FAIL;
3051 2258253 : return GDK_SUCCEED;
3052 : }
3053 :
3054 : /* ---------------------------------------------------------------------- */
3055 : /* left shift (any integral type) */
3056 :
3057 : #define LSH(a, b) ((a) << (b))
3058 :
3059 : #define SHIFT_CHECK(a, b) ((b) < 0 || (b) >= 8 * (int) sizeof(a))
3060 : #define NO_SHIFT_CHECK(a, b) 0
3061 :
3062 : /* In standard C, left shift is undefined if any of the following
3063 : * conditions hold:
3064 : * - right operand is negative or larger or equal to the width of the
3065 : * left operand;
3066 : * - left operand is negative;
3067 : * - left operand times two-to-the-power of the right operand is not
3068 : * representable in the (promoted) type of the left operand. */
3069 : #define LSH_CHECK(a, b, TYPE) (SHIFT_CHECK(a, b) || (a) < 0 || (a) > (GDK_##TYPE##_max >> (b)))
3070 : #define LSH_CHECK_bte(a, b) LSH_CHECK(a, b, bte)
3071 : #define LSH_CHECK_sht(a, b) LSH_CHECK(a, b, sht)
3072 : #define LSH_CHECK_int(a, b) LSH_CHECK(a, b, int)
3073 : #define LSH_CHECK_lng(a, b) LSH_CHECK(a, b, lng)
3074 :
3075 : static BUN
3076 11 : lsh_typeswitchloop(const void *lft, int tp1, bool incr1,
3077 : const void *rgt, int tp2, bool incr2,
3078 : void *restrict dst,
3079 : struct canditer *restrict ci1,
3080 : struct canditer *restrict ci2,
3081 : oid candoff1, oid candoff2,
3082 : const char *func)
3083 : {
3084 11 : BUN i, j, k;
3085 11 : BUN nils = 0;
3086 :
3087 11 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
3088 :
3089 11 : tp1 = ATOMbasetype(tp1);
3090 11 : tp2 = ATOMbasetype(tp2);
3091 11 : switch (tp1) {
3092 2 : case TYPE_bte:
3093 2 : switch (tp2) {
3094 0 : case TYPE_bte:
3095 0 : BINARY_3TYPE_FUNC_CHECK(bte, bte, bte, LSH,
3096 : LSH_CHECK_bte);
3097 : break;
3098 0 : case TYPE_sht:
3099 0 : BINARY_3TYPE_FUNC_CHECK(bte, sht, bte, LSH,
3100 : LSH_CHECK_bte);
3101 : break;
3102 2 : case TYPE_int:
3103 8 : BINARY_3TYPE_FUNC_CHECK(bte, int, bte, LSH,
3104 : LSH_CHECK_bte);
3105 : break;
3106 0 : case TYPE_lng:
3107 0 : BINARY_3TYPE_FUNC_CHECK(bte, lng, bte, LSH,
3108 : LSH_CHECK_bte);
3109 : break;
3110 : #ifdef HAVE_HGE
3111 0 : case TYPE_hge:
3112 0 : BINARY_3TYPE_FUNC_CHECK(bte, hge, bte, LSH,
3113 : SHIFT_CHECK);
3114 : break;
3115 : #endif
3116 0 : default:
3117 0 : goto unsupported;
3118 : }
3119 : break;
3120 4 : case TYPE_sht:
3121 4 : switch (tp2) {
3122 0 : case TYPE_bte:
3123 0 : BINARY_3TYPE_FUNC_CHECK(sht, bte, sht, LSH,
3124 : LSH_CHECK_sht);
3125 : break;
3126 0 : case TYPE_sht:
3127 0 : BINARY_3TYPE_FUNC_CHECK(sht, sht, sht, LSH,
3128 : LSH_CHECK_sht);
3129 : break;
3130 4 : case TYPE_int:
3131 16 : BINARY_3TYPE_FUNC_CHECK(sht, int, sht, LSH,
3132 : LSH_CHECK_sht);
3133 : break;
3134 0 : case TYPE_lng:
3135 0 : BINARY_3TYPE_FUNC_CHECK(sht, lng, sht, LSH,
3136 : LSH_CHECK_sht);
3137 : break;
3138 : #ifdef HAVE_HGE
3139 0 : case TYPE_hge:
3140 0 : BINARY_3TYPE_FUNC_CHECK(sht, hge, sht, LSH,
3141 : SHIFT_CHECK);
3142 : break;
3143 : #endif
3144 0 : default:
3145 0 : goto unsupported;
3146 : }
3147 : break;
3148 0 : case TYPE_int:
3149 0 : switch (tp2) {
3150 0 : case TYPE_bte:
3151 0 : BINARY_3TYPE_FUNC_CHECK(int, bte, int, LSH,
3152 : LSH_CHECK_int);
3153 : break;
3154 0 : case TYPE_sht:
3155 0 : BINARY_3TYPE_FUNC_CHECK(int, sht, int, LSH,
3156 : LSH_CHECK_int);
3157 : break;
3158 0 : case TYPE_int:
3159 0 : BINARY_3TYPE_FUNC_CHECK(int, int, int, LSH,
3160 : LSH_CHECK_int);
3161 : break;
3162 0 : case TYPE_lng:
3163 0 : BINARY_3TYPE_FUNC_CHECK(int, lng, int, LSH,
3164 : LSH_CHECK_int);
3165 : break;
3166 : #ifdef HAVE_HGE
3167 0 : case TYPE_hge:
3168 0 : BINARY_3TYPE_FUNC_CHECK(int, hge, int, LSH,
3169 : SHIFT_CHECK);
3170 : break;
3171 : #endif
3172 0 : default:
3173 0 : goto unsupported;
3174 : }
3175 : break;
3176 2 : case TYPE_lng:
3177 2 : switch (tp2) {
3178 0 : case TYPE_bte:
3179 0 : BINARY_3TYPE_FUNC_CHECK(lng, bte, lng, LSH,
3180 : LSH_CHECK_lng);
3181 : break;
3182 0 : case TYPE_sht:
3183 0 : BINARY_3TYPE_FUNC_CHECK(lng, sht, lng, LSH,
3184 : LSH_CHECK_lng);
3185 : break;
3186 2 : case TYPE_int:
3187 8 : BINARY_3TYPE_FUNC_CHECK(lng, int, lng, LSH,
3188 : LSH_CHECK_lng);
3189 : break;
3190 0 : case TYPE_lng:
3191 0 : BINARY_3TYPE_FUNC_CHECK(lng, lng, lng, LSH,
3192 : LSH_CHECK_lng);
3193 : break;
3194 : #ifdef HAVE_HGE
3195 0 : case TYPE_hge:
3196 0 : BINARY_3TYPE_FUNC_CHECK(lng, hge, lng, LSH,
3197 : SHIFT_CHECK);
3198 : break;
3199 : #endif
3200 0 : default:
3201 0 : goto unsupported;
3202 : }
3203 : break;
3204 : #ifdef HAVE_HGE
3205 3 : case TYPE_hge:
3206 3 : switch (tp2) {
3207 0 : case TYPE_bte:
3208 0 : BINARY_3TYPE_FUNC_CHECK(hge, bte, hge, LSH,
3209 : NO_SHIFT_CHECK);
3210 : break;
3211 0 : case TYPE_sht:
3212 0 : BINARY_3TYPE_FUNC_CHECK(hge, sht, hge, LSH,
3213 : SHIFT_CHECK);
3214 : break;
3215 3 : case TYPE_int:
3216 12 : BINARY_3TYPE_FUNC_CHECK(hge, int, hge, LSH,
3217 : SHIFT_CHECK);
3218 : break;
3219 0 : case TYPE_lng:
3220 0 : BINARY_3TYPE_FUNC_CHECK(hge, lng, hge, LSH,
3221 : SHIFT_CHECK);
3222 : break;
3223 0 : case TYPE_hge:
3224 0 : BINARY_3TYPE_FUNC_CHECK(hge, hge, hge, LSH,
3225 : SHIFT_CHECK);
3226 : break;
3227 0 : default:
3228 0 : goto unsupported;
3229 : }
3230 : break;
3231 : #endif
3232 0 : default:
3233 0 : goto unsupported;
3234 : }
3235 :
3236 : return nils;
3237 :
3238 0 : unsupported:
3239 0 : GDKerror("%s: bad input types %s,%s.\n", func,
3240 : ATOMname(tp1), ATOMname(tp2));
3241 : checkfail:
3242 : return BUN_NONE;
3243 : }
3244 :
3245 : BAT *
3246 3 : BATcalclsh(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
3247 : {
3248 3 : lng t0 = 0;
3249 3 : BAT *bn;
3250 3 : BUN nils;
3251 3 : struct canditer ci1, ci2;
3252 :
3253 3 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
3254 :
3255 3 : BATcheck(b1, NULL);
3256 3 : BATcheck(b2, NULL);
3257 :
3258 3 : canditer_init(&ci1, b1, s1);
3259 3 : canditer_init(&ci2, b2, s2);
3260 3 : if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
3261 0 : GDKerror("inputs not the same size.\n");
3262 0 : return NULL;
3263 : }
3264 :
3265 3 : bn = COLnew(ci1.hseq, b1->ttype, ci1.ncand, TRANSIENT);
3266 3 : if (bn == NULL)
3267 : return NULL;
3268 3 : if (ci1.ncand == 0)
3269 : return bn;
3270 :
3271 0 : BATiter b1i = bat_iterator(b1);
3272 0 : BATiter b2i = bat_iterator(b2);
3273 0 : nils = lsh_typeswitchloop(b1i.base, b1i.type, true,
3274 0 : b2i.base, b2i.type, true,
3275 0 : Tloc(bn, 0),
3276 : &ci1, &ci2, b1->hseqbase, b2->hseqbase,
3277 : __func__);
3278 0 : bat_iterator_end(&b1i);
3279 0 : bat_iterator_end(&b2i);
3280 :
3281 0 : if (nils == BUN_NONE) {
3282 0 : BBPunfix(bn->batCacheid);
3283 0 : return NULL;
3284 : }
3285 :
3286 0 : BATsetcount(bn, ci1.ncand);
3287 :
3288 0 : bn->tsorted = ci1.ncand <= 1 || nils == ci1.ncand;
3289 0 : bn->trevsorted = ci1.ncand <= 1 || nils == ci1.ncand;
3290 0 : bn->tkey = ci1.ncand <= 1;
3291 0 : bn->tnil = nils != 0;
3292 0 : bn->tnonil = nils == 0;
3293 :
3294 0 : TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
3295 : ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
3296 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
3297 : ALGOBATPAR(b1), ALGOBATPAR(b2),
3298 : ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
3299 : ALGOOPTBATPAR(bn), GDKusec() - t0);
3300 :
3301 : return bn;
3302 : }
3303 :
3304 : BAT *
3305 0 : BATcalclshcst(BAT *b, const ValRecord *v, BAT *s)
3306 : {
3307 0 : lng t0 = 0;
3308 0 : BAT *bn;
3309 0 : BUN nils;
3310 0 : struct canditer ci;
3311 :
3312 0 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
3313 :
3314 0 : BATcheck(b, NULL);
3315 :
3316 0 : canditer_init(&ci, b, s);
3317 :
3318 0 : bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
3319 0 : if (bn == NULL)
3320 : return NULL;
3321 0 : if (ci.ncand == 0)
3322 : return bn;
3323 :
3324 0 : BATiter bi = bat_iterator(b);
3325 0 : nils = lsh_typeswitchloop(bi.base, bi.type, true,
3326 0 : VALptr(v), v->vtype, false,
3327 0 : Tloc(bn, 0),
3328 : &ci,
3329 0 : &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
3330 : b->hseqbase, 0,
3331 : __func__);
3332 0 : bat_iterator_end(&bi);
3333 :
3334 0 : if (nils == BUN_NONE) {
3335 0 : BBPunfix(bn->batCacheid);
3336 0 : return NULL;
3337 : }
3338 :
3339 0 : BATsetcount(bn, ci.ncand);
3340 :
3341 0 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
3342 0 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
3343 0 : bn->tkey = ci.ncand <= 1;
3344 0 : bn->tnil = nils != 0;
3345 0 : bn->tnonil = nils == 0;
3346 :
3347 0 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
3348 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
3349 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
3350 : ALGOOPTBATPAR(bn), GDKusec() - t0);
3351 :
3352 : return bn;
3353 : }
3354 :
3355 : BAT *
3356 0 : BATcalccstlsh(const ValRecord *v, BAT *b, BAT *s)
3357 : {
3358 0 : lng t0 = 0;
3359 0 : BAT *bn;
3360 0 : BUN nils;
3361 0 : struct canditer ci;
3362 :
3363 0 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
3364 :
3365 0 : BATcheck(b, NULL);
3366 :
3367 0 : canditer_init(&ci, b, s);
3368 :
3369 0 : bn = COLnew(ci.hseq, v->vtype, ci.ncand, TRANSIENT);
3370 0 : if (bn == NULL)
3371 : return NULL;
3372 0 : if (ci.ncand == 0)
3373 : return bn;
3374 :
3375 0 : BATiter bi = bat_iterator(b);
3376 0 : nils = lsh_typeswitchloop(VALptr(v), v->vtype, false,
3377 0 : bi.base, bi.type, true,
3378 0 : Tloc(bn, 0),
3379 0 : &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
3380 : &ci,
3381 : 0, b->hseqbase,
3382 : __func__);
3383 0 : bat_iterator_end(&bi);
3384 :
3385 0 : if (nils == BUN_NONE) {
3386 0 : BBPunfix(bn->batCacheid);
3387 0 : return NULL;
3388 : }
3389 :
3390 0 : BATsetcount(bn, ci.ncand);
3391 :
3392 0 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
3393 0 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
3394 0 : bn->tkey = ci.ncand <= 1;
3395 0 : bn->tnil = nils != 0;
3396 0 : bn->tnonil = nils == 0;
3397 :
3398 0 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
3399 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
3400 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
3401 : ALGOOPTBATPAR(bn), GDKusec() - t0);
3402 :
3403 : return bn;
3404 : }
3405 :
3406 : gdk_return
3407 11 : VARcalclsh(ValPtr ret, const ValRecord *lft, const ValRecord *rgt)
3408 : {
3409 11 : *ret = (ValRecord) {.vtype = lft->vtype};
3410 11 : if (lsh_typeswitchloop(VALptr(lft), lft->vtype, false,
3411 11 : VALptr(rgt), rgt->vtype, false,
3412 : VALget(ret),
3413 11 : &(struct canditer){.tpe=cand_dense, .ncand=1},
3414 11 : &(struct canditer){.tpe=cand_dense, .ncand=1},
3415 : 0, 0, __func__) == BUN_NONE)
3416 0 : return GDK_FAIL;
3417 11 : return GDK_SUCCEED;
3418 : }
3419 :
3420 : /* ---------------------------------------------------------------------- */
3421 : /* right shift (any integral type) */
3422 :
3423 : #define RSH(a, b) ((a) >> (b))
3424 :
3425 : static BUN
3426 21 : rsh_typeswitchloop(const void *lft, int tp1, bool incr1,
3427 : const void *rgt, int tp2, bool incr2,
3428 : void *restrict dst,
3429 : struct canditer *restrict ci1,
3430 : struct canditer *restrict ci2,
3431 : oid candoff1, oid candoff2,
3432 : const char *restrict func)
3433 : {
3434 21 : BUN i, j, k;
3435 21 : BUN nils = 0;
3436 :
3437 21 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
3438 :
3439 21 : tp1 = ATOMbasetype(tp1);
3440 21 : tp2 = ATOMbasetype(tp2);
3441 21 : switch (tp1) {
3442 6 : case TYPE_bte:
3443 6 : switch (tp2) {
3444 0 : case TYPE_bte:
3445 0 : BINARY_3TYPE_FUNC_CHECK(bte, bte, bte, RSH,
3446 : SHIFT_CHECK);
3447 : break;
3448 0 : case TYPE_sht:
3449 0 : BINARY_3TYPE_FUNC_CHECK(bte, sht, bte, RSH,
3450 : SHIFT_CHECK);
3451 : break;
3452 6 : case TYPE_int:
3453 24 : BINARY_3TYPE_FUNC_CHECK(bte, int, bte, RSH,
3454 : SHIFT_CHECK);
3455 : break;
3456 0 : case TYPE_lng:
3457 0 : BINARY_3TYPE_FUNC_CHECK(bte, lng, bte, RSH,
3458 : SHIFT_CHECK);
3459 : break;
3460 : #ifdef HAVE_HGE
3461 0 : case TYPE_hge:
3462 0 : BINARY_3TYPE_FUNC_CHECK(bte, hge, bte, RSH,
3463 : SHIFT_CHECK);
3464 : break;
3465 : #endif
3466 0 : default:
3467 0 : goto unsupported;
3468 : }
3469 : break;
3470 0 : case TYPE_sht:
3471 0 : switch (tp2) {
3472 0 : case TYPE_bte:
3473 0 : BINARY_3TYPE_FUNC_CHECK(sht, bte, sht, RSH,
3474 : SHIFT_CHECK);
3475 : break;
3476 0 : case TYPE_sht:
3477 0 : BINARY_3TYPE_FUNC_CHECK(sht, sht, sht, RSH,
3478 : SHIFT_CHECK);
3479 : break;
3480 0 : case TYPE_int:
3481 0 : BINARY_3TYPE_FUNC_CHECK(sht, int, sht, RSH,
3482 : SHIFT_CHECK);
3483 : break;
3484 0 : case TYPE_lng:
3485 0 : BINARY_3TYPE_FUNC_CHECK(sht, lng, sht, RSH,
3486 : SHIFT_CHECK);
3487 : break;
3488 : #ifdef HAVE_HGE
3489 0 : case TYPE_hge:
3490 0 : BINARY_3TYPE_FUNC_CHECK(sht, hge, sht, RSH,
3491 : SHIFT_CHECK);
3492 : break;
3493 : #endif
3494 0 : default:
3495 0 : goto unsupported;
3496 : }
3497 : break;
3498 12 : case TYPE_int:
3499 12 : switch (tp2) {
3500 0 : case TYPE_bte:
3501 0 : BINARY_3TYPE_FUNC_CHECK(int, bte, int, RSH,
3502 : SHIFT_CHECK);
3503 : break;
3504 0 : case TYPE_sht:
3505 0 : BINARY_3TYPE_FUNC_CHECK(int, sht, int, RSH,
3506 : SHIFT_CHECK);
3507 : break;
3508 12 : case TYPE_int:
3509 76 : BINARY_3TYPE_FUNC_CHECK(int, int, int, RSH,
3510 : SHIFT_CHECK);
3511 : break;
3512 0 : case TYPE_lng:
3513 0 : BINARY_3TYPE_FUNC_CHECK(int, lng, int, RSH,
3514 : SHIFT_CHECK);
3515 : break;
3516 : #ifdef HAVE_HGE
3517 0 : case TYPE_hge:
3518 0 : BINARY_3TYPE_FUNC_CHECK(int, hge, int, RSH,
3519 : SHIFT_CHECK);
3520 : break;
3521 : #endif
3522 0 : default:
3523 0 : goto unsupported;
3524 : }
3525 : break;
3526 0 : case TYPE_lng:
3527 0 : switch (tp2) {
3528 0 : case TYPE_bte:
3529 0 : BINARY_3TYPE_FUNC_CHECK(lng, bte, lng, RSH,
3530 : SHIFT_CHECK);
3531 : break;
3532 0 : case TYPE_sht:
3533 0 : BINARY_3TYPE_FUNC_CHECK(lng, sht, lng, RSH,
3534 : SHIFT_CHECK);
3535 : break;
3536 0 : case TYPE_int:
3537 0 : BINARY_3TYPE_FUNC_CHECK(lng, int, lng, RSH,
3538 : SHIFT_CHECK);
3539 : break;
3540 0 : case TYPE_lng:
3541 0 : BINARY_3TYPE_FUNC_CHECK(lng, lng, lng, RSH,
3542 : SHIFT_CHECK);
3543 : break;
3544 : #ifdef HAVE_HGE
3545 0 : case TYPE_hge:
3546 0 : BINARY_3TYPE_FUNC_CHECK(lng, hge, lng, RSH,
3547 : SHIFT_CHECK);
3548 : break;
3549 : #endif
3550 0 : default:
3551 0 : goto unsupported;
3552 : }
3553 : break;
3554 : #ifdef HAVE_HGE
3555 3 : case TYPE_hge:
3556 3 : switch (tp2) {
3557 0 : case TYPE_bte:
3558 0 : BINARY_3TYPE_FUNC_CHECK(hge, bte, hge, RSH,
3559 : NO_SHIFT_CHECK);
3560 : break;
3561 0 : case TYPE_sht:
3562 0 : BINARY_3TYPE_FUNC_CHECK(hge, sht, hge, RSH,
3563 : SHIFT_CHECK);
3564 : break;
3565 3 : case TYPE_int:
3566 12 : BINARY_3TYPE_FUNC_CHECK(hge, int, hge, RSH,
3567 : SHIFT_CHECK);
3568 : break;
3569 0 : case TYPE_lng:
3570 0 : BINARY_3TYPE_FUNC_CHECK(hge, lng, hge, RSH,
3571 : SHIFT_CHECK);
3572 : break;
3573 0 : case TYPE_hge:
3574 0 : BINARY_3TYPE_FUNC_CHECK(hge, hge, hge, RSH,
3575 : SHIFT_CHECK);
3576 : break;
3577 0 : default:
3578 0 : goto unsupported;
3579 : }
3580 : break;
3581 : #endif
3582 0 : default:
3583 0 : goto unsupported;
3584 : }
3585 :
3586 : return nils;
3587 :
3588 0 : unsupported:
3589 0 : GDKerror("%s: bad input types %s,%s.\n", func,
3590 : ATOMname(tp1), ATOMname(tp2));
3591 : checkfail:
3592 : return BUN_NONE;
3593 : }
3594 :
3595 : BAT *
3596 2 : BATcalcrsh(BAT *b1, BAT *b2, BAT *s1, BAT *s2)
3597 : {
3598 2 : lng t0 = 0;
3599 2 : BAT *bn;
3600 2 : BUN nils;
3601 2 : struct canditer ci1, ci2;
3602 :
3603 2 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
3604 :
3605 2 : BATcheck(b1, NULL);
3606 2 : BATcheck(b2, NULL);
3607 :
3608 2 : canditer_init(&ci1, b1, s1);
3609 2 : canditer_init(&ci2, b2, s2);
3610 2 : if (ci1.ncand != ci2.ncand || ci1.hseq != ci2.hseq) {
3611 0 : GDKerror("inputs not the same size.\n");
3612 0 : return NULL;
3613 : }
3614 :
3615 2 : bn = COLnew(ci1.hseq, b1->ttype, ci1.ncand, TRANSIENT);
3616 2 : if (bn == NULL)
3617 : return NULL;
3618 2 : if (ci1.ncand == 0)
3619 : return bn;
3620 :
3621 0 : BATiter b1i = bat_iterator(b1);
3622 0 : BATiter b2i = bat_iterator(b2);
3623 0 : nils = rsh_typeswitchloop(b1i.base, b1i.type, true,
3624 0 : b2i.base, b2i.type, true,
3625 0 : Tloc(bn, 0),
3626 : &ci1, &ci2, b1->hseqbase, b2->hseqbase,
3627 : __func__);
3628 0 : bat_iterator_end(&b1i);
3629 0 : bat_iterator_end(&b2i);
3630 :
3631 0 : if (nils == BUN_NONE) {
3632 0 : BBPunfix(bn->batCacheid);
3633 0 : return NULL;
3634 : }
3635 :
3636 0 : BATsetcount(bn, ci1.ncand);
3637 :
3638 0 : bn->tsorted = ci1.ncand <= 1 || nils == ci1.ncand;
3639 0 : bn->trevsorted = ci1.ncand <= 1 || nils == ci1.ncand;
3640 0 : bn->tkey = ci1.ncand <= 1;
3641 0 : bn->tnil = nils != 0;
3642 0 : bn->tnonil = nils == 0;
3643 :
3644 0 : TRC_DEBUG(ALGO, "b1=" ALGOBATFMT ",b2=" ALGOBATFMT
3645 : ",s1=" ALGOOPTBATFMT ",s2=" ALGOOPTBATFMT
3646 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
3647 : ALGOBATPAR(b1), ALGOBATPAR(b2),
3648 : ALGOOPTBATPAR(s1), ALGOOPTBATPAR(s2),
3649 : ALGOOPTBATPAR(bn), GDKusec() - t0);
3650 :
3651 : return bn;
3652 : }
3653 :
3654 : BAT *
3655 506 : BATcalcrshcst(BAT *b, const ValRecord *v, BAT *s)
3656 : {
3657 506 : lng t0 = 0;
3658 506 : BAT *bn;
3659 506 : BUN nils;
3660 506 : struct canditer ci;
3661 :
3662 506 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
3663 :
3664 506 : BATcheck(b, NULL);
3665 :
3666 506 : canditer_init(&ci, b, s);
3667 :
3668 506 : bn = COLnew(ci.hseq, b->ttype, ci.ncand, TRANSIENT);
3669 506 : if (bn == NULL)
3670 : return NULL;
3671 506 : if (ci.ncand == 0)
3672 : return bn;
3673 :
3674 10 : BATiter bi = bat_iterator(b);
3675 20 : nils = rsh_typeswitchloop(bi.base, bi.type, true,
3676 10 : VALptr(v), v->vtype, false,
3677 10 : Tloc(bn, 0),
3678 : &ci,
3679 10 : &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
3680 : b->hseqbase, 0,
3681 : __func__);
3682 10 : bat_iterator_end(&bi);
3683 :
3684 10 : if (nils == BUN_NONE) {
3685 0 : BBPunfix(bn->batCacheid);
3686 0 : return NULL;
3687 : }
3688 :
3689 10 : BATsetcount(bn, ci.ncand);
3690 :
3691 10 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
3692 10 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
3693 10 : bn->tkey = ci.ncand <= 1;
3694 10 : bn->tnil = nils != 0;
3695 10 : bn->tnonil = nils == 0;
3696 :
3697 10 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
3698 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
3699 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
3700 : ALGOOPTBATPAR(bn), GDKusec() - t0);
3701 :
3702 : return bn;
3703 : }
3704 :
3705 : BAT *
3706 1 : BATcalccstrsh(const ValRecord *v, BAT *b, BAT *s)
3707 : {
3708 1 : lng t0 = 0;
3709 1 : BAT *bn;
3710 1 : BUN nils;
3711 1 : struct canditer ci;
3712 :
3713 1 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
3714 :
3715 1 : BATcheck(b, NULL);
3716 :
3717 1 : canditer_init(&ci, b, s);
3718 :
3719 1 : bn = COLnew(ci.hseq, v->vtype, ci.ncand, TRANSIENT);
3720 1 : if (bn == NULL)
3721 : return NULL;
3722 1 : if (ci.ncand == 0)
3723 : return bn;
3724 :
3725 1 : BATiter bi = bat_iterator(b);
3726 2 : nils = rsh_typeswitchloop(VALptr(v), v->vtype, false,
3727 1 : bi.base, bi.type, true,
3728 1 : Tloc(bn, 0),
3729 1 : &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
3730 : &ci,
3731 : 0, b->hseqbase,
3732 : __func__);
3733 1 : bat_iterator_end(&bi);
3734 :
3735 1 : if (nils == BUN_NONE) {
3736 0 : BBPunfix(bn->batCacheid);
3737 0 : return NULL;
3738 : }
3739 :
3740 1 : BATsetcount(bn, ci.ncand);
3741 :
3742 1 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
3743 1 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
3744 1 : bn->tkey = ci.ncand <= 1;
3745 1 : bn->tnil = nils != 0;
3746 1 : bn->tnonil = nils == 0;
3747 :
3748 1 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
3749 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
3750 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
3751 : ALGOOPTBATPAR(bn), GDKusec() - t0);
3752 :
3753 : return bn;
3754 : }
3755 :
3756 : gdk_return
3757 10 : VARcalcrsh(ValPtr ret, const ValRecord *lft, const ValRecord *rgt)
3758 : {
3759 10 : *ret = (ValRecord) {.vtype = lft->vtype};
3760 10 : if (rsh_typeswitchloop(VALptr(lft), lft->vtype, false,
3761 10 : VALptr(rgt), rgt->vtype, false,
3762 : VALget(ret),
3763 10 : &(struct canditer){.tpe=cand_dense, .ncand=1},
3764 10 : &(struct canditer){.tpe=cand_dense, .ncand=1},
3765 : 0, 0, __func__) == BUN_NONE)
3766 1 : return GDK_FAIL;
3767 9 : return GDK_SUCCEED;
3768 : }
3769 :
3770 : /* ---------------------------------------------------------------------- */
3771 : /* between (any "linear" type) */
3772 :
3773 : #define LTbte(a,b) ((a) < (b))
3774 : #define LTsht(a,b) ((a) < (b))
3775 : #define LTint(a,b) ((a) < (b))
3776 : #define LTlng(a,b) ((a) < (b))
3777 : #define LThge(a,b) ((a) < (b))
3778 : #define LToid(a,b) ((a) < (b))
3779 : #define LTflt(a,b) ((a) < (b))
3780 : #define LTdbl(a,b) ((a) < (b))
3781 : #define LTany(a,b) ((*atomcmp)(a, b) < 0)
3782 : #define EQbte(a,b) ((a) == (b))
3783 : #define EQsht(a,b) ((a) == (b))
3784 : #define EQint(a,b) ((a) == (b))
3785 : #define EQlng(a,b) ((a) == (b))
3786 : #define EQhge(a,b) ((a) == (b))
3787 : #define EQoid(a,b) ((a) == (b))
3788 : #define EQflt(a,b) ((a) == (b))
3789 : #define EQdbl(a,b) ((a) == (b))
3790 : #define EQany(a,b) ((*atomcmp)(a, b) == 0)
3791 :
3792 : #define is_any_nil(v) ((v) == NULL || (*atomcmp)((v), nil) == 0)
3793 :
3794 : #define less3(a,b,i,t) (is_##t##_nil(a) || is_##t##_nil(b) ? bit_nil : LT##t(a, b) || (i && EQ##t(a, b)))
3795 : #define grtr3(a,b,i,t) (is_##t##_nil(a) || is_##t##_nil(b) ? bit_nil : LT##t(b, a) || (i && EQ##t(a, b)))
3796 : #define not3(a) (is_bit_nil(a) ? bit_nil : !(a))
3797 :
3798 : #define between3(v, lo, linc, hi, hinc, TYPE) \
3799 : and3(grtr3(v, lo, linc, TYPE), less3(v, hi, hinc, TYPE))
3800 :
3801 : #define BETWEEN(v, lo, hi, TYPE) \
3802 : (is_##TYPE##_nil(v) \
3803 : ? nils_false ? 0 : bit_nil \
3804 : : (bit) (anti \
3805 : ? (symmetric \
3806 : ? not3(or3(between3(v, lo, linc, hi, hinc, TYPE), \
3807 : between3(v, hi, hinc, lo, linc, TYPE))) \
3808 : : not3(between3(v, lo, linc, hi, hinc, TYPE))) \
3809 : : (symmetric \
3810 : ? or3(between3(v, lo, linc, hi, hinc, TYPE), \
3811 : between3(v, hi, hinc, lo, linc, TYPE)) \
3812 : : between3(v, lo, linc, hi, hinc, TYPE))))
3813 :
3814 : #define BETWEEN_LOOP_TYPE(TYPE, canditer_next) \
3815 : do { \
3816 : i = j = k = 0; \
3817 : TIMEOUT_LOOP_IDX(l, ncand, qry_ctx) { \
3818 : if (incr1) \
3819 : i = canditer_next(ci) - seqbase1; \
3820 : if (incr2) \
3821 : j = canditer_next(cilo) - seqbase2; \
3822 : if (incr3) \
3823 : k = canditer_next(cihi) - seqbase3; \
3824 : dst[l] = BETWEEN(((const TYPE *) src)[i], \
3825 : ((const TYPE *) lo)[j], \
3826 : ((const TYPE *) hi)[k], \
3827 : TYPE); \
3828 : nils += is_bit_nil(dst[l]); \
3829 : } \
3830 : TIMEOUT_CHECK(qry_ctx, \
3831 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
3832 : } while (0)
3833 :
3834 : static BAT *
3835 12973 : BATcalcbetween_intern(const void *src, bool incr1, const char *hp1, int wd1,
3836 : const void *lo, bool incr2, const char *hp2, int wd2,
3837 : const void *hi, bool incr3, const char *hp3, int wd3,
3838 : int tp,
3839 : struct canditer *restrict ci,
3840 : struct canditer *restrict cilo,
3841 : struct canditer *restrict cihi,
3842 : oid seqbase1, oid seqbase2, oid seqbase3,
3843 : bool symmetric, bool anti,
3844 : bool linc, bool hinc, bool nils_false, const char *func)
3845 : {
3846 12973 : BAT *bn;
3847 12973 : BUN nils = 0;
3848 12973 : BUN i, j, k, l, ncand = ci->ncand;
3849 12973 : bit *restrict dst;
3850 12973 : const void *nil;
3851 12973 : int (*atomcmp)(const void *, const void *);
3852 :
3853 12973 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
3854 :
3855 12972 : bn = COLnew(ci->hseq, TYPE_bit, ncand, TRANSIENT);
3856 12973 : if (bn == NULL)
3857 : return NULL;
3858 12973 : if (ncand == 0)
3859 : return bn;
3860 :
3861 12005 : dst = (bit *) Tloc(bn, 0);
3862 :
3863 12005 : tp = ATOMbasetype(tp);
3864 :
3865 12005 : switch (tp) {
3866 37 : case TYPE_bte:
3867 37 : if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
3868 315 : BETWEEN_LOOP_TYPE(bte, canditer_next_dense);
3869 : else
3870 8 : BETWEEN_LOOP_TYPE(bte, canditer_next);
3871 : break;
3872 5 : case TYPE_sht:
3873 5 : if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
3874 132 : BETWEEN_LOOP_TYPE(sht, canditer_next_dense);
3875 : else
3876 0 : BETWEEN_LOOP_TYPE(sht, canditer_next);
3877 : break;
3878 4875 : case TYPE_int:
3879 4875 : if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
3880 96340 : BETWEEN_LOOP_TYPE(int, canditer_next_dense);
3881 : else
3882 16 : BETWEEN_LOOP_TYPE(int, canditer_next);
3883 : break;
3884 6970 : case TYPE_lng:
3885 6970 : if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
3886 59564656 : BETWEEN_LOOP_TYPE(lng, canditer_next_dense);
3887 : else
3888 1124 : BETWEEN_LOOP_TYPE(lng, canditer_next);
3889 : break;
3890 : #ifdef HAVE_HGE
3891 8 : case TYPE_hge:
3892 8 : if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
3893 4691 : BETWEEN_LOOP_TYPE(hge, canditer_next_dense);
3894 : else
3895 228 : BETWEEN_LOOP_TYPE(hge, canditer_next);
3896 : break;
3897 : #endif
3898 2 : case TYPE_flt:
3899 2 : if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
3900 30 : BETWEEN_LOOP_TYPE(flt, canditer_next_dense);
3901 : else
3902 0 : BETWEEN_LOOP_TYPE(flt, canditer_next);
3903 : break;
3904 64 : case TYPE_dbl:
3905 64 : if (ci->tpe == cand_dense && cilo->tpe == cand_dense && cihi->tpe == cand_dense)
3906 13092 : BETWEEN_LOOP_TYPE(dbl, canditer_next_dense);
3907 : else
3908 4 : BETWEEN_LOOP_TYPE(dbl, canditer_next);
3909 : break;
3910 44 : default:
3911 44 : assert(tp != TYPE_oid);
3912 44 : if (!ATOMlinear(tp) ||
3913 44 : (atomcmp = ATOMcompare(tp)) == NULL) {
3914 0 : BBPunfix(bn->batCacheid);
3915 0 : GDKerror("%s: bad input type %s.\n",
3916 : func, ATOMname(tp));
3917 0 : return NULL;
3918 : }
3919 44 : nil = ATOMnilptr(tp);
3920 44 : i = j = k = 0;
3921 299 : TIMEOUT_LOOP_IDX(l, ncand, qry_ctx) {
3922 167 : if (incr1)
3923 167 : i = canditer_next(ci) - seqbase1;
3924 167 : if (incr2)
3925 152 : j = canditer_next(cilo) - seqbase2;
3926 167 : if (incr3)
3927 157 : k = canditer_next(cihi) - seqbase3;
3928 167 : const void *p1, *p2, *p3;
3929 334 : p1 = hp1
3930 163 : ? (const void *) (hp1 + VarHeapVal(src, i, wd1))
3931 330 : : (const void *) ((const char *) src + i * wd1);
3932 334 : p2 = hp2
3933 148 : ? (const void *) (hp2 + VarHeapVal(lo, j, wd2))
3934 315 : : (const void *) ((const char *) lo + j * wd2);
3935 334 : p3 = hp3
3936 153 : ? (const void *) (hp3 + VarHeapVal(hi, k, wd3))
3937 320 : : (const void *) ((const char *) hi + k * wd3);
3938 167 : dst[l] = BETWEEN(p1, p2, p3, any);
3939 167 : nils += is_bit_nil(dst[l]);
3940 : }
3941 44 : TIMEOUT_CHECK(qry_ctx,
3942 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
3943 : break;
3944 : }
3945 :
3946 12002 : BATsetcount(bn, ncand);
3947 :
3948 12003 : bn->tsorted = ncand <= 1 || nils == ncand;
3949 12003 : bn->trevsorted = ncand <= 1 || nils == ncand;
3950 12003 : bn->tkey = ncand <= 1;
3951 12003 : bn->tnil = nils != 0;
3952 12003 : bn->tnonil = nils == 0;
3953 :
3954 12003 : return bn;
3955 0 : bailout:
3956 0 : BBPunfix(bn->batCacheid);
3957 0 : return NULL;
3958 : }
3959 :
3960 : #define HANDLE_TIMEOUT(qry_ctx) \
3961 : do { \
3962 : GDKerror("%s\n", TIMEOUT_MESSAGE(qry_ctx)); \
3963 : BBPreclaim(bn); \
3964 : bn = NULL; \
3965 : } while (0)
3966 :
3967 : BAT *
3968 12735 : BATcalcbetween(BAT *b, BAT *lo, BAT *hi, BAT *s, BAT *slo, BAT *shi,
3969 : bool symmetric, bool linc, bool hinc, bool nils_false, bool anti)
3970 : {
3971 12735 : lng t0 = 0;
3972 12735 : BAT *bn;
3973 12735 : struct canditer ci, cilo, cihi;
3974 :
3975 12735 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
3976 :
3977 12735 : BATcheck(b, NULL);
3978 12735 : BATcheck(lo, NULL);
3979 12735 : BATcheck(hi, NULL);
3980 :
3981 12735 : canditer_init(&ci, b, s);
3982 12735 : canditer_init(&cilo, lo, slo);
3983 12734 : canditer_init(&cihi, hi, shi);
3984 12734 : if (ci.ncand != cilo.ncand || ci.hseq != cilo.hseq ||
3985 12734 : ci.ncand != cihi.ncand || ci.hseq != cihi.hseq) {
3986 0 : GDKerror("inputs not the same size.\n");
3987 0 : return NULL;
3988 : }
3989 :
3990 12734 : if (BATtvoid(b) &&
3991 0 : BATtvoid(lo) &&
3992 0 : BATtvoid(hi)) {
3993 0 : bit res;
3994 :
3995 0 : res = BETWEEN(b->tseqbase, lo->tseqbase, hi->tseqbase, oid);
3996 0 : return BATconstant(ci.hseq, TYPE_bit, &res, ci.ncand,
3997 : TRANSIENT);
3998 : }
3999 :
4000 12734 : BATiter bi = bat_iterator(b);
4001 12735 : BATiter loi = bat_iterator(lo);
4002 12735 : BATiter hii = bat_iterator(hi);
4003 12734 : if (b->ttype == TYPE_void || lo->ttype == TYPE_void || hi->ttype == TYPE_void) {
4004 0 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
4005 0 : bn = COLnew(ci.seq, TYPE_bit, ci.ncand, TRANSIENT);
4006 0 : if (bn) {
4007 0 : bit *restrict dst = (bit *) Tloc(bn, 0);
4008 0 : BUN i, j, k, l;
4009 0 : BUN nils = 0;
4010 0 : TIMEOUT_LOOP_IDX(l, ci.ncand, qry_ctx) {
4011 0 : i = canditer_next(&ci) - b->hseqbase;
4012 0 : j = canditer_next(&cilo) - lo->hseqbase;
4013 0 : k = canditer_next(&cihi) - hi->hseqbase;
4014 0 : dst[l] = BETWEEN(BUNtoid(b, i),
4015 : BUNtoid(lo, j),
4016 : BUNtoid(hi, k), oid);
4017 0 : nils += is_bit_nil(dst[l]);
4018 : }
4019 0 : BATsetcount(bn, ci.ncand);
4020 0 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
4021 0 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
4022 0 : bn->tkey = ci.ncand <= 1;
4023 0 : bn->tnil = nils != 0;
4024 0 : bn->tnonil = nils == 0;
4025 0 : TIMEOUT_CHECK(qry_ctx, HANDLE_TIMEOUT(qry_ctx));
4026 : }
4027 : } else {
4028 12821 : bn = BATcalcbetween_intern(bi.base, 1,
4029 12735 : bi.vh ? bi.vh->base : NULL,
4030 12735 : bi.width,
4031 12735 : loi.base, 1,
4032 12735 : loi.vh ? loi.vh->base : NULL,
4033 12735 : loi.width,
4034 12735 : hii.base, 1,
4035 12735 : hii.vh ? hii.vh->base : NULL,
4036 12735 : hii.width,
4037 12735 : bi.type,
4038 : &ci, &cilo, &cihi,
4039 : b->hseqbase, lo->hseqbase, hi->hseqbase,
4040 : symmetric, anti, linc, hinc,
4041 : nils_false, __func__);
4042 : }
4043 12735 : bat_iterator_end(&bi);
4044 12734 : bat_iterator_end(&loi);
4045 12733 : bat_iterator_end(&hii);
4046 :
4047 12735 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",lo=" ALGOBATFMT ",hi=" ALGOBATFMT
4048 : ",s=" ALGOOPTBATFMT ",slo=" ALGOOPTBATFMT ",shi=" ALGOOPTBATFMT
4049 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
4050 : ALGOBATPAR(b), ALGOBATPAR(lo), ALGOBATPAR(hi),
4051 : ALGOOPTBATPAR(s), ALGOOPTBATPAR(slo), ALGOOPTBATPAR(shi),
4052 : ALGOOPTBATPAR(bn), GDKusec() - t0);
4053 :
4054 : return bn;
4055 : }
4056 :
4057 : BAT *
4058 144 : BATcalcbetweencstcst(BAT *b, const ValRecord *lo, const ValRecord *hi,
4059 : BAT *s,
4060 : bool symmetric, bool linc, bool hinc, bool nils_false,
4061 : bool anti)
4062 : {
4063 144 : lng t0 = 0;
4064 144 : BAT *bn;
4065 144 : struct canditer ci;
4066 :
4067 144 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
4068 :
4069 144 : BATcheck(b, NULL);
4070 :
4071 378 : if (ATOMbasetype(b->ttype) != ATOMbasetype(lo->vtype) ||
4072 189 : ATOMbasetype(b->ttype) != ATOMbasetype(hi->vtype)) {
4073 0 : GDKerror("incompatible input types.\n");
4074 0 : return NULL;
4075 : }
4076 :
4077 144 : canditer_init(&ci, b, s);
4078 :
4079 144 : BATiter bi = bat_iterator(b);
4080 144 : if (b->ttype == TYPE_void) {
4081 0 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
4082 0 : bn = COLnew(ci.seq, TYPE_bit, ci.ncand, TRANSIENT);
4083 0 : if (bn) {
4084 0 : bit *restrict dst = (bit *) Tloc(bn, 0);
4085 0 : BUN i, l;
4086 0 : BUN nils = 0;
4087 0 : TIMEOUT_LOOP_IDX(l, ci.ncand, qry_ctx) {
4088 0 : i = canditer_next(&ci) - b->hseqbase;
4089 0 : dst[l] = BETWEEN(BUNtoid(b, i), lo->val.oval,
4090 : hi->val.oval, oid);
4091 0 : nils += is_bit_nil(dst[l]);
4092 : }
4093 0 : BATsetcount(bn, ci.ncand);
4094 0 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
4095 0 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
4096 0 : bn->tkey = ci.ncand <= 1;
4097 0 : bn->tnil = nils != 0;
4098 0 : bn->tnonil = nils == 0;
4099 0 : TIMEOUT_CHECK(qry_ctx, HANDLE_TIMEOUT(qry_ctx));
4100 : }
4101 : } else {
4102 144 : bn = BATcalcbetween_intern(bi.base, 1,
4103 144 : bi.vh ? bi.vh->base : NULL,
4104 144 : bi.width,
4105 : VALptr(lo), 0, NULL, 0,
4106 : VALptr(hi), 0, NULL, 0,
4107 144 : bi.type,
4108 : &ci,
4109 144 : &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
4110 144 : &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
4111 : b->hseqbase, 0, 0, symmetric, anti,
4112 : linc, hinc, nils_false,
4113 : __func__);
4114 : }
4115 144 : bat_iterator_end(&bi);
4116 :
4117 144 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
4118 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
4119 : ALGOBATPAR(b), ALGOOPTBATPAR(s),
4120 : ALGOOPTBATPAR(bn), GDKusec() - t0);
4121 :
4122 : return bn;
4123 : }
4124 :
4125 : BAT *
4126 53 : BATcalcbetweenbatcst(BAT *b, BAT *lo, const ValRecord *hi, BAT *s, BAT *slo,
4127 : bool symmetric, bool linc, bool hinc, bool nils_false,
4128 : bool anti)
4129 : {
4130 53 : lng t0 = 0;
4131 53 : BAT *bn;
4132 53 : struct canditer ci, cilo;
4133 :
4134 53 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
4135 :
4136 53 : BATcheck(b, NULL);
4137 53 : BATcheck(lo, NULL);
4138 :
4139 147 : if (ATOMbasetype(b->ttype) != ATOMbasetype(hi->vtype)) {
4140 0 : GDKerror("incompatible input types.\n");
4141 0 : return NULL;
4142 : }
4143 :
4144 53 : canditer_init(&ci, b, s);
4145 53 : canditer_init(&cilo, lo, slo);
4146 53 : if (ci.ncand != cilo.ncand || ci.hseq != cilo.hseq) {
4147 0 : GDKerror("inputs not the same size.\n");
4148 0 : return NULL;
4149 : }
4150 :
4151 53 : BATiter bi = bat_iterator(b);
4152 53 : BATiter loi = bat_iterator(lo);
4153 53 : if (b->ttype == TYPE_void || lo->ttype == TYPE_void) {
4154 0 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
4155 0 : bn = COLnew(ci.seq, TYPE_bit, ci.ncand, TRANSIENT);
4156 0 : if (bn) {
4157 0 : bit *restrict dst = (bit *) Tloc(bn, 0);
4158 0 : BUN i, j, l;
4159 0 : BUN nils = 0;
4160 0 : TIMEOUT_LOOP_IDX(l, ci.ncand, qry_ctx) {
4161 0 : i = canditer_next(&ci) - b->hseqbase;
4162 0 : j = canditer_next(&cilo) - lo->hseqbase;
4163 0 : dst[l] = BETWEEN(BUNtoid(b, i), BUNtoid(lo, j),
4164 : hi->val.oval, oid);
4165 0 : nils += is_bit_nil(dst[l]);
4166 : }
4167 0 : BATsetcount(bn, ci.ncand);
4168 0 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
4169 0 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
4170 0 : bn->tkey = ci.ncand <= 1;
4171 0 : bn->tnil = nils != 0;
4172 0 : bn->tnonil = nils == 0;
4173 0 : TIMEOUT_CHECK(qry_ctx, HANDLE_TIMEOUT(qry_ctx));
4174 : }
4175 : } else {
4176 57 : bn = BATcalcbetween_intern(bi.base, 1,
4177 53 : bi.vh ? bi.vh->base : NULL,
4178 53 : bi.width,
4179 53 : loi.base, 1,
4180 53 : loi.vh ? loi.vh->base : NULL,
4181 53 : loi.width,
4182 : VALptr(hi), 0, NULL, 0,
4183 53 : bi.type,
4184 : &ci,
4185 : &cilo,
4186 53 : &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
4187 : b->hseqbase, lo->hseqbase, 0,
4188 : symmetric, anti,
4189 : linc, hinc, nils_false,
4190 : __func__);
4191 : }
4192 53 : bat_iterator_end(&bi);
4193 53 : bat_iterator_end(&loi);
4194 :
4195 53 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",lo=" ALGOBATFMT
4196 : ",s=" ALGOOPTBATFMT ",slo=" ALGOOPTBATFMT
4197 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
4198 : ALGOBATPAR(b), ALGOBATPAR(lo),
4199 : ALGOOPTBATPAR(s), ALGOOPTBATPAR(slo),
4200 : ALGOOPTBATPAR(bn), GDKusec() - t0);
4201 :
4202 : return bn;
4203 : }
4204 :
4205 : BAT *
4206 42 : BATcalcbetweencstbat(BAT *b, const ValRecord *lo, BAT *hi, BAT *s, BAT *shi,
4207 : bool symmetric, bool linc, bool hinc, bool nils_false,
4208 : bool anti)
4209 : {
4210 42 : lng t0 = 0;
4211 42 : BAT *bn;
4212 42 : struct canditer ci, cihi;
4213 :
4214 42 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
4215 :
4216 42 : BATcheck(b, NULL);
4217 42 : BATcheck(hi, NULL);
4218 :
4219 104 : if (ATOMbasetype(b->ttype) != ATOMbasetype(lo->vtype)) {
4220 0 : GDKerror("incompatible input types.\n");
4221 0 : return NULL;
4222 : }
4223 :
4224 42 : canditer_init(&ci, b, s);
4225 42 : canditer_init(&cihi, hi, shi);
4226 42 : if (ci.ncand != cihi.ncand || ci.hseq != cihi.hseq) {
4227 0 : GDKerror("inputs not the same size.\n");
4228 0 : return NULL;
4229 : }
4230 :
4231 42 : BATiter bi = bat_iterator(b);
4232 42 : BATiter hii = bat_iterator(hi);
4233 42 : if (b->ttype == TYPE_void || hi->ttype == TYPE_void) {
4234 1 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
4235 1 : bn = COLnew(ci.seq, TYPE_bit, ci.ncand, TRANSIENT);
4236 1 : if (bn) {
4237 1 : bit *restrict dst = (bit *) Tloc(bn, 0);
4238 1 : BUN i, k, l;
4239 1 : BUN nils = 0;
4240 4 : TIMEOUT_LOOP_IDX(l, ci.ncand, qry_ctx) {
4241 1 : i = canditer_next(&ci) - b->hseqbase;
4242 1 : k = canditer_next(&cihi) - hi->hseqbase;
4243 1 : dst[l] = BETWEEN(BUNtoid(b, i), lo->val.oval,
4244 : BUNtoid(hi, k), oid);
4245 1 : nils += is_bit_nil(dst[l]);
4246 : }
4247 1 : BATsetcount(bn, ci.ncand);
4248 1 : bn->tsorted = ci.ncand <= 1 || nils == ci.ncand;
4249 1 : bn->trevsorted = ci.ncand <= 1 || nils == ci.ncand;
4250 1 : bn->tkey = ci.ncand <= 1;
4251 1 : bn->tnil = nils != 0;
4252 1 : bn->tnonil = nils == 0;
4253 1 : TIMEOUT_CHECK(qry_ctx, HANDLE_TIMEOUT(qry_ctx));
4254 : }
4255 : } else {
4256 48 : bn = BATcalcbetween_intern(bi.base, 1,
4257 41 : bi.vh ? bi.vh->base : NULL,
4258 41 : bi.width,
4259 : VALptr(lo), 0, NULL, 0,
4260 41 : hii.base, 1,
4261 41 : hii.vh ? hii.vh->base : NULL,
4262 41 : hii.width,
4263 41 : bi.type,
4264 : &ci,
4265 41 : &(struct canditer){.tpe=cand_dense, .ncand=ci.ncand},
4266 : &cihi,
4267 : b->hseqbase, 0, hi->hseqbase,
4268 : symmetric, anti,
4269 : linc, hinc, nils_false,
4270 : __func__);
4271 : }
4272 42 : bat_iterator_end(&bi);
4273 42 : bat_iterator_end(&hii);
4274 :
4275 41 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",hi=" ALGOBATFMT
4276 : ",s=" ALGOOPTBATFMT ",shi=" ALGOOPTBATFMT
4277 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
4278 : ALGOBATPAR(b), ALGOBATPAR(hi),
4279 : ALGOOPTBATPAR(s), ALGOOPTBATPAR(shi),
4280 : ALGOOPTBATPAR(bn), GDKusec() - t0);
4281 :
4282 : return bn;
4283 : }
4284 :
4285 : gdk_return
4286 41 : VARcalcbetween(ValPtr ret, const ValRecord *v, const ValRecord *lo,
4287 : const ValRecord *hi, bool symmetric, bool linc, bool hinc,
4288 : bool nils_false, bool anti)
4289 : {
4290 41 : int t;
4291 41 : int (*atomcmp)(const void *, const void *);
4292 41 : const void *nil;
4293 :
4294 41 : t = v->vtype;
4295 41 : if (t != lo->vtype || t != hi->vtype) {
4296 0 : GDKerror("incompatible input types.\n");
4297 0 : return GDK_FAIL;
4298 : }
4299 41 : if (!ATOMlinear(t)) {
4300 0 : GDKerror("non-linear input type.\n");
4301 0 : return GDK_FAIL;
4302 : }
4303 :
4304 41 : t = ATOMbasetype(t);
4305 :
4306 41 : *ret = (ValRecord) {.vtype = TYPE_bit};
4307 41 : switch (t) {
4308 17 : case TYPE_bte:
4309 17 : ret->val.btval = BETWEEN(v->val.btval, lo->val.btval, hi->val.btval, bte);
4310 17 : break;
4311 2 : case TYPE_sht:
4312 2 : ret->val.btval = BETWEEN(v->val.shval, lo->val.shval, hi->val.shval, sht);
4313 2 : break;
4314 3 : case TYPE_int:
4315 3 : ret->val.btval = BETWEEN(v->val.ival, lo->val.ival, hi->val.ival, int);
4316 3 : break;
4317 8 : case TYPE_lng:
4318 8 : ret->val.btval = BETWEEN(v->val.lval, lo->val.lval, hi->val.lval, lng);
4319 8 : break;
4320 : #ifdef HAVE_HGE
4321 0 : case TYPE_hge:
4322 0 : ret->val.btval = BETWEEN(v->val.hval, lo->val.hval, hi->val.hval, hge);
4323 0 : break;
4324 : #endif
4325 0 : case TYPE_flt:
4326 0 : ret->val.btval = BETWEEN(v->val.fval, lo->val.fval, hi->val.fval, flt);
4327 0 : break;
4328 1 : case TYPE_dbl:
4329 1 : ret->val.btval = BETWEEN(v->val.dval, lo->val.dval, hi->val.dval, dbl);
4330 1 : break;
4331 10 : default:
4332 10 : nil = ATOMnilptr(t);
4333 10 : atomcmp = ATOMcompare(t);
4334 10 : ret->val.btval = BETWEEN(VALptr(v), VALptr(lo), VALptr(hi), any);
4335 10 : break;
4336 : }
4337 : return GDK_SUCCEED;
4338 : }
4339 :
4340 : /* ---------------------------------------------------------------------- */
4341 : /* if-then-else (any type) */
4342 :
4343 : #define IFTHENELSELOOP(TYPE) \
4344 : do { \
4345 : TIMEOUT_LOOP_IDX(i, cnt, qry_ctx) { \
4346 : if (src[i] && !is_bit_nil(src[i])) { \
4347 : ((TYPE *) dst)[i] = ((TYPE *) col1)[k]; \
4348 : } else { \
4349 : ((TYPE *) dst)[i] = ((TYPE *) col2)[l]; \
4350 : } \
4351 : k += incr1; \
4352 : l += incr2; \
4353 : } \
4354 : TIMEOUT_CHECK(qry_ctx, \
4355 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
4356 : } while (0)
4357 : #define IFTHENELSELOOP_msk(TYPE) \
4358 : do { \
4359 : TIMEOUT_LOOP_IDX(i, cnt, qry_ctx) { \
4360 : if (n == 32) { \
4361 : n = 0; \
4362 : mask = src[i / 32]; \
4363 : } \
4364 : ((TYPE *) dst)[i] = mask & (1U << n) ? \
4365 : ((TYPE *) col1)[k] : \
4366 : ((TYPE *) col2)[l]; \
4367 : k += incr1; \
4368 : l += incr2; \
4369 : n++; \
4370 : } \
4371 : TIMEOUT_CHECK(qry_ctx, \
4372 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
4373 : } while (0)
4374 :
4375 : static BAT *
4376 4184 : BATcalcifthenelse_intern(BATiter *bi,
4377 : const void *col1, bool incr1, const char *heap1,
4378 : int width1, bool nonil1, oid seq1,
4379 : const void *col2, bool incr2, const char *heap2,
4380 : int width2, bool nonil2, oid seq2,
4381 : int tpe)
4382 : {
4383 4184 : BAT *bn;
4384 4184 : void *restrict dst;
4385 4184 : BUN i, k, l;
4386 4184 : const void *p;
4387 4184 : BUN cnt = bi->count;
4388 :
4389 4184 : QryCtx *qry_ctx = MT_thread_get_qry_ctx();
4390 :
4391 : /* col1 and col2 can only be NULL for void columns */
4392 4183 : assert(col1 != NULL || ATOMtype(tpe) == TYPE_oid);
4393 4183 : assert(col2 != NULL || ATOMtype(tpe) == TYPE_oid);
4394 4183 : assert(col1 != NULL || heap1 == NULL);
4395 4183 : assert(col2 != NULL || heap2 == NULL);
4396 4183 : assert(col1 != NULL || incr1 == true);
4397 4183 : assert(col2 != NULL || incr2 == true);
4398 :
4399 4183 : bn = COLnew(bi->b->hseqbase, ATOMtype(tpe), cnt, TRANSIENT);
4400 4184 : if (bn == NULL)
4401 : return NULL;
4402 4184 : if (cnt == 0)
4403 : return bn;
4404 :
4405 3549 : dst = (void *) Tloc(bn, 0);
4406 3549 : k = l = 0;
4407 3549 : if (bn->tvheap) {
4408 293 : assert((heap1 != NULL && width1 > 0) || (width1 == 0 && incr1 == 0));
4409 293 : assert((heap2 != NULL && width2 > 0) || (width2 == 0 && incr2 == 0));
4410 293 : if (ATOMstorage(bi->type) == TYPE_msk) {
4411 0 : const uint32_t *src = bi->base;
4412 0 : BUN n = cnt / 32;
4413 0 : TIMEOUT_LOOP_IDX(i, n + 1, qry_ctx) {
4414 0 : BUN rem = i == n ? cnt % 32 : 32;
4415 0 : uint32_t mask = rem != 0 ? src[i] : 0;
4416 0 : for (BUN j = 0; j < rem; j++) {
4417 0 : if (mask & (1U << j)) {
4418 0 : if (heap1)
4419 0 : p = heap1 + VarHeapVal(col1, k, width1);
4420 : else
4421 : p = col1;
4422 : } else {
4423 0 : if (heap2)
4424 0 : p = heap2 + VarHeapVal(col2, l, width2);
4425 : else
4426 : p = col2;
4427 : }
4428 0 : if (tfastins_nocheckVAR(bn, i, p) != GDK_SUCCEED) {
4429 0 : goto bailout;
4430 : }
4431 0 : k += incr1;
4432 0 : l += incr2;
4433 : }
4434 : }
4435 0 : TIMEOUT_CHECK(qry_ctx,
4436 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
4437 : } else {
4438 293 : const bit *src = bi->base;
4439 192530 : TIMEOUT_LOOP_IDX(i, cnt, qry_ctx) {
4440 191651 : if (src[i] && !is_bit_nil(src[i])) {
4441 149141 : if (heap1)
4442 2721 : p = heap1 + VarHeapVal(col1, k, width1);
4443 : else
4444 : p = col1;
4445 : } else {
4446 42510 : if (heap2)
4447 9125 : p = heap2 + VarHeapVal(col2, l, width2);
4448 : else
4449 : p = col2;
4450 : }
4451 191651 : if (tfastins_nocheckVAR(bn, i, p) != GDK_SUCCEED) {
4452 0 : goto bailout;
4453 : }
4454 191651 : k += incr1;
4455 191651 : l += incr2;
4456 : }
4457 293 : TIMEOUT_CHECK(qry_ctx,
4458 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
4459 : }
4460 : } else {
4461 3256 : assert(heap1 == NULL);
4462 3256 : assert(heap2 == NULL);
4463 3256 : if (ATOMstorage(bi->type) == TYPE_msk) {
4464 0 : const uint32_t *src = bi->base;
4465 0 : uint32_t mask = 0;
4466 0 : BUN n = 32;
4467 0 : if (ATOMtype(tpe) == TYPE_oid) {
4468 0 : TIMEOUT_LOOP_IDX(i, cnt, qry_ctx) {
4469 0 : if (n == 32) {
4470 0 : n = 0;
4471 0 : mask = src[i / 32];
4472 : }
4473 0 : ((oid *) dst)[i] = mask & (1U << n) ?
4474 0 : col1 ? ((oid *)col1)[k] : seq1 :
4475 0 : col2 ? ((oid *)col2)[l] : seq2;
4476 0 : k += incr1;
4477 0 : l += incr2;
4478 0 : seq1 += incr1;
4479 0 : seq2 += incr2;
4480 0 : n++;
4481 : }
4482 0 : TIMEOUT_CHECK(qry_ctx,
4483 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
4484 0 : } else if (ATOMstorage(tpe) == TYPE_msk) {
4485 0 : uint32_t v1, v2;
4486 0 : if (incr1) {
4487 : v1 = 0;
4488 : } else {
4489 0 : v1 = * (msk *) col1 ? ~0U : 0U;
4490 : }
4491 0 : if (incr2) {
4492 : v2 = 0;
4493 : } else {
4494 0 : v2 = * (msk *) col2 ? ~0U : 0U;
4495 : }
4496 0 : n = (cnt + 31) / 32;
4497 0 : TIMEOUT_LOOP_IDX(i, n, qry_ctx) {
4498 0 : if (incr1)
4499 0 : v1 = ((uint32_t *) col1)[i];
4500 0 : if (incr2)
4501 0 : v2 = ((uint32_t *) col2)[i];
4502 0 : ((uint32_t *) dst)[i] = (src[i] & v1)
4503 0 : | (~src[i] & v2);
4504 : }
4505 0 : TIMEOUT_CHECK(qry_ctx,
4506 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
4507 : } else {
4508 0 : switch (bn->twidth) {
4509 : case 1:
4510 0 : IFTHENELSELOOP_msk(bte);
4511 : break;
4512 : case 2:
4513 0 : IFTHENELSELOOP_msk(sht);
4514 : break;
4515 : case 4:
4516 0 : IFTHENELSELOOP_msk(int);
4517 : break;
4518 : case 8:
4519 0 : IFTHENELSELOOP_msk(lng);
4520 : break;
4521 : case 16:
4522 : #ifdef HAVE_HGE
4523 0 : IFTHENELSELOOP_msk(hge);
4524 : #else
4525 : IFTHENELSELOOP_msk(uuid);
4526 : #endif
4527 : break;
4528 : default:
4529 0 : TIMEOUT_LOOP_IDX(i, cnt, qry_ctx) {
4530 0 : if (n == 32) {
4531 0 : n = 0;
4532 0 : mask = src[i / 32];
4533 : }
4534 0 : if (mask & (1U << n))
4535 0 : p = ((const char *) col1) + k * width1;
4536 : else
4537 0 : p = ((const char *) col2) + l * width2;
4538 0 : memcpy(dst, p, bn->twidth);
4539 0 : dst = (void *) ((char *) dst + bn->twidth);
4540 0 : k += incr1;
4541 0 : l += incr2;
4542 0 : n++;
4543 : }
4544 0 : TIMEOUT_CHECK(qry_ctx,
4545 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
4546 : }
4547 : }
4548 : } else {
4549 3256 : const bit *src = bi->base;
4550 3256 : if (ATOMtype(tpe) == TYPE_oid) {
4551 0 : TIMEOUT_LOOP_IDX(i, cnt, qry_ctx) {
4552 0 : if (src[i] && !is_bit_nil(src[i])) {
4553 0 : ((oid *) dst)[i] = col1 ? ((oid *) col1)[k] : seq1;
4554 : } else {
4555 0 : ((oid *) dst)[i] = col2 ? ((oid *) col2)[k] : seq2;
4556 : }
4557 0 : k += incr1;
4558 0 : l += incr2;
4559 0 : seq1 += incr1;
4560 0 : seq2 += incr2;
4561 : }
4562 0 : TIMEOUT_CHECK(qry_ctx,
4563 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
4564 3256 : } else if (ATOMstorage(tpe) == TYPE_msk) {
4565 0 : uint32_t v1, v2;
4566 0 : uint32_t *d = dst;
4567 0 : if (incr1) {
4568 : v1 = 0;
4569 : } else {
4570 0 : v1 = * (msk *) col1 ? ~0U : 0U;
4571 : }
4572 0 : if (incr2) {
4573 : v2 = 0;
4574 : } else {
4575 0 : v2 = * (msk *) col2 ? ~0U : 0U;
4576 : }
4577 0 : i = 0;
4578 0 : TIMEOUT_LOOP(cnt / 32, qry_ctx) {
4579 0 : uint32_t mask = 0;
4580 0 : if (incr1)
4581 0 : v1 = ((uint32_t *) col1)[i/32];
4582 0 : if (incr2)
4583 0 : v2 = ((uint32_t *) col2)[i/32];
4584 0 : for (int n = 0; n < 32; n++) {
4585 0 : mask |= (uint32_t) (src[i] != 0) << n;
4586 : }
4587 0 : *d++ = (mask & v1) | (~mask & v2);
4588 0 : i += 32;
4589 : }
4590 0 : TIMEOUT_CHECK(qry_ctx,
4591 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
4592 : /* do the last word */
4593 0 : if (i < cnt) {
4594 0 : uint32_t mask = 0;
4595 0 : if (incr1)
4596 0 : v1 = ((uint32_t *) col1)[i/32];
4597 0 : if (incr2)
4598 0 : v2 = ((uint32_t *) col2)[i/32];
4599 0 : for (int n = 0; n < 32; n++) {
4600 0 : mask |= (uint32_t) (src[i] != 0) << n;
4601 0 : if (++i == cnt)
4602 : break;
4603 : }
4604 0 : *d++ = (mask & v1) | (~mask & v2);
4605 : }
4606 : } else {
4607 3256 : switch (bn->twidth) {
4608 : case 1:
4609 5659971 : IFTHENELSELOOP(bte);
4610 : break;
4611 : case 2:
4612 202 : IFTHENELSELOOP(sht);
4613 : break;
4614 : case 4:
4615 661937 : IFTHENELSELOOP(int);
4616 : break;
4617 : case 8:
4618 80089 : IFTHENELSELOOP(lng);
4619 : break;
4620 : case 16:
4621 : #ifdef HAVE_HGE
4622 26892 : IFTHENELSELOOP(hge);
4623 : #else
4624 : IFTHENELSELOOP(uuid);
4625 : #endif
4626 : break;
4627 : default:
4628 0 : TIMEOUT_LOOP_IDX(i, cnt, qry_ctx) {
4629 0 : if (src[i] && !is_bit_nil(src[i])) {
4630 0 : p = ((const char *) col1) + k * width1;
4631 : } else {
4632 0 : p = ((const char *) col2) + l * width2;
4633 : }
4634 0 : memcpy(dst, p, bn->twidth);
4635 0 : dst = (void *) ((char *) dst + bn->twidth);
4636 0 : k += incr1;
4637 0 : l += incr2;
4638 : }
4639 0 : TIMEOUT_CHECK(qry_ctx,
4640 : GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
4641 : }
4642 : }
4643 : }
4644 : }
4645 :
4646 3549 : BATsetcount(bn, cnt);
4647 :
4648 3549 : bn->tsorted = cnt <= 1;
4649 3549 : bn->trevsorted = cnt <= 1;
4650 3549 : bn->tkey = cnt <= 1;
4651 3549 : bn->tnil = 0;
4652 3549 : bn->tnonil = nonil1 && nonil2;
4653 :
4654 3549 : return bn;
4655 0 : bailout:
4656 0 : BBPreclaim(bn);
4657 0 : return NULL;
4658 : }
4659 :
4660 : BAT *
4661 48 : BATcalcifthenelse(BAT *b, BAT *b1, BAT *b2)
4662 : {
4663 48 : lng t0 = 0;
4664 48 : BAT *bn;
4665 :
4666 48 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
4667 :
4668 48 : BATcheck(b, NULL);
4669 48 : BATcheck(b1, NULL);
4670 48 : BATcheck(b2, NULL);
4671 :
4672 48 : BATiter bi = bat_iterator(b);
4673 48 : BATiter b1i = bat_iterator(b1);
4674 48 : BATiter b2i = bat_iterator(b2);
4675 96 : if (checkbats(&bi, &b1i, __func__) != GDK_SUCCEED ||
4676 48 : checkbats(&bi, &b2i, __func__) != GDK_SUCCEED) {
4677 0 : bat_iterator_end(&bi);
4678 0 : bat_iterator_end(&b1i);
4679 0 : bat_iterator_end(&b2i);
4680 0 : return NULL;
4681 : }
4682 144 : if (b->ttype != TYPE_bit || ATOMtype(b1->ttype) != ATOMtype(b2->ttype)) {
4683 0 : bat_iterator_end(&bi);
4684 0 : bat_iterator_end(&b1i);
4685 0 : bat_iterator_end(&b2i);
4686 0 : GDKerror("\"then\" and \"else\" BATs have different types.\n");
4687 0 : return NULL;
4688 : }
4689 28 : bn = BATcalcifthenelse_intern(&bi,
4690 48 : b1i.base, true, b1i.vh ? b1i.vh->base : NULL, b1i.width, b1i.nonil, b1->tseqbase,
4691 48 : b2i.base, true, b2i.vh ? b2i.vh->base : NULL, b2i.width, b2i.nonil, b2->tseqbase,
4692 48 : b1i.type);
4693 48 : bat_iterator_end(&bi);
4694 48 : bat_iterator_end(&b1i);
4695 48 : bat_iterator_end(&b2i);
4696 :
4697 48 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",b1=" ALGOBATFMT ",b2=" ALGOBATFMT
4698 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
4699 : ALGOBATPAR(b), ALGOBATPAR(b1), ALGOBATPAR(b2),
4700 : ALGOOPTBATPAR(bn), GDKusec() - t0);
4701 :
4702 : return bn;
4703 : }
4704 :
4705 : BAT *
4706 125 : BATcalcifthenelsecst(BAT *b, BAT *b1, const ValRecord *c2)
4707 : {
4708 125 : lng t0 = 0;
4709 125 : BAT *bn;
4710 :
4711 125 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
4712 :
4713 125 : BATcheck(b, NULL);
4714 125 : BATcheck(b1, NULL);
4715 125 : BATcheck(c2, NULL);
4716 :
4717 125 : BATiter bi = bat_iterator(b);
4718 125 : BATiter b1i = bat_iterator(b1);
4719 125 : if (checkbats(&bi, &b1i, __func__) != GDK_SUCCEED) {
4720 0 : bat_iterator_end(&bi);
4721 0 : bat_iterator_end(&b1i);
4722 0 : return NULL;
4723 : }
4724 375 : if (b->ttype != TYPE_bit || ATOMtype(b1->ttype) != ATOMtype(c2->vtype)) {
4725 0 : bat_iterator_end(&bi);
4726 0 : bat_iterator_end(&b1i);
4727 0 : GDKerror("\"then\" and \"else\" BATs have different types.\n");
4728 0 : return NULL;
4729 : }
4730 24 : bn = BATcalcifthenelse_intern(&bi,
4731 125 : b1i.base, true, b1i.vh ? b1i.vh->base : NULL, b1i.width, b1i.nonil, b1->tseqbase,
4732 125 : VALptr(c2), false, NULL, 0, !VALisnil(c2), 0,
4733 125 : b1i.type);
4734 125 : bat_iterator_end(&bi);
4735 125 : bat_iterator_end(&b1i);
4736 :
4737 125 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",b1=" ALGOBATFMT
4738 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
4739 : ALGOBATPAR(b), ALGOBATPAR(b1),
4740 : ALGOOPTBATPAR(bn), GDKusec() - t0);
4741 :
4742 : return bn;
4743 : }
4744 :
4745 : BAT *
4746 2704 : BATcalcifthencstelse(BAT *b, const ValRecord *c1, BAT *b2)
4747 : {
4748 2704 : lng t0 = 0;
4749 2704 : BAT *bn;
4750 :
4751 2704 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
4752 :
4753 2704 : BATcheck(b, NULL);
4754 2704 : BATcheck(c1, NULL);
4755 2704 : BATcheck(b2, NULL);
4756 :
4757 2704 : BATiter bi = bat_iterator(b);
4758 2704 : BATiter b2i = bat_iterator(b2);
4759 2704 : if (checkbats(&bi, &b2i, __func__) != GDK_SUCCEED) {
4760 0 : bat_iterator_end(&bi);
4761 0 : bat_iterator_end(&b2i);
4762 0 : return NULL;
4763 : }
4764 8112 : if (b->ttype != TYPE_bit || ATOMtype(b2->ttype) != ATOMtype(c1->vtype)) {
4765 0 : bat_iterator_end(&bi);
4766 0 : bat_iterator_end(&b2i);
4767 0 : GDKerror("\"then\" and \"else\" BATs have different types.\n");
4768 0 : return NULL;
4769 : }
4770 49 : bn = BATcalcifthenelse_intern(&bi,
4771 2704 : VALptr(c1), false, NULL, 0, !VALisnil(c1), 0,
4772 2753 : b2i.base, true, b2i.vh ? b2i.vh->base : NULL, b2i.width, b2i.nonil, b2->tseqbase,
4773 2704 : c1->vtype);
4774 2704 : bat_iterator_end(&bi);
4775 2704 : bat_iterator_end(&b2i);
4776 :
4777 2704 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",b2=" ALGOBATFMT
4778 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
4779 : ALGOBATPAR(b), ALGOBATPAR(b2),
4780 : ALGOOPTBATPAR(bn), GDKusec() - t0);
4781 :
4782 : return bn;
4783 : }
4784 :
4785 : BAT *
4786 1307 : BATcalcifthencstelsecst(BAT *b, const ValRecord *c1, const ValRecord *c2)
4787 : {
4788 1307 : lng t0 = 0;
4789 1307 : BAT *bn;
4790 :
4791 1307 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
4792 :
4793 1307 : BATcheck(b, NULL);
4794 1307 : BATcheck(c1, NULL);
4795 1307 : BATcheck(c2, NULL);
4796 :
4797 3921 : if (b->ttype != TYPE_bit || ATOMtype(c1->vtype) != ATOMtype(c2->vtype)) {
4798 0 : GDKerror("\"then\" and \"else\" BATs have different types.\n");
4799 0 : return NULL;
4800 : }
4801 1307 : BATiter bi = bat_iterator(b);
4802 5226 : bn = BATcalcifthenelse_intern(&bi,
4803 1306 : VALptr(c1), false, NULL, 0, !VALisnil(c1), 0,
4804 1307 : VALptr(c2), false, NULL, 0, !VALisnil(c2), 0,
4805 1307 : c1->vtype);
4806 1306 : bat_iterator_end(&bi);
4807 :
4808 1307 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT
4809 : " -> " ALGOOPTBATFMT " " LLFMT "usec\n",
4810 : ALGOBATPAR(b),
4811 : ALGOOPTBATPAR(bn), GDKusec() - t0);
4812 :
4813 : return bn;
4814 : }
|