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 <klib/defs.h>
28 #include <klib/rc.h>
29 #include <vdb/xform.h>
30 #include <vdb/schema.h>
31 #include <bitstr.h>
32 #include <sysalloc.h>
33 
34 #include <stdint.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include <assert.h>
39 
40 typedef struct self_t {
41     void (*f)(const struct self_t *, void *, const void *, size_t);
42     uint32_t type_size;
43     uint32_t dim;
44     uint32_t n;
45     uint32_t idx[7];
46 } self_t;
47 
48 static
cut8(const struct self_t * self,void * Dst,const void * Src,size_t elem_count)49 void cut8(const struct self_t *self, void *Dst, const void *Src, size_t elem_count) {
50     uint8_t *dst = Dst;
51     const uint8_t *src = Src;
52     int i;
53     int j;
54     int doff;
55     int soff;
56 
57     for (doff = soff = i = 0; i != elem_count; ++i, doff += self->n, soff += self->dim) {
58         for (j = 0; j != self->n; ++j) {
59             dst[doff + j] = src[soff + self->idx[j]];
60         }
61     }
62 }
63 
64 static
cut16(const struct self_t * self,void * Dst,const void * Src,size_t elem_count)65 void cut16(const struct self_t *self, void *Dst, const void *Src, size_t elem_count) {
66     uint16_t *dst = Dst;
67     const uint16_t *src = Src;
68     int i;
69     int j;
70     int doff;
71     int soff;
72 
73     for (doff = soff = i = 0; i != elem_count; ++i, doff += self->n, soff += self->dim) {
74         for (j = 0; j != self->n; ++j) {
75             dst[doff + j] = src[soff + self->idx[j]];
76         }
77     }
78 }
79 
80 static
cut32(const struct self_t * self,void * Dst,const void * Src,size_t elem_count)81 void cut32(const struct self_t *self, void *Dst, const void *Src, size_t elem_count) {
82     uint32_t *dst = Dst;
83     const uint32_t *src = Src;
84     int i;
85     int j;
86     int doff;
87     int soff;
88 
89     for (doff = soff = i = 0; i != elem_count; ++i, doff += self->n, soff += self->dim) {
90         for (j = 0; j != self->n; ++j) {
91             dst[doff + j] = src[soff + self->idx[j]];
92         }
93     }
94 }
95 
96 static
cut64(const struct self_t * self,void * Dst,const void * Src,size_t elem_count)97 void cut64(const struct self_t *self, void *Dst, const void *Src, size_t elem_count) {
98     uint64_t *dst = Dst;
99     const uint64_t *src = Src;
100     int i;
101     int j;
102     int doff;
103     int soff;
104 
105     for (doff = soff = i = 0; i != elem_count; ++i, doff += self->n, soff += self->dim) {
106         for (j = 0; j != self->n; ++j) {
107             dst[doff + j] = src[soff + self->idx[j]];
108         }
109     }
110 }
111 
112 static
cut_bytes(const struct self_t * self,void * Dst,const void * Src,size_t elem_count)113 void cut_bytes(const struct self_t *self, void *Dst, const void *Src, size_t elem_count) {
114     uint8_t *dst = Dst;
115     const uint8_t *src = Src;
116     int i;
117     int j;
118     int doff;
119     int soff;
120     const int sz = self->type_size >> 3;
121     const int di = sz * self->n;
122     const int si = sz * self->dim;
123 
124     for (doff = soff = i = 0; i != elem_count; ++i, doff += di, soff += si) {
125         for (j = 0; j != self->n; ++j) {
126             memmove(dst + doff + j * sz, src + soff + self->idx[j] * sz, sz);
127         }
128     }
129 }
130 
131 static
cut_bits(const struct self_t * self,void * dst,const void * src,size_t elem_count)132 void cut_bits(const struct self_t *self, void *dst, const void *src, size_t elem_count) {
133     int i;
134     int j;
135     int doff;
136     int soff;
137     const int sz = self->type_size;
138     const int di = sz * self->n;
139     const int si = sz * self->dim;
140 
141     for (doff = soff = i = 0; i != elem_count; ++i, doff += di, soff += si) {
142         for (j = 0; j != self->n; ++j) {
143             bitcpy(dst, doff + j * sz, src, soff + self->idx[j] * sz, sz);
144         }
145     }
146 }
147 
148 static
cut_driver(void * Self,const VXformInfo * info,void * dst,const void * src,uint64_t elem_count)149 rc_t CC cut_driver (
150                     void *Self,
151                     const VXformInfo *info,
152                     void *dst,
153                     const void *src,
154                     uint64_t elem_count
155                     )
156 {
157     const self_t *self = Self;
158 
159     self->f( self, dst, src, elem_count );
160     return 0;
161 }
162 
163 static
vxf_cut_wrapper(void * ptr)164 void CC vxf_cut_wrapper( void *ptr )
165 {
166 	free( ptr );
167 }
168 
169 /* cut
170  * function < type T >
171  * T [ * ] cut #1.0 < U32 idx, ... > ( T [ * ] in );
172  */
173 VTRANSFACT_IMPL(vdb_cut, 1, 0, 0) (const void *self, const VXfactInfo *info, VFuncDesc *rslt, const VFactoryParams *cp, const VFunctionParams *dp )
174 {
175     uint32_t dim = cp->argc;
176     int i;
177     self_t *ctx;
178 
179     assert(dim != 0);
180     for (i = 0; i != dim; ++i) {
181         if (*(cp->argv[i].data.u32) >= dp->argv[0].fd.td.dim)
182             return RC(rcVDB, rcFunction, rcConstructing, rcParam, rcInvalid);
183     }
184 
185     ctx = malloc ( sizeof * ctx - sizeof ctx -> idx + dim * sizeof ctx -> idx [ 0 ] );
186     if (ctx == NULL)
187         return RC(rcVDB, rcFunction, rcConstructing, rcMemory, rcExhausted);
188 
189     ctx->type_size = VTypedescSizeof ( & info -> fdesc . desc ) / dim;
190     ctx->dim = VTypedescSizeof ( & dp->argv[0].desc ) / ctx->type_size;
191     ctx->n = dim;
192 
193     for (i = 0; i != dim; ++i)
194     {
195         ctx->idx[i] = cp->argv[i].data.u32[0];
196         if ( ctx->idx[i] >= ctx->dim )
197         {
198             free ( ctx );
199             return RC(rcVDB, rcFunction, rcConstructing, rcParam, rcInvalid);
200         }
201     }
202 
203     rslt->self = ctx;
204     rslt->whack = vxf_cut_wrapper;
205     rslt->variant = vftArray;
206     rslt->u.af = cut_driver;
207 
208     switch (ctx->type_size) {
209         case 8:
210             ctx->f = cut8;
211             break;
212         case 16:
213             ctx->f = cut16;
214             break;
215         case 32:
216             ctx->f = cut32;
217             break;
218         case 64:
219             ctx->f = cut64;
220             break;
221         default:
222             ctx->f = (ctx->type_size & 7) == 0 ? cut_bytes : cut_bits;
223             break;
224     }
225 
226 	return 0;
227 }
228