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