1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 *
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V.
7 */
8
9/* This file is included multiple times. We expect the tokens UI, UU, UO, US
10 * to be defined by the including file, and we expect that the
11 * combination (UI,UU,UO,US) is unique to each inclusion. */
12
13
14/* ! ENSURE THAT THESE LOCAL MACROS ARE UNDEFINED AT THE END OF THIS FILE ! */
15
16/* concatenate two, three or five tokens */
17#define U_CONCAT_2(a,b) a##b
18#define U_CONCAT_3(a,b,c) a##b##c
19#define U_CONCAT_5(a,b,c,d,e) a##b##c##d##e
20
21/* function names, *_nil & TYPE_* macros */
22#define UF(p,i,o,s) U_CONCAT_5(p,i,_,o,s)
23#define UN(t) U_CONCAT_2(t,_nil)
24#define UT(t) U_CONCAT_2(TYPE_,t)
25#define NL(t) U_CONCAT_3(is_,t,_nil)
26
27
28/* scalar fuse */
29
30/* fuse two (shift-byte) in values into one (2*shift-byte) out value */
31/* actual implementation */
32static char *
33UF(UDFfuse_,UI,UO,_) ( UO *ret , UI one , UI two )
34{
35 int shift = sizeof(UI) * 8;
36
37 /* assert calling sanity */
38 assert(ret != NULL);
39
40 if (NL(UI)(one) || NL(UI)(two))
41 /* NULL/nil in => NULL/nil out */
42 *ret = UN(UO);
43 else
44 /* do the work; watch out for sign bits */
45 *ret = ((UO) (UU) one << shift) | (UU) two;
46
47 return MAL_SUCCEED;
48}
49/* MAL wrapper */
50char *
51UF(UDFfuse_,UI,UO,) ( UO *ret , const UI *one , const UI *two )
52{
53 /* assert calling sanity */
54 assert(ret != NULL && one != NULL && two != NULL);
55
56 return UF(UDFfuse_,UI,UO,_) ( ret, *one, *two );
57}
58
59/* BAT fuse */
60/*
61 * TYPE-expanded optimized version,
62 * accessing value arrays directly.
63 */
64
65/* type-specific core algorithm on arrays */
66static char *
67UF(UDFarrayfuse_,UI,UO,) ( UO *res, const UI *one, const UI *two, BUN n )
68{
69 BUN i;
70 int shift = sizeof(UI) * 8;
71
72 /* assert calling sanity */
73 assert(res != NULL && one != NULL && two != NULL);
74
75 /* iterate over all values/tuples and do the work */
76 for (i = 0; i < n; i++)
77 if (NL(UI)(one[i]) || NL(UI)(two[i]))
78 /* NULL/nil in => NULL/nil out */
79 res[i] = UN(UO);
80 else
81 /* do the work; watch out for sign bits */
82 res[i] = ((UO) (UU) one[i] << shift) | (UU) two[i];
83
84 return MAL_SUCCEED;
85}
86
87/* type-specific core algorithm on BATs */
88static char *
89UF(UDFBATfuse_,UI,UO,) ( const BAT *bres, const BAT *bone, const BAT *btwo, BUN n,
90 bit *two_tail_sorted_unsigned,
91 bit *two_tail_revsorted_unsigned )
92{
93 UI *one = NULL, *two = NULL;
94 UO *res = NULL;
95 str msg = NULL;
96
97 /* assert calling sanity */
98 assert(bres != NULL && bone != NULL && btwo != NULL);
99 assert(BATcapacity(bres) >= n);
100 assert(BATcount(bone) >= n && BATcount(btwo) >= n);
101 assert(bone->ttype == UT(UI) && btwo->ttype == UT(UI));
102 assert(bres->ttype == UT(UO));
103
104 /* get direct access to the tail arrays */
105 one = (UI*) Tloc(bone, 0);
106 two = (UI*) Tloc(btwo, 0);
107 res = (UO*) Tloc(bres, 0);
108
109 /* call core function on arrays */
110 msg = UF(UDFarrayfuse_,UI,UO,) ( res, one, two , n );
111 if (msg != MAL_SUCCEED)
112 return msg;
113
114 *two_tail_sorted_unsigned =
115 BATtordered(btwo) && (two[0] >= 0 || two[n-1] < 0);
116 *two_tail_revsorted_unsigned =
117 BATtrevordered(btwo) && (two[0] < 0 || two[n-1] >= 0);
118
119 return MAL_SUCCEED;
120}
121
122
123/* undo local defines */
124#undef UT
125#undef UN
126#undef UF
127#undef NL
128#undef U_CONCAT_5
129#undef U_CONCAT_3
130#undef U_CONCAT_2
131