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