1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26 #include <vdb/extern.h>
27 #include <vdb/xform.h>
28 #include <arch-impl.h>
29 #include <klib/rc.h>
30 #include <sysalloc.h>
31
32 #include <stdlib.h>
33 #include <assert.h>
34 #include <string.h>
35
36 /* optional constant */
37 typedef union diff_data diff_data;
38 union diff_data
39 {
40 int8_t i8;
41 int16_t i16;
42 int32_t i32;
43 int64_t i64;
44
45 uint8_t u8;
46 uint16_t u16;
47 uint32_t u32;
48 uint64_t u64;
49
50 float f32;
51 double f64;
52 };
53
54 #define FULL_DIFF_NAME( T ) \
55 full_diff_ ## T
56 #define FULL_DIFF( T, k ) \
57 static \
58 rc_t CC FULL_DIFF_NAME ( T ) ( void *data, \
59 const VXformInfo *info, int64_t row_id, const VFixedRowResult *rslt, \
60 uint32_t argc, const VRowData argv [] ) \
61 { \
62 uint32_t i; \
63 const diff_data *self = ( const void* ) data; \
64 \
65 T *dst = rslt -> base; \
66 const T *a = argv [ 0 ] . u . data . base; \
67 const T *b = argv [ 1 ] . u . data . base; \
68 \
69 for ( i = 0, dst += rslt -> first_elem, \
70 a += argv [ 0 ] . u . data . first_elem, \
71 b += argv [ 1 ] . u . data . first_elem; \
72 i < rslt -> elem_count; ++ i ) \
73 { \
74 dst [ i ] = a [ i ] - b [ i ] - self -> k; \
75 } \
76 \
77 return 0; \
78 }
79
80 FULL_DIFF ( int8_t, i8 )
81 FULL_DIFF ( int16_t, i16 )
82 FULL_DIFF ( int32_t, i32 )
83 FULL_DIFF ( int64_t, i64 )
84 FULL_DIFF ( uint8_t, u8 )
85 FULL_DIFF ( uint16_t, u16 )
86 FULL_DIFF ( uint32_t, u32 )
87 FULL_DIFF ( uint64_t, u64 )
88 FULL_DIFF ( float, f32 )
89 FULL_DIFF ( double, f64 )
90
91 static VFixedRowFunc full_diff_func [] =
92 {
93 FULL_DIFF_NAME ( uint8_t ),
94 FULL_DIFF_NAME ( uint16_t ),
95 FULL_DIFF_NAME ( uint32_t ),
96 FULL_DIFF_NAME ( uint64_t ),
97 FULL_DIFF_NAME ( int8_t ),
98 FULL_DIFF_NAME ( int16_t ),
99 FULL_DIFF_NAME ( int32_t ),
100 FULL_DIFF_NAME ( int64_t ),
101 NULL,
102 NULL,
103 FULL_DIFF_NAME ( float ),
104 FULL_DIFF_NAME ( double )
105 };
106
107 #define CONST_DIFF_NAME( T ) \
108 const_diff_ ## T
109 #define CONST_DIFF( T, k ) \
110 static \
111 rc_t CC CONST_DIFF_NAME ( T ) ( void *data, const VXformInfo *info, \
112 void *rslt, const void *src, uint64_t elem_count ) \
113 { \
114 uint32_t i; \
115 const diff_data *self = ( const void* ) data; \
116 \
117 T *dst = rslt; \
118 const T *a = src; \
119 \
120 for ( i = 0; i < elem_count; ++ i ) \
121 { \
122 dst [ i ] = a [ i ] - self -> k; \
123 } \
124 \
125 return 0; \
126 }
127
128 CONST_DIFF ( int8_t, i8 )
129 CONST_DIFF ( int16_t, i16 )
130 CONST_DIFF ( int32_t, i32 )
131 CONST_DIFF ( int64_t, i64 )
132 CONST_DIFF ( uint8_t, u8 )
133 CONST_DIFF ( uint16_t, u16 )
134 CONST_DIFF ( uint32_t, u32 )
135 CONST_DIFF ( uint64_t, u64 )
136 CONST_DIFF ( float, f32 )
137 CONST_DIFF ( double, f64 )
138
139 static VArrayFunc const_diff_func [] =
140 {
141 CONST_DIFF_NAME ( uint8_t ),
142 CONST_DIFF_NAME ( uint16_t ),
143 CONST_DIFF_NAME ( uint32_t ),
144 CONST_DIFF_NAME ( uint64_t ),
145 CONST_DIFF_NAME ( int8_t ),
146 CONST_DIFF_NAME ( int16_t ),
147 CONST_DIFF_NAME ( int32_t ),
148 CONST_DIFF_NAME ( int64_t ),
149 NULL,
150 NULL,
151 CONST_DIFF_NAME ( float ),
152 CONST_DIFF_NAME ( double )
153 };
154
155 #define NO_CONST_NAME( T ) \
156 no_const_ ## T
157 #define NO_CONST( T ) \
158 static \
159 rc_t CC NO_CONST_NAME ( T ) ( void *data, \
160 const VXformInfo *info, int64_t row_id, const VFixedRowResult *rslt, \
161 uint32_t argc, const VRowData argv [] ) \
162 { \
163 uint32_t i; \
164 \
165 T *dst = rslt -> base; \
166 const T *a = argv [ 0 ] . u . data . base; \
167 const T *b = argv [ 1 ] . u . data . base; \
168 \
169 for ( i = 0, dst += rslt -> first_elem, \
170 a += argv [ 0 ] . u . data . first_elem, \
171 b += argv [ 1 ] . u . data . first_elem; \
172 i < rslt -> elem_count; ++ i ) \
173 { \
174 dst [ i ] = a [ i ] - b [ i ]; \
175 } \
176 \
177 return 0; \
178 }
179
180 NO_CONST ( int8_t )
181 NO_CONST ( int16_t )
182 NO_CONST ( int32_t )
183 NO_CONST ( int64_t )
184 NO_CONST ( uint8_t )
185 NO_CONST ( uint16_t )
186 NO_CONST ( uint32_t )
187 NO_CONST ( uint64_t )
188 NO_CONST ( float )
189 NO_CONST ( double )
190
191 static VFixedRowFunc no_const_func [] =
192 {
193 NO_CONST_NAME ( uint8_t ),
194 NO_CONST_NAME ( uint16_t ),
195 NO_CONST_NAME ( uint32_t ),
196 NO_CONST_NAME ( uint64_t ),
197 NO_CONST_NAME ( int8_t ),
198 NO_CONST_NAME ( int16_t ),
199 NO_CONST_NAME ( int32_t ),
200 NO_CONST_NAME ( int64_t ),
201 NULL,
202 NULL,
203 NO_CONST_NAME ( float ),
204 NO_CONST_NAME ( double )
205 };
206
207 static
no_diff(void * data,const VXformInfo * info,void * dst,const void * src,uint64_t elem_count)208 rc_t CC no_diff ( void *data, const VXformInfo *info,
209 void *dst, const void *src, uint64_t elem_count )
210 {
211 memmove ( dst, src, (size_t)elem_count * VTypedescSizeof ( & info -> fdesc . desc ) >> 3 );
212 return 0;
213 }
214
215 static
vxf_diff_wrapper(void * ptr)216 void CC vxf_diff_wrapper( void *ptr )
217 {
218 free( ptr );
219 }
220
221 /* diff
222 * return the difference of inputs
223 *
224 * "T" [ TYPE ] - input and output data type
225 * must be member of numeric_set
226 *
227 * "k" [ CONST, DEFAULT 0 ] - optional constant
228 * to be added or subtracted
229 *
230 * "a" [ DATA ] - left-most operand
231 *
232 * "b" [ DATA ] - optional subtractand
233 *
234 * SYNOPSIS:
235 * incorporates "k" into expression for every row
236 * returns sum or difference of inputs for all rows
237 *
238 * USAGE:
239 * length of half-closed interval
240 * U32 len = < U32 > diff ( stop, start );
241 * length of fully-closed interval
242 * U32 len = < U32 > diff < -1 > ( stop, start );
243 */
244 VTRANSFACT_IMPL ( vdb_diff, 1, 0, 0 ) ( const void *self, const VXfactInfo *info,
245 VFuncDesc *rslt, const VFactoryParams *cp, const VFunctionParams *dp )
246 {
247 bool has_const;
248 int32_t size_idx;
249 diff_data k;
250
251 /* "T" must be member of numeric_set */
252 switch ( info -> fdesc . desc . domain )
253 {
254 case vtdUint:
255 case vtdInt:
256 case vtdFloat:
257 break;
258 default:
259 return RC ( rcXF, rcFunction, rcConstructing, rcType, rcIncorrect );
260 }
261
262 /* TBD - eventually support vector differences
263 for today, check that dim of T is 1 */
264 if ( dp -> argv [ 0 ] . desc . intrinsic_dim != 1 )
265 return RC ( rcXF, rcFunction, rcConstructing, rcType, rcIncorrect );
266
267 /* the only numeric types we support are between 8 and 64 bits */
268 size_idx = uint32_lsbit ( dp -> argv [ 0 ] . desc . intrinsic_bits ) - 3;
269 if ( size_idx < 0 || size_idx > 3 || ( ( dp -> argv [ 0 ] . desc . intrinsic_bits &
270 ( dp -> argv [ 0 ] . desc . intrinsic_bits - 1 ) ) != 0 ) )
271 return RC ( rcXF, rcFunction, rcConstructing, rcType, rcIncorrect );
272
273
274 /* there are 4 variants:
275 1. no constant ( or is 0 ) and single input
276 2. non-zero constant and single input
277 3. no constant ( or is 0 ) and dual input
278 4. non-zero constant and dual input */
279 has_const = false;
280 if ( cp -> argc == 1 ) switch ( cp -> argv [ 0 ] . desc . domain )
281 {
282 case vtdUint:
283 case vtdInt:
284 switch ( cp -> argv [ 0 ] . desc . intrinsic_bits )
285 {
286 case 8:
287 if ( ( k . u8 = cp -> argv [ 0 ] . data . u8 [ 0 ] ) != 0 )
288 has_const = true;
289 break;
290 case 16:
291 if ( ( k . u16 = cp -> argv [ 0 ] . data . u16 [ 0 ] ) != 0 )
292 has_const = true;
293 break;
294 case 32:
295 if ( ( k . u32 = cp -> argv [ 0 ] . data . u32 [ 0 ] ) != 0 )
296 has_const = true;
297 break;
298 case 64:
299 if ( ( k . u64 = cp -> argv [ 0 ] . data . u64 [ 0 ] ) != 0 )
300 has_const = true;
301 break;
302 }
303 break;
304
305 case vtdFloat:
306 switch ( cp -> argv [ 0 ] . desc . intrinsic_bits )
307 {
308 case 32:
309 if ( ( k . f32 = cp -> argv [ 0 ] . data . f32 [ 0 ] ) != 0.0 )
310 has_const = true;
311 break;
312 case 64:
313 if ( ( k . f64 = cp -> argv [ 0 ] . data . f64 [ 0 ] ) != 0.0 )
314 has_const = true;
315 break;
316 }
317 break;
318 }
319
320 if ( has_const )
321 {
322 diff_data *pb = malloc ( sizeof * pb );
323 if ( pb == NULL )
324 return RC ( rcXF, rcFunction, rcConstructing, rcMemory, rcExhausted );
325 * pb = k;
326
327 rslt -> self = pb;
328 rslt -> whack = vxf_diff_wrapper;
329
330 if ( dp -> argc > 1 )
331 {
332 rslt -> u . pf = full_diff_func [ ( dp -> argv [ 0 ] . desc . domain - vtdUint ) * 4 + size_idx ];
333 rslt -> variant = vftFixedRow;
334 }
335 else
336 {
337 rslt -> u . af = const_diff_func [ ( dp -> argv [ 0 ] . desc . domain - vtdUint ) * 4 + size_idx ];
338 rslt -> variant = vftArray;
339 }
340 }
341 else
342 {
343 if ( dp -> argc > 1 )
344 {
345 rslt -> u . pf = no_const_func [ ( dp -> argv [ 0 ] . desc . domain - vtdUint ) * 4 + size_idx ];
346 rslt -> variant = vftFixedRow;
347 }
348 else
349 {
350 rslt -> u . af = no_diff;
351 rslt -> variant = vftArray;
352 }
353 }
354
355 return 0;
356 }
357