ae2f_docs
Conv.imp.c
Go to the documentation of this file.
1#include <ae2f/Cmp.h>
2#include <ae2f/Ann/Conv.h>
3
4#include <stdlib.h>
5#include <string.h>
6
7#define ae2f_AnnConv1dSz(in_f, in_g, pad, stride)
8 (((((pad << 1) + *ae2f_mMMapDimLen(in_f, const))
9 - *ae2f_mMMapDimLen(in_g, const))
10 / stride)
11 + 1)
12
13static size_t iter_indices(
14 size_t dim, size_t* indices, const size_t* max_indices) {
15 size_t i;
16 for (i = dim; i--;) {
17 indices[i]++;
18 if (indices[i] < max_indices[i]) {
19 return 1;
20 }
21 indices[i] = 0;
22 }
23 return 0;
24}
25
26static void get_conv_indices(
27 size_t dim,
28 const size_t* out_indices, const size_t* filter_indices,
29 const size_t* in_dims, const size_t* filter_dims,
30 const size_t* stride, const size_t* pad,
31 size_t* in_idx, size_t* filter_idx, size_t* out_idx,
32 int* is_padded) {
33 size_t in_stride = 1, filter_stride = 1, out_stride = 1;
34 size_t i;
35
36 *in_idx = *filter_idx = *out_idx = 0;
37 *is_padded = 0;
38
39 for (i = dim; i--;) {
40 assert(dim != i);
41
42 size_t cur_in_idx =
43 out_indices[i] * (stride ? stride[i] : 1) + filter_indices[i];
44 if (cur_in_idx < (pad ? pad[i] : 0) ||
45 cur_in_idx >= (in_dims[i] + (pad ? pad[i] : 0))) {
46 *is_padded = 1;
47 return;
48 }
49 cur_in_idx -= (pad ? pad[i] : 0);
50
51 *in_idx += cur_in_idx * in_stride;
52 *filter_idx += filter_indices[i] * filter_stride;
53 *out_idx += out_indices[i] * out_stride;
54
55 in_stride *= in_dims[i];
56 filter_stride *= filter_dims[i];
57 out_stride *=
58 ((in_dims[i] - filter_dims[i] + 2 * (pad ? pad[i] : 0)) /
59 (stride ? stride[i] : 1) +
60 1);
61 }
62}
63
64/**
65 * @brief
66 * all vectors are suggested initiated as 0.
67 * */
68 ae2f_SHAREDEXPORT ae2f_err_t
70 const ae2f_float_t* infv,
71 size_t infc,
72 const ae2f_float_t* ingv,
73 size_t ingc,
74 ae2f_float_t* outv,
75 size_t* opt_outc,
76 size_t stride,
77 size_t pad
78 )
79{
80 ae2f_err_t err = 0;
81 const size_t outc = ((infc - ingc + (pad << 1)) / (stride)) + 1;
82
83#define return(n) { err = n; goto _return; }
85 if(!outv) return(0);
86 if(outc <= pad << 1) return (ae2f_errGlob_OK);
87 size_t i, j;
88 for(i = 0; i < outc; i++)
89 {
90 ae2f_float_t sum = 0;
91 const size_t begi = i * stride;
92
93 for(j = 0; j < ingc; j++)
94 {
95 const size_t infi = begi + j;
96
97 /* If infv is padded so it went to zero. */
98 if(infi < pad || infi >= infc + pad) {
99 continue;
100 }
101
102 /* If one of them are zero for nullptr reason */
103 if(!(infv && ingv)) {
104 continue;
105 }
106
107 sum +=
108 infv[(infi - pad)] * ingv[j];
109 }
110
111 /**
112 * It adds the sum value, expecting that outv is initialised with 0,
113 * ...or it is called on loop and needs to added somehow.
114 * */
115 outv[i] += sum;
116 }
117_return:
118#undef return
119 if(opt_outc) *opt_outc = outc;
120 return err;
121}
122
123ae2f_extern ae2f_SHAREDEXPORT
125 const ae2f_float_t* inv,
126 const size_t inc,
127 ae2f_float_t* outv,
128 size_t* opt_outc,
129 const size_t window,
130 const size_t stride,
131 ae2f_eAnnCnnPool type
132 ) noexcept
133{
134 if(!stride) return ae2f_errGlob_WRONG_OPERATION;
135
136 /** @brief Calculation of out vector's size. */
137 size_t outc = 1 + ((inc - window) / stride), i, j;
138
139 if(inc < window)
141
142 if(opt_outc) {
143 *opt_outc = outc;
144 }
145
146 if(!inv) return ae2f_errGlob_PTR_IS_NULL;
147 if(!outv) return ae2f_errGlob_OK;
148 if(!stride) return ae2f_errGlob_WRONG_OPERATION;
149 if(!window) return ae2f_errGlob_OK;
150
151 for(i = 0; i < outc; i++)
152 {
153#define o (i * stride)
154 ae2f_float_t a = 0;
155
156 if(!(type & 0b10)) {
157 a = inv[o]; /** is not adding, comparing? */
158 }
159
160 if(type & 0b100) {
161 a = outv[i]; /** is outer thing */
162 }
163
164
165 for(j = 0; j < window; j++)
166 {
167 switch(type & 0b11)
168 {
171 a += inv[o + j];
172 break;
174 a = ae2f_CmpGetGt(a, inv[o + j]);
175 break;
176
178 a = ae2f_CmpGetLs(a, inv[o + j]);
179 break;
180 }
181#undef o
182 }
183
184 if(type == ae2f_eAnnCnnPool_AVG)
185 a /= window;
186
187 outv[i] = a;
188 }
189
190 return 0;
191}
192
193/**
194 * @brief
195 * `dim` must be the dimension of mmaps, lengths of lists.
196 * This function is meant to be recursive. For minimize the stack,
197 *
198 * @param infcc
199 * All elements in [infc] timed.
200 * If you set it to zero, it will calculate it for you.
201 *
202 * @param ingcc
203 * All elemtns in [ingc] timed.
204 * If you set it to zero, it will calculate it for you.
205 *
206 * @param outcc
207 * All elemtns in [outc] timed.
208 * You need to set it to zero. it will calculate it for you.
209 * */
210ae2f_SHAREDEXPORT ae2f_err_t ae2f_AnnCnnConv(
211 size_t dim,
212 const ae2f_float_t* infv,
213 const size_t* infc,
214 size_t infcc,
215 const ae2f_float_t* ingv,
216 const size_t* ingc,
217 size_t ingcc,
218 ae2f_float_t* outv,
219 size_t* outc_opt,
220 size_t outcc,
221 const size_t* stride_opt,
222 const size_t* pad_opt
223 )
224{
225 if (!outv || !infc || !ingc) return ae2f_errGlob_PTR_IS_NULL;
226 if (!dim) return ae2f_errGlob_IMP_NOT_FOUND;
227
228 size_t* out_dims = (size_t*)malloc(dim * sizeof(size_t));
229 size_t total_out_size = 1;
230
231 size_t i;
232 for (i = 0; i < dim; i++) {
233 out_dims[i] = ((infc[i] - ingc[i] + 2 * (pad_opt ? pad_opt[i] : 0)) /
234 (stride_opt ? stride_opt[i] : 1) +
235 1);
236 total_out_size *= out_dims[i];
237 if (outc_opt) outc_opt[i] = out_dims[i];
238 }
239
240 memset(outv, 0, total_out_size * sizeof(ae2f_float_t));
241
242 size_t* out_indices = (size_t*)calloc(dim, sizeof(size_t));
243 size_t* filter_indices = (size_t*)calloc(dim, sizeof(size_t));
244
245 do {
246 do {
247 size_t in_idx, filter_idx, out_idx;
248 int is_padded;
249 get_conv_indices(dim, out_indices, filter_indices, infc, ingc,
250 stride_opt, pad_opt, &in_idx, &filter_idx,
251 &out_idx, &is_padded);
252 if (!is_padded) {
253 outv[out_idx] += infv[in_idx] * ingv[filter_idx];
254 }
255 } while (iter_indices(dim, filter_indices, ingc));
256 } while (iter_indices(dim, out_indices, out_dims));
257
258 free(out_dims);
259 free(out_indices);
260 free(filter_indices);
261
262 return 0;
263}
264
265
266ae2f_extern ae2f_SHAREDEXPORT
268 size_t dim, const ae2f_float_t* inv, const size_t* inc, size_t incc,
269 ae2f_float_t* outv, size_t* opt_outc, size_t outcc,
270 const size_t* window_opt, const size_t* stride_opt, ae2f_eAnnCnnPool type) {
271 if (!inv || !inc) return ae2f_errGlob_PTR_IS_NULL;
272 if (!dim) return ae2f_errGlob_IMP_NOT_FOUND;
273
274 size_t* out_dims = (size_t*)malloc(dim * sizeof(size_t));
275 size_t total_out_size = 1;
276 size_t i;
277
278 for (i = 0; i < dim; i++) {
279 out_dims[i] =
280 (inc[i] - window_opt[i]) / (stride_opt ? stride_opt[i] : 1) + 1;
281 total_out_size *= out_dims[i];
282 if (opt_outc) opt_outc[i] = out_dims[i];
283 }
284
285 size_t* out_indices = (size_t*)calloc(dim, sizeof(size_t));
286 assert(out_indices);
287
288 do {
289 size_t out_idx = 0;
290 size_t out_stride = 1;
291
292 for (i = dim; i--; ) {
293
294
295 out_idx += out_indices[i] * out_stride;
296 out_stride *= out_dims[i];
297 }
298
299 ae2f_float_t res = 0;
300 switch (type & 0b11) {
302 res = -__FLT_MAX__;
303 break;
305 res = __FLT_MAX__;
306 break;
307 }
308
309 size_t* window_indices = (size_t*)calloc(dim, sizeof(size_t));
310 assert(window_indices);
311
312 do {
313 size_t in_idx = 0;
314 size_t in_stride = 1;
315
316 for (i = dim; i--; ) {
317 assert((((intptr_t)i) >= 0) && "Fishy index");
318 assert(i != dim);
319 in_idx += (out_indices[i] * (stride_opt ? stride_opt[i] : 1) +
320 window_indices[i]) *
321 in_stride;
322 in_stride *= inc[i];
323 }
324
325 switch (type & 0b11) {
328 res += inv[in_idx];
329 break;
331 if (inv[in_idx] > res) res = inv[in_idx];
332 break;
334 if (inv[in_idx] < res) res = inv[in_idx];
335 break;
336 }
337 } while (iter_indices(dim, window_indices, window_opt));
338
339 outv[out_idx] = res;
340 free(window_indices);
341 } while (iter_indices(dim, out_indices, out_dims));
342
343 free(out_dims);
344 free(out_indices);
345
346 return 0;
347}
348
349 ae2f_extern ae2f_SHAREDEXPORT ae2f_err_t
350ae2f_AnnCnnPool(size_t dim, const ae2f_float_t *inv, const size_t *inc,
351 size_t incc, ae2f_float_t *outv, size_t *opt_outc, size_t outcc,
352 const size_t *window_opt, size_t windowcc,
353 const size_t *stride_opt, ae2f_eAnnCnnPool type)
354{
356 dim
357 , inv, inc, incc
358 , outv, opt_outc, outcc
359 , window_opt, stride_opt
360 , type
361 );
362
363 size_t i, j;
364 if(!windowcc) {
365 windowcc = 1;
366 for(i = 0; i < dim; i++)
367 {
368 windowcc *= window_opt ? window_opt[i] : 1;
369 }
370 }
371
372 if(!outv) return ae2f_errGlob_OK;
373
374 if(ae2f_eAnnCnnPool_AVG == (type & 0b11))
375 for(i = 0; i < windowcc; i++)
376 {
377 outv[i] /= windowcc;
378 }
379
380 return e;
381}
#define ae2f_extern
Suggests the existence of external variable or function, in naming of C. [non-mangling].
Definition Cast.h:88
#define ae2f_CmpGetGt(a, b)
Definition Cmp.h:20
#define ae2f_CmpGetLs(a, b)
Definition Cmp.h:26
@ ae2f_eAnnCnnPool_MAX
Max.
Definition Conv.h:51
@ ae2f_eAnnCnnPool_MIN
Min.
Definition Conv.h:54
@ ae2f_eAnnCnnPool_ADD
Add.
Definition Conv.h:57
@ ae2f_eAnnCnnPool_AVG
Average.
Definition Conv.h:60
ae2f_extern ae2f_SHAREDEXPORT ae2f_err_t ae2f_AnnCnnPool1d(const ae2f_float_t *inv, const size_t inc, ae2f_float_t *outv, size_t *opt_outc, const size_t window, const size_t stride, ae2f_eAnnCnnPool type) noexcept
Definition Conv.imp.c:124
ae2f_extern ae2f_SHAREDEXPORT ae2f_err_t ae2f_AnnCnnPool_imp(size_t dim, const ae2f_float_t *inv, const size_t *inc, size_t incc, ae2f_float_t *outv, size_t *opt_outc, size_t outcc, const size_t *window_opt, const size_t *stride_opt, ae2f_eAnnCnnPool type)
Definition Conv.imp.c:267
ae2f_extern ae2f_SHAREDEXPORT ae2f_err_t ae2f_AnnCnnPool(size_t dim, const ae2f_float_t *inv, const size_t *inc, size_t incc, ae2f_float_t *outv, size_t *opt_outc, size_t outcc, const size_t *window_opt, size_t windowcc, const size_t *stride_opt, ae2f_eAnnCnnPool type)
Definition Conv.imp.c:350
ae2f_SHAREDEXPORT ae2f_err_t ae2f_AnnCnnConv1d(const ae2f_float_t *infv, size_t infc, const ae2f_float_t *ingv, size_t ingc, ae2f_float_t *outv, size_t *opt_outc, size_t stride, size_t pad)
all vectors are suggested initiated as 0.
Definition Conv.imp.c:69
ae2f_SHAREDEXPORT ae2f_err_t ae2f_AnnCnnConv(size_t dim, const ae2f_float_t *infv, const size_t *infc, size_t infcc, const ae2f_float_t *ingv, const size_t *ingc, size_t ingcc, ae2f_float_t *outv, size_t *outc_opt, size_t outcc, const size_t *stride_opt, const size_t *pad_opt)
dim must be the dimension of mmaps, lengths of lists. This function is meant to be recursive....
Definition Conv.imp.c:210
ae2f_float ae2f_float_t
Definition Float.h:38
#define ae2f_mMMapDimLen(mmap,...)
Length vector for every dimension index.
Definition MMap.auto.h:104
#define ae2f_errGlob_OK
The Operation you've wanted went successful.
Definition errGlob.h:23
#define ae2f_errGlob_WRONG_OPERATION
Found that parameter sent by programmer is invalid. The operation may have been ceased while the midd...
Definition errGlob.h:45
uint8_t ae2f_err_t
Informs that this number represents the error.
Definition errGlob.h:19
#define ae2f_errGlob_PTR_IS_NULL
Failed to refer the pointer either l-value inside the function.
Definition errGlob.h:32
#define ae2f_errGlob_IMP_NOT_FOUND
Failed to find the function on preprocessor which is callable for some reason No operation has beed d...
Definition errGlob.h:28