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