Bug Summary

File:nnc/ccv_cnnp_dataframe_addons.c
Warning:line 535, column 44
Division by zero

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ccv_cnnp_dataframe_addons.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model static -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -target-feature +sse2 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -resource-dir /usr/local/lib/clang/8.0.0 -I ../ -I /usr/local/cuda/include -D HAVE_CBLAS -D HAVE_LIBPNG -D HAVE_LIBJPEG -D HAVE_FFTW3 -D HAVE_PTHREAD -D HAVE_UCONTEXT -D HAVE_LIBLINEAR -D HAVE_TESSERACT -D HAVE_AVCODEC -D HAVE_AVFORMAT -D HAVE_AVUTIL -D HAVE_SWSCALE -D USE_DISPATCH -D HAVE_SSE2 -D HAVE_GSL -D HAVE_CUDA -D HAVE_CUDNN -D HAVE_NCCL -I /usr/local/include -internal-isystem /usr/local/include -internal-isystem /usr/local/lib/clang/8.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -fdebug-compilation-dir /home/liu/buildslave/linux-x64-runtests/build/lib/nnc -ferror-limit 19 -fmessage-length 0 -fblocks -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -o /home/liu/buildslave/public_html/analyze/2019-07-03-215927-77989-1 -x c ccv_cnnp_dataframe_addons.c -faddrsig

ccv_cnnp_dataframe_addons.c

1#include "ccv_nnc.h"
2#include "ccv_nnc_easy.h"
3#include "ccv_nnc_internal.h"
4#include "ccv_internal.h"
5#include "_ccv_cnnp_dataframe.h"
6
7#include <3rdparty/sfmt/SFMT.h>
8
9#pragma mark - Create Dataframe from Array
10
11static void _ccv_cnnp_array_enum(const int column_idx, const int* const row_idxs, const int row_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context)
12{
13 int i;
14 ccv_array_t* const array = (ccv_array_t*)context;
15 for (i = 0; i < row_size; i++)
16 data[i] = ccv_array_get(array, row_idxs[i])((void*)(((char*)((array)->data)) + (size_t)(array)->rsize
* (size_t)(row_idxs[i])))
;
17}
18
19ccv_cnnp_dataframe_t* ccv_cnnp_dataframe_from_array_new(ccv_array_t* const array)
20{
21 const ccv_cnnp_column_data_t array_column_data = {
22 .data_enum = _ccv_cnnp_array_enum,
23 .context = array
24 };
25 return ccv_cnnp_dataframe_new(&array_column_data, 1, array->rnum);
26}
27
28typedef struct {
29 ccv_cnnp_dataframe_tuple_t tuple;
30 int tensor_offset;
31 int device_id;
32} ccv_cnnp_copy_to_gpu_context_t;
33
34#pragma mark - Copy Tensors from CPU to GPU
35
36static void _ccv_cnnp_tensor_list_deinit(void* const data, void* const context)
37{
38 ccv_cnnp_dataframe_tuple_t* const tuple = (ccv_cnnp_dataframe_tuple_t*)context;
39 ccv_nnc_tensor_t** const tensor_list = (ccv_nnc_tensor_t**)data;
40 int i;
41 for (i = 0; i < tuple->size; i++)
42 if (tensor_list[i])
43 ccv_nnc_tensor_free(tensor_list[i]);
44 ccfreefree(tensor_list);
45}
46
47static void _ccv_cnnp_copy_to_gpu(void*** const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context)
48{
49 const ccv_cnnp_copy_to_gpu_context_t* const copy_to_gpu_context = (ccv_cnnp_copy_to_gpu_context_t*)context;
50 int i, j;
51 for (i = 0; i < batch_size; i++)
52 {
53 ccv_nnc_tensor_t** inputs = (ccv_nnc_tensor_t**)column_data[0][i] + copy_to_gpu_context->tensor_offset;
54 ccv_nnc_tensor_t** outputs = (ccv_nnc_tensor_t**)data[i];
55 if (!outputs)
56 {
57 outputs = (ccv_nnc_tensor_t**)(data[i] = ccmallocmalloc(sizeof(ccv_nnc_tensor_t*) * copy_to_gpu_context->tuple.size));
58 for (j = 0; j < copy_to_gpu_context->tuple.size; j++)
59 {
60 ccv_nnc_tensor_param_t params = inputs[j]->info;
61 params.type &= ~CCV_TENSOR_CPU_MEMORY;
62 params.type |= CCV_TENSOR_GPU_MEMORY; // Change to GPU memory.
63 CCV_TENSOR_SET_DEVICE_ID(params.type, copy_to_gpu_context->device_id)(params.type) = (((params.type) & ~0xfff00) | (((copy_to_gpu_context
->device_id) & 0xfff) << 8))
;
64 outputs[j] = ccv_nnc_tensor_new(0, params, 0);
65 }
66 }
67 for (j = 0; j < copy_to_gpu_context->tuple.size; j++)
68 ccv_nnc_tensor_pin_memory(inputs[j]);
69 ccv_nnc_cmd_exec(CMD_DATA_TRANSFER_FORWARD()ccv_nnc_cmd(CCV_NNC_DATA_TRANSFER_FORWARD, 0, ccv_nnc_cmd_auto
, 0)
, ccv_nnc_no_hint, 0, inputs, copy_to_gpu_context->tuple.size, outputs, copy_to_gpu_context->tuple.size, stream_context);
70 }
71}
72
73int ccv_cnnp_dataframe_copy_to_gpu(ccv_cnnp_dataframe_t* const dataframe, const int column_idx, const int tensor_offset, const int tensor_size, const int device_id)
74{
75 assert(tensor_size > 0)((void) sizeof ((tensor_size > 0) ? 1 : 0), __extension__ (
{ if (tensor_size > 0) ; else __assert_fail ("tensor_size > 0"
, "ccv_cnnp_dataframe_addons.c", 75, __extension__ __PRETTY_FUNCTION__
); }))
;
76 int stream_type = CCV_STREAM_CONTEXT_GPU;
77 CCV_STREAM_SET_DEVICE_ID(stream_type, device_id)(stream_type) = (((stream_type) & ~0xfff00) | (((device_id
) & 0xfff) << 8))
;
78 ccv_cnnp_copy_to_gpu_context_t* const copy_to_gpu_context = (ccv_cnnp_copy_to_gpu_context_t*)ccmallocmalloc(sizeof(ccv_cnnp_copy_to_gpu_context_t));
79 copy_to_gpu_context->tuple.size = tensor_size;
80 copy_to_gpu_context->tensor_offset = tensor_offset;
81 copy_to_gpu_context->device_id = device_id;
82 return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_copy_to_gpu, stream_type, _ccv_cnnp_tensor_list_deinit, COLUMN_ID_LIST(column_idx)(int []){column_idx}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
, copy_to_gpu_context, (ccv_cnnp_column_data_context_deinit_f)ccfreefree);
83}
84
85#pragma mark - Use Command to Generate Output Tuple
86
87typedef struct {
88 ccv_cnnp_dataframe_tuple_t tuple;
89 int input_offset;
90 int input_size;
91 ccv_nnc_cmd_t cmd;
92 ccv_nnc_hint_t hint;
93 int flags;
94 ccv_nnc_tensor_param_t output_params[1];
95} ccv_cnnp_cmd_exec_context_t;
96
97static void _ccv_cnnp_dataframe_cmd_exec(void*** const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context)
98{
99 const ccv_cnnp_cmd_exec_context_t* const cmd_exec_context = (ccv_cnnp_cmd_exec_context_t*)context;
100 int i, j;
101 for (i = 0; i < batch_size; i++)
102 {
103 ccv_nnc_tensor_t** inputs = (ccv_nnc_tensor_t**)column_data[0][i] + cmd_exec_context->input_offset;
104 ccv_nnc_tensor_t** outputs = (ccv_nnc_tensor_t**)data[i];
105 if (!outputs)
106 {
107 outputs = (ccv_nnc_tensor_t**)(data[i] = ccmallocmalloc(sizeof(ccv_nnc_tensor_t*) * cmd_exec_context->tuple.size));
108 for (j = 0; j < cmd_exec_context->tuple.size; j++)
109 outputs[j] = ccv_nnc_tensor_new(0, cmd_exec_context->output_params[j], 0);
110 }
111 ccv_nnc_cmd_exec(cmd_exec_context->cmd, cmd_exec_context->hint, cmd_exec_context->flags, inputs, cmd_exec_context->input_size, outputs, cmd_exec_context->tuple.size, stream_context);
112 }
113}
114
115int ccv_cnnp_dataframe_cmd_exec(ccv_cnnp_dataframe_t* const dataframe, const int column_idx, const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint, const int flags, const int input_offset, const int input_size, const ccv_nnc_tensor_param_t* const output_params, const int output_size, const int stream_type)
116{
117 assert(input_size > 0)((void) sizeof ((input_size > 0) ? 1 : 0), __extension__ (
{ if (input_size > 0) ; else __assert_fail ("input_size > 0"
, "ccv_cnnp_dataframe_addons.c", 117, __extension__ __PRETTY_FUNCTION__
); }))
;
118 assert(output_size > 0)((void) sizeof ((output_size > 0) ? 1 : 0), __extension__ (
{ if (output_size > 0) ; else __assert_fail ("output_size > 0"
, "ccv_cnnp_dataframe_addons.c", 118, __extension__ __PRETTY_FUNCTION__
); }))
;
119 ccv_cnnp_cmd_exec_context_t* const cmd_exec_context = (ccv_cnnp_cmd_exec_context_t*)ccmallocmalloc(sizeof(ccv_cnnp_cmd_exec_context_t) + sizeof(ccv_nnc_tensor_param_t) * (output_size - 1));
120 cmd_exec_context->tuple.size = output_size;
121 cmd_exec_context->input_offset = input_offset;
122 cmd_exec_context->input_size = input_size;
123 cmd_exec_context->cmd = cmd;
124 cmd_exec_context->hint = hint;
125 cmd_exec_context->flags = flags;
126 memcpy(cmd_exec_context->output_params, output_params, sizeof(ccv_nnc_tensor_param_t) * output_size);
127 return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_dataframe_cmd_exec, stream_type, _ccv_cnnp_tensor_list_deinit, COLUMN_ID_LIST(column_idx)(int []){column_idx}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
, cmd_exec_context, (ccv_cnnp_column_data_context_deinit_f)ccfreefree);
128 return 0;
129}
130
131#pragma mark - Make Auxiliary Tensor as a new Column
132
133static void _ccv_cnnp_tensor_deinit(void* const data, void* const context)
134{
135 ccv_nnc_tensor_free((ccv_nnc_tensor_t*)data);
136}
137
138static void _ccv_cnnp_tensor_new(const int column_idx, const int* const row_idxs, const int row_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context)
139{
140 ccv_nnc_tensor_param_t params = *(ccv_nnc_tensor_param_t*)context;
141 int i;
142 for (i = 0; i < row_size; i++)
143 if (!data[i])
144 data[i] = ccv_nnc_tensor_new(0, params, 0);
145}
146
147int ccv_cnnp_dataframe_add_aux(ccv_cnnp_dataframe_t* const dataframe, const ccv_nnc_tensor_param_t params)
148{
149 int stream_type = CCV_TENSOR_GET_MEMORY(params.type)((params.type) & 0x3) == CCV_TENSOR_CPU_MEMORY ? 0 : CCV_STREAM_CONTEXT_GPU;
150 if (stream_type == CCV_STREAM_CONTEXT_GPU)
151 CCV_STREAM_SET_DEVICE_ID(stream_type, CCV_TENSOR_GET_DEVICE_ID(params.type))(stream_type) = (((stream_type) & ~0xfff00) | ((((((params
.type) & 0xfff00) >> 8)) & 0xfff) << 8))
;
152 ccv_nnc_tensor_param_t* const context = (ccv_nnc_tensor_param_t*)ccmallocmalloc(sizeof(ccv_nnc_tensor_param_t));
153 context[0] = params;
154 return ccv_cnnp_dataframe_add(dataframe, _ccv_cnnp_tensor_new, stream_type, _ccv_cnnp_tensor_deinit, context, (ccv_cnnp_column_data_context_deinit_f)ccfreefree);
155}
156
157#pragma mark - Load Tensor from File Path
158
159static void _ccv_cnnp_image_deinit(void* const data, void* const context)
160{
161 ccv_matrix_free(data);
162}
163
164static void _ccv_cnnp_read_image(void*** const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context)
165{
166 parallel_for(i, batch_size){ int i; for ((i) = 0; (i) < (batch_size); (i)++) { {
167 if (data[i])
168 ccv_matrix_free(data[i]);
169 off_t structof = (off_t)context;
170 char* const filename = *(char**)((char*)column_data[0][i] + structof);
171 data[i] = 0;
172 ccv_read(filename, (ccv_dense_matrix_t**)&data[i], CCV_IO_ANY_FILE | CCV_IO_RGB_COLOR)ccv_read_impl(filename, (ccv_dense_matrix_t**)&data[i], CCV_IO_ANY_FILE
| CCV_IO_RGB_COLOR, 0, 0, 0)
;
173 } parallel_endfor} }
174}
175
176int ccv_cnnp_dataframe_read_image(ccv_cnnp_dataframe_t* const dataframe, const int column_idx, const off_t structof)
177{
178 return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_read_image, 0, _ccv_cnnp_image_deinit, COLUMN_ID_LIST(column_idx)(int []){column_idx}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
, (void*)(uintptr_t)structof, 0);
179}
180
181#pragma mark - Apply Random Jitter to Image
182
183typedef struct {
184 sfmt_t sfmt;
185 int datatype;
186 ccv_cnnp_random_jitter_t random_jitter;
187} ccv_cnnp_random_jitter_context_t;
188
189static void _ccv_cnnp_image_lighting(ccv_dense_matrix_t* image, const float alpha_r, const float alpha_g, const float alpha_b)
190{
191 assert(CCV_GET_DATA_TYPE(image->type) == CCV_32F)((void) sizeof ((((image->type) & 0xFF000) == CCV_32F)
? 1 : 0), __extension__ ({ if (((image->type) & 0xFF000
) == CCV_32F) ; else __assert_fail ("CCV_GET_DATA_TYPE(image->type) == CCV_32F"
, "ccv_cnnp_dataframe_addons.c", 191, __extension__ __PRETTY_FUNCTION__
); }))
;
192 assert(CCV_GET_CHANNEL(image->type) == CCV_C3)((void) sizeof ((((image->type) & 0xFFF) == CCV_C3) ? 1
: 0), __extension__ ({ if (((image->type) & 0xFFF) ==
CCV_C3) ; else __assert_fail ("CCV_GET_CHANNEL(image->type) == CCV_C3"
, "ccv_cnnp_dataframe_addons.c", 192, __extension__ __PRETTY_FUNCTION__
); }))
;
193 // These eigenvector values can be computed out of imageNet dataset (see ccv_convnet for how that is done). Here I just copied
194 // from mxnet: https://github.com/apache/incubator-mxnet/blob/master/src/operator/image/image_random-inl.h#L632
195 const float pca_r = alpha_r * (55.46 * -0.5675) + alpha_g * (4.794 * 0.7192) + alpha_b * (1.148 * 0.4009);
196 const float pca_g = alpha_r * (55.46 * -0.5808) + alpha_g * (4.794 * -0.0045) + alpha_b * (1.148 * -0.8140);
197 const float pca_b = alpha_r * (55.46 * -0.5836) + alpha_g * (4.794 * -0.6948) + alpha_b * (1.148 * 0.4203);
198 int i;
199 const int size = image->rows * image->cols;
200 float* const ptr = image->data.f32;
201 for (i = 0; i < size; i++)
202 {
203 ptr[i * 3] = ccv_clamp(ptr[i * 3] + pca_r, 0, 255)({ typeof (0) _a = (0); typeof (255) _b = (255); typeof (ptr[
i * 3] + pca_r) _x = (ptr[i * 3] + pca_r); (_x < _a) ? _a :
((_x > _b) ? _b : _x); })
;
204 ptr[i * 3 + 1] = ccv_clamp(ptr[i * 3 + 1] + pca_g, 0, 255)({ typeof (0) _a = (0); typeof (255) _b = (255); typeof (ptr[
i * 3 + 1] + pca_g) _x = (ptr[i * 3 + 1] + pca_g); (_x < _a
) ? _a : ((_x > _b) ? _b : _x); })
;
205 ptr[i * 3 + 2] = ccv_clamp(ptr[i * 3 + 2] + pca_b, 0, 255)({ typeof (0) _a = (0); typeof (255) _b = (255); typeof (ptr[
i * 3 + 2] + pca_b) _x = (ptr[i * 3 + 2] + pca_b); (_x < _a
) ? _a : ((_x > _b) ? _b : _x); })
;
206 }
207}
208
209static float _ccv_cnnp_random_logexp(sfmt_t* const sfmt, const float jitter)
210{
211 // We want to get something around logarithmic scale, thus, 0 is no good, and infinity is no good. 1 is the same.
212 // jitter is some turbulence we want around 1. We want the range range to be around [1 / (1 + jitter), 1 + jitter]
213 // but the distribution is not uniform (50% fall under 1, and 50% fall above 1). The way to do this is to first
214 // get to logarithmic range, doing a uniform sampling, and then convert back.
215 double log_jitter_limit = log(1 + jitter);
216 double log_random_jitter = sfmt_genrand_real1(sfmt) * 2 * log_jitter_limit - log_jitter_limit;
217 return (float)exp(log_random_jitter); // Convert it back to exponential form.
218}
219
220static void _ccv_cnnp_image_manip(ccv_dense_matrix_t* image, const ccv_cnnp_random_jitter_t random_jitter, sfmt_t* const sfmt)
221{
222 assert(sfmt && CCV_GET_CHANNEL(image->type) == CCV_C3)((void) sizeof ((sfmt && ((image->type) & 0xFFF
) == CCV_C3) ? 1 : 0), __extension__ ({ if (sfmt && (
(image->type) & 0xFFF) == CCV_C3) ; else __assert_fail
("sfmt && CCV_GET_CHANNEL(image->type) == CCV_C3"
, "ccv_cnnp_dataframe_addons.c", 222, __extension__ __PRETTY_FUNCTION__
); }))
;
223 int idx[4] = {0, 1, 2, 3};
224 sfmt_genrand_shuffle(sfmt, idx, 4, sizeof(int));
225 int i;
226 for (i = 0; i < 4; i++)
227 // change the applying order
228 switch (idx[i])
229 {
230 case 0:
231 if (random_jitter.brightness == 0)
232 break;
233 // introduce some brightness changes to the original image
234 ccv_scale(image, (ccv_matrix_t**)&image, 0, _ccv_cnnp_random_logexp(sfmt, random_jitter.brightness));
235 break;
236 case 1:
237 // introduce some saturation changes to the original image
238 if (random_jitter.saturation == 0)
239 break;
240 ccv_saturation(image, &image, 0, _ccv_cnnp_random_logexp(sfmt, random_jitter.saturation));
241 break;
242 case 2:
243 // introduce some contrast changes to the original image
244 if (random_jitter.contrast == 0)
245 break;
246 ccv_contrast(image, &image, 0, _ccv_cnnp_random_logexp(sfmt, random_jitter.contrast));
247 break;
248 case 3:
249 if (random_jitter.lighting == 0)
250 break;
251 _ccv_cnnp_image_lighting(image, sfmt_genrand_real1(sfmt) * random_jitter.lighting, sfmt_genrand_real1(sfmt) * random_jitter.lighting, sfmt_genrand_real1(sfmt) * random_jitter.lighting);
252 break;
253 }
254}
255
256static void _ccv_cnnp_normalize(ccv_dense_matrix_t* const image, const float mean[3], const float inv_std[3])
257{
258 int i;
259 const int count = image->rows * image->cols;
260 float* ap = image->data.f32;
261 for (i = 0; i < count; i++)
262 {
263 ap[i * 3] = (ap[i * 3] - mean[0]) * inv_std[0];
264 ap[i * 3 + 1] = (ap[i * 3 + 1] - mean[1]) * inv_std[1];
265 ap[i * 3 + 2] = (ap[i * 3 + 2] - mean[2]) * inv_std[2];
266 }
267}
268
269static void _ccv_cnnp_random_jitter(void*** const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context)
270{
271 sfmt_t* const sfmt = (sfmt_t*)alloca(sizeof(sfmt_t) * batch_size)__builtin_alloca (sizeof(sfmt_t) * batch_size);
272 ccv_cnnp_random_jitter_context_t* const ctx = (ccv_cnnp_random_jitter_context_t*)context;
273 int i;
274 for (i = 0; i < batch_size; i++)
275 sfmt_init_gen_rand(&sfmt[i], sfmt_genrand_uint32(&ctx->sfmt));
276 const ccv_cnnp_random_jitter_t random_jitter = ctx->random_jitter;
277 assert(random_jitter.resize.min > 0)((void) sizeof ((random_jitter.resize.min > 0) ? 1 : 0), __extension__
({ if (random_jitter.resize.min > 0) ; else __assert_fail
("random_jitter.resize.min > 0", "ccv_cnnp_dataframe_addons.c"
, 277, __extension__ __PRETTY_FUNCTION__); }))
;
278 assert(random_jitter.resize.max >= random_jitter.resize.min)((void) sizeof ((random_jitter.resize.max >= random_jitter
.resize.min) ? 1 : 0), __extension__ ({ if (random_jitter.resize
.max >= random_jitter.resize.min) ; else __assert_fail ("random_jitter.resize.max >= random_jitter.resize.min"
, "ccv_cnnp_dataframe_addons.c", 278, __extension__ __PRETTY_FUNCTION__
); }))
;
279 parallel_for(i, batch_size){ int i; for ((i) = 0; (i) < (batch_size); (i)++) { {
280 if (data[i])
281 ccv_matrix_free(data[i]);
282 ccv_dense_matrix_t* const input = (ccv_dense_matrix_t*)column_data[0][i];
283 const int resize = ccv_clamp((int)(sfmt_genrand_real1(&sfmt[i]) * (random_jitter.resize.max - random_jitter.resize.min) + 0.5) + random_jitter.resize.min, random_jitter.resize.min, random_jitter.resize.max)({ typeof (random_jitter.resize.min) _a = (random_jitter.resize
.min); typeof (random_jitter.resize.max) _b = (random_jitter.
resize.max); typeof ((int)(sfmt_genrand_real1(&sfmt[i]) *
(random_jitter.resize.max - random_jitter.resize.min) + 0.5)
+ random_jitter.resize.min) _x = ((int)(sfmt_genrand_real1(&
sfmt[i]) * (random_jitter.resize.max - random_jitter.resize.min
) + 0.5) + random_jitter.resize.min); (_x < _a) ? _a : ((_x
> _b) ? _b : _x); })
;
284 int resize_rows = ccv_max(resize, (int)(input->rows * (float)resize / input->cols + 0.5))({ typeof (resize) _a = (resize); typeof ((int)(input->rows
* (float)resize / input->cols + 0.5)) _b = ((int)(input->
rows * (float)resize / input->cols + 0.5)); (_a > _b) ?
_a : _b; })
;
285 int resize_cols = ccv_max(resize, (int)(input->cols * (float)resize / input->rows + 0.5))({ typeof (resize) _a = (resize); typeof ((int)(input->cols
* (float)resize / input->rows + 0.5)) _b = ((int)(input->
cols * (float)resize / input->rows + 0.5)); (_a > _b) ?
_a : _b; })
;
286 if (random_jitter.aspect_ratio > 0)
287 {
288 const float aspect_ratio = sqrtf(_ccv_cnnp_random_logexp(&sfmt[i], random_jitter.aspect_ratio));
289 resize_rows = (int)(resize_rows * aspect_ratio + 0.5);
290 resize_cols = (int)(resize_cols / aspect_ratio + 0.5);
291 }
292 const int need_crop = (random_jitter.size.cols > 0 && random_jitter.size.rows > 0 &&
293 ((resize_cols != random_jitter.size.cols || resize_rows != random_jitter.size.rows) ||
294 (random_jitter.offset.x != 0 || random_jitter.offset.y != 0)));
295 int cropped = 0, crop_x = 0, crop_y = 0;
296 ccv_dense_matrix_t* sliced = 0;
297 if (need_crop)
298 {
299 // Compute crop x, y.
300 crop_x = random_jitter.center_crop ?
301 (resize_cols - random_jitter.size.cols + 1) / 2 : // Otherwise, random select x.
302 (int)(sfmt_genrand_real1(&sfmt[i]) * (resize_cols - random_jitter.size.cols + 1));
303 crop_x = ccv_clamp(crop_x,({ typeof (({ typeof (0) _a = (0); typeof (resize_cols - random_jitter
.size.cols) _b = (resize_cols - random_jitter.size.cols); (_a
< _b) ? _a : _b; })) _a = (({ typeof (0) _a = (0); typeof
(resize_cols - random_jitter.size.cols) _b = (resize_cols - random_jitter
.size.cols); (_a < _b) ? _a : _b; })); typeof (({ typeof (
0) _a = (0); typeof (resize_cols - random_jitter.size.cols) _b
= (resize_cols - random_jitter.size.cols); (_a > _b) ? _a
: _b; })) _b = (({ typeof (0) _a = (0); typeof (resize_cols -
random_jitter.size.cols) _b = (resize_cols - random_jitter.size
.cols); (_a > _b) ? _a : _b; })); typeof (crop_x) _x = (crop_x
); (_x < _a) ? _a : ((_x > _b) ? _b : _x); })
304 ccv_min(0, resize_cols - random_jitter.size.cols),({ typeof (({ typeof (0) _a = (0); typeof (resize_cols - random_jitter
.size.cols) _b = (resize_cols - random_jitter.size.cols); (_a
< _b) ? _a : _b; })) _a = (({ typeof (0) _a = (0); typeof
(resize_cols - random_jitter.size.cols) _b = (resize_cols - random_jitter
.size.cols); (_a < _b) ? _a : _b; })); typeof (({ typeof (
0) _a = (0); typeof (resize_cols - random_jitter.size.cols) _b
= (resize_cols - random_jitter.size.cols); (_a > _b) ? _a
: _b; })) _b = (({ typeof (0) _a = (0); typeof (resize_cols -
random_jitter.size.cols) _b = (resize_cols - random_jitter.size
.cols); (_a > _b) ? _a : _b; })); typeof (crop_x) _x = (crop_x
); (_x < _a) ? _a : ((_x > _b) ? _b : _x); })
305 ccv_max(0, resize_cols - random_jitter.size.cols))({ typeof (({ typeof (0) _a = (0); typeof (resize_cols - random_jitter
.size.cols) _b = (resize_cols - random_jitter.size.cols); (_a
< _b) ? _a : _b; })) _a = (({ typeof (0) _a = (0); typeof
(resize_cols - random_jitter.size.cols) _b = (resize_cols - random_jitter
.size.cols); (_a < _b) ? _a : _b; })); typeof (({ typeof (
0) _a = (0); typeof (resize_cols - random_jitter.size.cols) _b
= (resize_cols - random_jitter.size.cols); (_a > _b) ? _a
: _b; })) _b = (({ typeof (0) _a = (0); typeof (resize_cols -
random_jitter.size.cols) _b = (resize_cols - random_jitter.size
.cols); (_a > _b) ? _a : _b; })); typeof (crop_x) _x = (crop_x
); (_x < _a) ? _a : ((_x > _b) ? _b : _x); })
;
306 crop_y = random_jitter.center_crop ?
307 (resize_rows - random_jitter.size.rows + 1) / 2 : // Otherwise, random select y.
308 (int)(sfmt_genrand_real1(&sfmt[i]) * (resize_rows - random_jitter.size.rows + 1));
309 crop_y = ccv_clamp(crop_y,({ typeof (({ typeof (0) _a = (0); typeof (resize_rows - random_jitter
.size.rows) _b = (resize_rows - random_jitter.size.rows); (_a
< _b) ? _a : _b; })) _a = (({ typeof (0) _a = (0); typeof
(resize_rows - random_jitter.size.rows) _b = (resize_rows - random_jitter
.size.rows); (_a < _b) ? _a : _b; })); typeof (({ typeof (
0) _a = (0); typeof (resize_rows - random_jitter.size.rows) _b
= (resize_rows - random_jitter.size.rows); (_a > _b) ? _a
: _b; })) _b = (({ typeof (0) _a = (0); typeof (resize_rows -
random_jitter.size.rows) _b = (resize_rows - random_jitter.size
.rows); (_a > _b) ? _a : _b; })); typeof (crop_y) _x = (crop_y
); (_x < _a) ? _a : ((_x > _b) ? _b : _x); })
310 ccv_min(0, resize_rows - random_jitter.size.rows),({ typeof (({ typeof (0) _a = (0); typeof (resize_rows - random_jitter
.size.rows) _b = (resize_rows - random_jitter.size.rows); (_a
< _b) ? _a : _b; })) _a = (({ typeof (0) _a = (0); typeof
(resize_rows - random_jitter.size.rows) _b = (resize_rows - random_jitter
.size.rows); (_a < _b) ? _a : _b; })); typeof (({ typeof (
0) _a = (0); typeof (resize_rows - random_jitter.size.rows) _b
= (resize_rows - random_jitter.size.rows); (_a > _b) ? _a
: _b; })) _b = (({ typeof (0) _a = (0); typeof (resize_rows -
random_jitter.size.rows) _b = (resize_rows - random_jitter.size
.rows); (_a > _b) ? _a : _b; })); typeof (crop_y) _x = (crop_y
); (_x < _a) ? _a : ((_x > _b) ? _b : _x); })
311 ccv_max(0, resize_rows - random_jitter.size.rows))({ typeof (({ typeof (0) _a = (0); typeof (resize_rows - random_jitter
.size.rows) _b = (resize_rows - random_jitter.size.rows); (_a
< _b) ? _a : _b; })) _a = (({ typeof (0) _a = (0); typeof
(resize_rows - random_jitter.size.rows) _b = (resize_rows - random_jitter
.size.rows); (_a < _b) ? _a : _b; })); typeof (({ typeof (
0) _a = (0); typeof (resize_rows - random_jitter.size.rows) _b
= (resize_rows - random_jitter.size.rows); (_a > _b) ? _a
: _b; })) _b = (({ typeof (0) _a = (0); typeof (resize_rows -
random_jitter.size.rows) _b = (resize_rows - random_jitter.size
.rows); (_a > _b) ? _a : _b; })); typeof (crop_y) _x = (crop_y
); (_x < _a) ? _a : ((_x > _b) ? _b : _x); })
;
312 if (random_jitter.offset.x != 0)
313 crop_x += sfmt_genrand_real1(&sfmt[i]) * random_jitter.offset.x * 2 - random_jitter.offset.x;
314 if (random_jitter.offset.y != 0)
315 crop_y += sfmt_genrand_real1(&sfmt[i]) * random_jitter.offset.y * 2 - random_jitter.offset.y;
316 // If we can fill in the whole view (not introducing any 0 padding), we can first crop and then scale down / up.
317 if (resize_cols >= random_jitter.size.cols && resize_rows >= random_jitter.size.rows)
318 {
319 const float scale_x = (float)input->cols / resize_cols;
320 const float scale_y = (float)input->rows / resize_rows;
321 const int slice_cols = (int)(random_jitter.size.cols * scale_x + 0.5);
322 const int slice_rows = (int)(random_jitter.size.rows * scale_y + 0.5);
323 assert(slice_cols <= input->cols)((void) sizeof ((slice_cols <= input->cols) ? 1 : 0), __extension__
({ if (slice_cols <= input->cols) ; else __assert_fail
("slice_cols <= input->cols", "ccv_cnnp_dataframe_addons.c"
, 323, __extension__ __PRETTY_FUNCTION__); }))
;
324 assert(slice_rows <= input->rows)((void) sizeof ((slice_rows <= input->rows) ? 1 : 0), __extension__
({ if (slice_rows <= input->rows) ; else __assert_fail
("slice_rows <= input->rows", "ccv_cnnp_dataframe_addons.c"
, 324, __extension__ __PRETTY_FUNCTION__); }))
;
325 const int x = ccv_clamp((int)(crop_x * scale_x + 0.5), 0, input->cols - slice_cols)({ typeof (0) _a = (0); typeof (input->cols - slice_cols) _b
= (input->cols - slice_cols); typeof ((int)(crop_x * scale_x
+ 0.5)) _x = ((int)(crop_x * scale_x + 0.5)); (_x < _a) ?
_a : ((_x > _b) ? _b : _x); })
;
326 const int y = ccv_clamp((int)(crop_y * scale_y + 0.5), 0, input->rows - slice_rows)({ typeof (0) _a = (0); typeof (input->rows - slice_rows) _b
= (input->rows - slice_rows); typeof ((int)(crop_y * scale_y
+ 0.5)) _x = ((int)(crop_y * scale_y + 0.5)); (_x < _a) ?
_a : ((_x > _b) ? _b : _x); })
;
327 ccv_slice(input, (ccv_matrix_t**)&sliced, 0, y, x, slice_rows, slice_cols);
328 resize_cols = random_jitter.size.cols;
329 resize_rows = random_jitter.size.rows;
330 cropped = 1;
331 } else
332 sliced = input;
333 } else
334 sliced = input;
335 ccv_dense_matrix_t* resized = 0;
336 // Resize.
337 if (sliced->rows >= resize_rows && sliced->cols >= resize_cols)
338 {
339 // If we can fill in the whole view, we can first crop and then scale down / up.
340 ccv_resample(sliced, &resized, CCV_32F, resize_rows, resize_cols, CCV_INTER_AREA);
341 } else if (sliced->rows != resize_rows || sliced->cols != resize_cols) {
342 ccv_resample(sliced, &resized, CCV_32F, resize_rows, resize_cols, CCV_INTER_CUBIC);
343 } else {
344 ccv_shift(sliced, (ccv_matrix_t**)&resized, CCV_32F, 0, 0); // converting to 32f
345 }
346 if (sliced != input)
347 ccv_matrix_free(sliced);
348 if (random_jitter.symmetric && (sfmt_genrand_uint32(&sfmt[i]) & 1) == 0)
349 ccv_flip(resized, &resized, 0, CCV_FLIP_X);
350 _ccv_cnnp_image_manip(resized, random_jitter, &sfmt[i]);
351 // Apply normalization. Slice will introduce 0 padding, which won't be correct before normalization.
352 if (random_jitter.normalize.mean[0] != 0 || random_jitter.normalize.std[0] != 1 ||
353 random_jitter.normalize.mean[1] != 0 || random_jitter.normalize.std[1] != 1 ||
354 random_jitter.normalize.mean[2] != 0 || random_jitter.normalize.std[2] != 1)
355 _ccv_cnnp_normalize(resized, random_jitter.normalize.mean, random_jitter.normalize.std);
356 // If we haven't cropped in previous step (likely because we have some fill-ins due to the resize down too much).
357 // Do the crop now.
358 ccv_dense_matrix_t* patch = 0;
359 if (!cropped && need_crop)
360 {
361 ccv_slice(resized, (ccv_matrix_t**)&patch, CCV_32F, crop_y, crop_x, random_jitter.size.rows, random_jitter.size.cols);
362 ccv_matrix_free(resized);
363 } else
364 patch = resized;
365 assert(!ccv_any_nan(patch))((void) sizeof ((!ccv_any_nan(patch)) ? 1 : 0), __extension__
({ if (!ccv_any_nan(patch)) ; else __assert_fail ("!ccv_any_nan(patch)"
, "ccv_cnnp_dataframe_addons.c", 365, __extension__ __PRETTY_FUNCTION__
); }))
;
366 data[i] = patch;
367 } parallel_endfor} }
368}
369
370int ccv_cnnp_dataframe_image_random_jitter(ccv_cnnp_dataframe_t* const dataframe, const int column_idx, const int datatype, const ccv_cnnp_random_jitter_t random_jitter)
371{
372 assert(datatype == CCV_32F)((void) sizeof ((datatype == CCV_32F) ? 1 : 0), __extension__
({ if (datatype == CCV_32F) ; else __assert_fail ("datatype == CCV_32F"
, "ccv_cnnp_dataframe_addons.c", 372, __extension__ __PRETTY_FUNCTION__
); }))
;
373 ccv_cnnp_random_jitter_context_t* const random_jitter_context = (ccv_cnnp_random_jitter_context_t*)ccmallocmalloc(sizeof(ccv_cnnp_random_jitter_context_t));
374 if (random_jitter.seed)
375 sfmt_init_gen_rand(&random_jitter_context->sfmt, (uint32_t)random_jitter.seed);
376 else
377 sfmt_init_gen_rand(&random_jitter_context->sfmt, (uint32_t)(uintptr_t)dataframe);
378 random_jitter_context->datatype = datatype;
379 random_jitter_context->random_jitter = random_jitter;
380 int i;
381 // The std in the random jitter should be inv_std.
382 for (i = 0; i < 3; i++)
383 random_jitter_context->random_jitter.normalize.std[i] = random_jitter_context->random_jitter.normalize.std[i] ? 1. / random_jitter_context->random_jitter.normalize.std[i] : 1;
384 return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_random_jitter, 0, _ccv_cnnp_image_deinit, COLUMN_ID_LIST(column_idx)(int []){column_idx}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
, random_jitter_context, (ccv_cnnp_column_data_context_deinit_f)ccfreefree);
385}
386
387typedef struct {
388 int range;
389 int datatype;
390 int format;
391 float onval;
392 float offval;
393 off_t structof;
394} ccv_cnnp_one_hot_context_t;
395
396static void _ccv_cnnp_one_hot(void*** const column_data, const int column_size, const int batch_size, void** const data, void* const context, ccv_nnc_stream_context_t* const stream_context)
397{
398 ccv_cnnp_one_hot_context_t* const one_hot = (ccv_cnnp_one_hot_context_t*)context;
399 ccv_nnc_tensor_param_t params = {
400 .datatype = one_hot->datatype,
401 .type = CCV_TENSOR_CPU_MEMORY,
402 .format = one_hot->format,
403 .dim = {
404 one_hot->range,
405 },
406 };
407 parallel_for(i, batch_size){ int i; for ((i) = 0; (i) < (batch_size); (i)++) { {
408 int j;
409 const int label = *(int*)((char*)column_data[0][i] + one_hot->structof);
410 if (!data[i])
411 data[i] = ccv_nnc_tensor_new(0, params, 0);
412 ccv_nnc_tensor_t* const tensor = (ccv_nnc_tensor_t*)data[i];
413 assert(label >= 0 && label < one_hot->range)((void) sizeof ((label >= 0 && label < one_hot->
range) ? 1 : 0), __extension__ ({ if (label >= 0 &&
label < one_hot->range) ; else __assert_fail ("label >= 0 && label < one_hot->range"
, "ccv_cnnp_dataframe_addons.c", 413, __extension__ __PRETTY_FUNCTION__
); }))
;
414 if (tensor->info.datatype == CCV_32F)
415 for (j = 0; j < one_hot->range; j++)
416 tensor->data.f32[j] = (j == label) ? one_hot->onval : one_hot->offval;
417 else if (tensor->info.datatype == CCV_16F)
418 for (j = 0; j < one_hot->range; j++)
419 ccv_float_to_half_precision((j == label) ? &one_hot->onval : &one_hot->offval, (uint16_t*)(tensor->data.f16 + j), 1);
420 else
421 { assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_cnnp_dataframe_addons.c", 421, __extension__ __PRETTY_FUNCTION__
); }))
; }
422 } parallel_endfor} }
423}
424
425int ccv_cnnp_dataframe_one_hot(ccv_cnnp_dataframe_t* const dataframe, const int column_idx, const off_t structof, const int range, const float onval, const float offval, const int datatype, const int format)
426{
427 assert(datatype == CCV_32F || datatype == CCV_16F)((void) sizeof ((datatype == CCV_32F || datatype == CCV_16F) ?
1 : 0), __extension__ ({ if (datatype == CCV_32F || datatype
== CCV_16F) ; else __assert_fail ("datatype == CCV_32F || datatype == CCV_16F"
, "ccv_cnnp_dataframe_addons.c", 427, __extension__ __PRETTY_FUNCTION__
); }))
;
428 ccv_cnnp_one_hot_context_t* const one_hot = (ccv_cnnp_one_hot_context_t*)ccmallocmalloc(sizeof(ccv_cnnp_one_hot_context_t));
429 one_hot->range = range;
430 one_hot->datatype = datatype;
431 one_hot->format = format;
432 one_hot->onval = onval;
433 one_hot->offval = offval;
434 one_hot->structof = structof;
435 return ccv_cnnp_dataframe_map(dataframe, _ccv_cnnp_one_hot, 0, _ccv_cnnp_tensor_deinit, COLUMN_ID_LIST(column_idx)(int []){column_idx}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
, one_hot, (ccv_cnnp_column_data_context_deinit_f)ccfreefree);
436}
437
438typedef struct {
439 ccv_cnnp_dataframe_tuple_t tuple;
440 int format;
441 int batch_count;
442 int group_count;
443} ccv_cnnp_batch_context_t;
444
445static void _ccv_cnnp_batching_new(void** const input_data, const int input_size, void** const output_data, void* const context, ccv_nnc_stream_context_t* const stream_context)
446{
447 ccv_cnnp_batch_context_t* const batch = (ccv_cnnp_batch_context_t*)context;
448 const int output_tuple_size = batch->tuple.size;
449 const int batch_count = batch->batch_count;
450 const int group_count = batch->group_count;
451 const int input_tuple_size = output_tuple_size / group_count;
452 int i, j, k;
453 assert(input_size > 0)((void) sizeof ((input_size > 0) ? 1 : 0), __extension__ (
{ if (input_size > 0) ; else __assert_fail ("input_size > 0"
, "ccv_cnnp_dataframe_addons.c", 453, __extension__ __PRETTY_FUNCTION__
); }))
;
1
Assuming 'input_size' is > 0
2
Taking true branch
454 if (!output_data[0])
3
Assuming the condition is false
4
Taking false branch
455 {
456 ccv_nnc_tensor_t** const inputs = (ccv_nnc_tensor_t**)input_data[0];
457 ccv_nnc_tensor_t** const tensors = (ccv_nnc_tensor_t**)(output_data[0] = ccmallocmalloc(sizeof(ccv_nnc_tensor_t*) * output_tuple_size));
458 for (i = 0; i < group_count; i++)
459 for (j = 0; j < input_tuple_size; j++)
460 {
461 ccv_nnc_tensor_param_t params = inputs[j]->info;
462 assert(params.datatype == CCV_32F || params.datatype == CCV_16F)((void) sizeof ((params.datatype == CCV_32F || params.datatype
== CCV_16F) ? 1 : 0), __extension__ ({ if (params.datatype ==
CCV_32F || params.datatype == CCV_16F) ; else __assert_fail (
"params.datatype == CCV_32F || params.datatype == CCV_16F", "ccv_cnnp_dataframe_addons.c"
, 462, __extension__ __PRETTY_FUNCTION__); }))
; // Only support 32 bit float yet.
463 assert(params.format == CCV_TENSOR_FORMAT_NHWC || params.format == CCV_TENSOR_FORMAT_NCHW)((void) sizeof ((params.format == CCV_TENSOR_FORMAT_NHWC || params
.format == CCV_TENSOR_FORMAT_NCHW) ? 1 : 0), __extension__ ({
if (params.format == CCV_TENSOR_FORMAT_NHWC || params.format
== CCV_TENSOR_FORMAT_NCHW) ; else __assert_fail ("params.format == CCV_TENSOR_FORMAT_NHWC || params.format == CCV_TENSOR_FORMAT_NCHW"
, "ccv_cnnp_dataframe_addons.c", 463, __extension__ __PRETTY_FUNCTION__
); }))
;
464 params.format = batch->format;
465 // Special-case for dim count is 3 and 1, in these two cases, the N is not provided.
466 if (batch->format == inputs[j]->info.format)
467 {
468 const int nd = ccv_nnc_tensor_nd(params.dim);
469 if (nd == 3 || nd == 1)
470 {
471 memset(params.dim, 0, sizeof(int) * CCV_NNC_MAX_DIM_ALLOC(8));
472 memcpy(params.dim + 1, inputs[j]->info.dim, sizeof(int) * nd);
473 }
474 } else {
475 const int nd = ccv_nnc_tensor_nd(params.dim);
476 if (nd == 1)
477 {
478 memset(params.dim, 0, sizeof(int) * CCV_NNC_MAX_DIM_ALLOC(8));
479 memcpy(params.dim + 1, inputs[j]->info.dim, sizeof(int) * nd);
480 } else if (nd >= 3) {
481 memset(params.dim, 0, sizeof(int) * CCV_NNC_MAX_DIM_ALLOC(8));
482 const int hw = ccv_nnc_tensor_hw(inputs[j]->info, nd);
483 if (batch->format == CCV_TENSOR_FORMAT_NCHW)
484 {
485 params.dim[1] = ccv_nnc_tensor_get_c(inputs[j]->info);
486 for (k = 0; k < CCV_NNC_MAX_DIM(2); k++)
487 params.dim[k + 2] = inputs[j]->info.dim[k + hw];
488 } else {
489 params.dim[CCV_NNC_MAX_DIM(2) + 1] = ccv_nnc_tensor_get_c(inputs[j]->info);
490 for (k = 0; k < CCV_NNC_MAX_DIM(2); k++)
491 params.dim[k + 1] = inputs[j]->info.dim[k + hw];
492 }
493 }
494 }
495 params.dim[0] = batch_count; // Set the batch count now.
496 tensors[i * input_tuple_size + j] = ccv_nnc_tensor_new(0, params, 0);
497 }
498 }
499 for (i = 0; i < group_count; i++)
5
Assuming 'i' is < 'group_count'
6
Loop condition is true. Entering loop body
500 for (j = 0; j < input_tuple_size; j++)
7
Assuming 'j' is < 'input_tuple_size'
8
Loop condition is true. Entering loop body
501 {
502 ccv_nnc_tensor_t* const output = ((ccv_nnc_tensor_t**)output_data[0])[i * input_tuple_size + j];
503 parallel_for(k, batch_count){ int k; for ((k) = 0; (k) < (batch_count); (k)++) { {
9
Assuming 'k' is < 'batch_count'
10
Loop condition is true. Entering loop body
504 ccv_nnc_tensor_t* const input = ((ccv_nnc_tensor_t**)input_data[(k + i * batch_count) % input_size])[j];
505 const size_t tensor_count = ccv_nnc_tensor_count(input->info);
506 if (input->info.datatype == CCV_32F)
11
Assuming the condition is false
12
Taking false branch
507 {
508 float* const ap = input->data.f32;
509 float* const bp = output->data.f32 + k * tensor_count;
510 if (input->info.format == output->info.format)
511 memcpy(bp, ap, sizeof(float) * tensor_count);
512 else {
513 // Do a simple format conversion.
514 const int c = ccv_nnc_tensor_get_c(input->info);
515 const size_t hw_count = tensor_count / c;
516 size_t x;
517 int y;
518 if (input->info.format == CCV_TENSOR_FORMAT_NHWC && output->info.format == CCV_TENSOR_FORMAT_NCHW)
519 for (x = 0; x < hw_count; x++)
520 for (y = 0; y < c; y++)
521 bp[y * hw_count + x] = ap[x * c + y];
522 else if (input->info.format == CCV_TENSOR_FORMAT_NCHW && output->info.format == CCV_TENSOR_FORMAT_NHWC)
523 for (x = 0; x < hw_count; x++)
524 for (y = 0; y < c; y++)
525 bp[x * c + y] = ap[y * hw_count + x];
526 }
527 } else if (input->info.datatype == CCV_16F) {
13
Assuming the condition is true
14
Taking true branch
528 ccv_float16_t* const ap = input->data.f16;
529 ccv_float16_t* const bp = output->data.f16 + k * tensor_count;
530 if (input->info.format == output->info.format)
15
Assuming the condition is false
16
Taking false branch
531 memcpy(bp, ap, sizeof(ccv_float16_t) * tensor_count);
532 else {
533 // Do a simple format conversion.
534 const int c = ccv_nnc_tensor_get_c(input->info);
17
Calling 'ccv_nnc_tensor_get_c'
20
Returning from 'ccv_nnc_tensor_get_c'
21
'c' initialized to 0
535 const size_t hw_count = tensor_count / c;
22
Division by zero
536 size_t x;
537 int y;
538 if (input->info.format == CCV_TENSOR_FORMAT_NHWC && output->info.format == CCV_TENSOR_FORMAT_NCHW)
539 for (x = 0; x < hw_count; x++)
540 for (y = 0; y < c; y++)
541 bp[y * hw_count + x] = ap[x * c + y];
542 else if (input->info.format == CCV_TENSOR_FORMAT_NCHW && output->info.format == CCV_TENSOR_FORMAT_NHWC)
543 for (x = 0; x < hw_count; x++)
544 for (y = 0; y < c; y++)
545 bp[x * c + y] = ap[y * hw_count + x];
546 }
547 } else {
548 assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_cnnp_dataframe_addons.c", 548, __extension__ __PRETTY_FUNCTION__
); }))
;
549 }
550 } parallel_endfor} }
551 }
552}
553
554static void _ccv_cnnp_batching_deinit(void* const self, void* const context)
555{
556 ccv_cnnp_batch_context_t* const batch = (ccv_cnnp_batch_context_t*)context;
557 ccv_nnc_tensor_t** const tensors = (ccv_nnc_tensor_t**)self;
558 const int size = batch->tuple.size;
559 int i;
560 for (i = 0; i < size; i++)
561 ccv_nnc_tensor_free(tensors[i]);
562 ccfreefree(tensors);
563}
564
565ccv_cnnp_dataframe_t* ccv_cnnp_dataframe_batching_new(ccv_cnnp_dataframe_t* const dataframe, const int* const column_idxs, const int column_idx_size, const int batch_count, const int group_count, const int format)
566{
567 assert(format == CCV_TENSOR_FORMAT_NCHW || format == CCV_TENSOR_FORMAT_NHWC)((void) sizeof ((format == CCV_TENSOR_FORMAT_NCHW || format ==
CCV_TENSOR_FORMAT_NHWC) ? 1 : 0), __extension__ ({ if (format
== CCV_TENSOR_FORMAT_NCHW || format == CCV_TENSOR_FORMAT_NHWC
) ; else __assert_fail ("format == CCV_TENSOR_FORMAT_NCHW || format == CCV_TENSOR_FORMAT_NHWC"
, "ccv_cnnp_dataframe_addons.c", 567, __extension__ __PRETTY_FUNCTION__
); }))
;
568 assert(column_idx_size >= 1)((void) sizeof ((column_idx_size >= 1) ? 1 : 0), __extension__
({ if (column_idx_size >= 1) ; else __assert_fail ("column_idx_size >= 1"
, "ccv_cnnp_dataframe_addons.c", 568, __extension__ __PRETTY_FUNCTION__
); }))
;
569 assert(batch_count > 0)((void) sizeof ((batch_count > 0) ? 1 : 0), __extension__ (
{ if (batch_count > 0) ; else __assert_fail ("batch_count > 0"
, "ccv_cnnp_dataframe_addons.c", 569, __extension__ __PRETTY_FUNCTION__
); }))
;
570 assert(group_count > 0)((void) sizeof ((group_count > 0) ? 1 : 0), __extension__ (
{ if (group_count > 0) ; else __assert_fail ("group_count > 0"
, "ccv_cnnp_dataframe_addons.c", 570, __extension__ __PRETTY_FUNCTION__
); }))
;
571 const int derived = ccv_cnnp_dataframe_make_tuple(dataframe, column_idxs, column_idx_size);
572 ccv_cnnp_batch_context_t* const batch = (ccv_cnnp_batch_context_t*)ccmallocmalloc(sizeof(ccv_cnnp_batch_context_t));
573 batch->tuple.size = column_idx_size * group_count;
574 batch->format = format;
575 batch->batch_count = batch_count;
576 batch->group_count = group_count;
577 return ccv_cnnp_dataframe_reduce_new(dataframe, _ccv_cnnp_batching_new, _ccv_cnnp_batching_deinit, derived, batch_count * group_count, batch, (ccv_cnnp_column_data_context_deinit_f)ccfreefree);
578}

./ccv_nnc_easy.h

1/**********************************************************
2 * C-based/Cached/Core Computer Vision Library
3 * Liu Liu, 2010-02-01
4 **********************************************************/
5
6/**********************************************************
7 * CCV - Neural Network Collection
8 **********************************************************/
9
10#ifndef GUARD_ccv_nnc_easy_h
11#define GUARD_ccv_nnc_easy_h
12
13#include <ccv.h>
14#include <nnc/ccv_nnc.h>
15
16/**
17 * Convenience API
18 *
19 * This header provides convenience APIs for nnc usage. Being convenience API,
20 * it is optimized for shorthand coding, and may collide the naming space with
21 * others.
22 *
23 */
24// c99 only, make sure your compiler supports that.
25
26#define NOOP_GRAPH_WHILE_EXPR(ccv_nnc_graph_while_f)(1) (ccv_nnc_graph_while_f)(1)
27#define NOOP_GRAPH_CASE_OF_EXPR(ccv_nnc_graph_case_of_f)(1) (ccv_nnc_graph_case_of_f)(1)
28
29// This is a better LIST_COUNT macro, it generates a list of 1+1+0+0+0 where it is 1 if the parameter presents, and 0 otherwise.
30// This works better for cases such as LIST_COUNT(1, 2, 3,) where previous macro will get 4 and this one will have correctly
31// computed result.
32#define LIST_COUNT_01(_0,_1,_2,...)_2 _2
33#define LIST_COUNT_E(...)1 LIST_COUNT_01(_0,##__VA_ARGS__,1,0)1
34#define LIST_COUNT_N(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,...)(1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +
1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +
1 +1 +1 -1)
(LIST_COUNT_E(_0)1+LIST_COUNT_E(_1)1+LIST_COUNT_E(_2)1+LIST_COUNT_E(_3)1+LIST_COUNT_E(_4)1+LIST_COUNT_E(_5)1+LIST_COUNT_E(_6)1+LIST_COUNT_E(_7)1+LIST_COUNT_E(_8)1+LIST_COUNT_E(_9)1+LIST_COUNT_E(_10)1+LIST_COUNT_E(_11)1+LIST_COUNT_E(_12)1+LIST_COUNT_E(_13)1+LIST_COUNT_E(_14)1+LIST_COUNT_E(_15)1+LIST_COUNT_E(_16)1+LIST_COUNT_E(_17)1+LIST_COUNT_E(_18)1+LIST_COUNT_E(_19)1+LIST_COUNT_E(_20)1+LIST_COUNT_E(_21)1+LIST_COUNT_E(_22)1+LIST_COUNT_E(_23)1+LIST_COUNT_E(_24)1+LIST_COUNT_E(_25)1+LIST_COUNT_E(_26)1+LIST_COUNT_E(_27)1+LIST_COUNT_E(_28)1+LIST_COUNT_E(_29)1+LIST_COUNT_E(_30)1+LIST_COUNT_E(_31)1+LIST_COUNT_E(_32)1+LIST_COUNT_E(_33)1+LIST_COUNT_E(_34)1+LIST_COUNT_E(_35)1+LIST_COUNT_E(_36)1+LIST_COUNT_E(_37)1+LIST_COUNT_E(_38)1+LIST_COUNT_E(_39)1+LIST_COUNT_E(_40)1+LIST_COUNT_E(_41)1+LIST_COUNT_E(_42)1+LIST_COUNT_E(_43)1+LIST_COUNT_E(_44)1+LIST_COUNT_E(_45)1+LIST_COUNT_E(_46)1+LIST_COUNT_E(_47)1+LIST_COUNT_E(_48)1+LIST_COUNT_E(_49)1+LIST_COUNT_E(_50)1+LIST_COUNT_E(_51)1+LIST_COUNT_E(_52)1+LIST_COUNT_E(_53)1+LIST_COUNT_E(_54)1+LIST_COUNT_E(_55)1+LIST_COUNT_E(_56)1+LIST_COUNT_E(_57)1+LIST_COUNT_E(_58)1+LIST_COUNT_E(_59)1+LIST_COUNT_E(_60)1+LIST_COUNT_E(_61)1+LIST_COUNT_E(_62)1+LIST_COUNT_E(_63)1-1)
35#define LIST_COUNT(...)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
LIST_COUNT_N(_0,##__VA_ARGS__,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
36
37#define TENSOR_LIST_X(...)(ccv_nnc_tensor_t* []){...} (ccv_nnc_tensor_t* []){__VA_ARGS__}
38
39#define TENSOR_PARAM_LIST_X(...)(ccv_nnc_tensor_param_t []){...} (ccv_nnc_tensor_param_t []){__VA_ARGS__}
40
41#define TENSOR_SYMBOL_LIST_X(...)(ccv_nnc_tensor_symbol_t []){...} (ccv_nnc_tensor_symbol_t []){__VA_ARGS__}
42
43#define TENSOR_VARIABLE_LIST_X(...)(ccv_nnc_tensor_variable_t []){...} (ccv_nnc_tensor_variable_t []){__VA_ARGS__}
44
45#define KV_X(_x, _y, ...){(_x), (_y)} {(_x), (_y)}
46#define KV(...){(...), (0)} KV_X(__VA_ARGS__, 0){(__VA_ARGS__), (0)}
47#define TENSOR_BIND_MAP_X(...)(ccv_nnc_tensor_bind_t []){...} (ccv_nnc_tensor_bind_t []){__VA_ARGS__}
48
49#define TENSOR_SYMBOL_MAP_X(...)(ccv_nnc_tensor_symbol_map_t []){...} (ccv_nnc_tensor_symbol_map_t []){__VA_ARGS__}
50
51#define GRAPH_EXEC_LIST_X(...)(ccv_nnc_graph_exec_t []){...} (ccv_nnc_graph_exec_t []){__VA_ARGS__}
52
53#define GRAPH_EXEC_SYMBOL_LIST_X(...)(ccv_nnc_graph_exec_symbol_t []){...} (ccv_nnc_graph_exec_symbol_t []){__VA_ARGS__}
54
55#define SYMBOLIC_GRAPH_PASSES_X(...)(int []){...} (int []){__VA_ARGS__}
56
57#define MODEL_LIST_X(...)(ccv_cnnp_model_t* []){...}(ccv_cnnp_model_t* []){__VA_ARGS__}
58
59#define MODEL_IO_LIST_X(...)(ccv_cnnp_model_io_t []){...}(ccv_cnnp_model_io_t []){__VA_ARGS__}
60
61#define MODEL_CMD_TENSOR_MAP_X(...)(ccv_cnnp_tensor_param_t []){...}(ccv_cnnp_tensor_param_t []){__VA_ARGS__}
62
63#define MODEL_CMD_TENSOR_LIST_X(...)(int []){...}(int []){__VA_ARGS__}
64
65#define COLUMN_ID_LIST_X(...)(int []){...}(int []){__VA_ARGS__}
66
67/**
68 * @defgroup convenience_api Convenience API
69 * @{
70 */
71/**
72 * Pass a list of tensors to NNC functions that accepts (tensor array, tensor array size).
73 * This method effectively gives two parameters as one.
74 */
75#define TENSOR_LIST(...)(ccv_nnc_tensor_t* []){...}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
TENSOR_LIST_X(__VA_ARGS__)(ccv_nnc_tensor_t* []){__VA_ARGS__}, LIST_COUNT(__VA_ARGS__)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
76/**
77 * Pass a list of tensor parameters to NNC functions that accepts (parameter array, parameter array size).
78 * This method effectively gives two parameters as one.
79 */
80#define TENSOR_PARAM_LIST(...)(ccv_nnc_tensor_param_t []){...}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
TENSOR_PARAM_LIST_X(__VA_ARGS__)(ccv_nnc_tensor_param_t []){__VA_ARGS__}, LIST_COUNT(__VA_ARGS__)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
81/**
82 * This represents a tensor symbol that is empty (tensor = nil)
83 */
84#define NO_TENSOR_SYMBOL(ccv_nnc_tensor_symbol_t){.d = CCV_NNC_NO_TENSOR_SYMBOL} (ccv_nnc_tensor_symbol_t){.d = CCV_NNC_NO_TENSOR_SYMBOL}
85/**
86 * This represents a graph exec symbol that is empty (exec = nil)
87 */
88#define NO_GRAPH_EXEC_SYMBOL(ccv_nnc_graph_exec_symbol_t){.d = CCV_NNC_NO_GRAPH_EXEC_SYMBOL
}
(ccv_nnc_graph_exec_symbol_t){.d = CCV_NNC_NO_GRAPH_EXEC_SYMBOL}
89/**
90 * Pass a list of tensor symbols to NNC functions that accepts (tensor symbol array, tensor symbol array size).
91 * This method effectively gives two parameters as one.
92 */
93#define TENSOR_SYMBOL_LIST(...)(ccv_nnc_tensor_symbol_t []){...}, (1 +1 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
TENSOR_SYMBOL_LIST_X(__VA_ARGS__)(ccv_nnc_tensor_symbol_t []){__VA_ARGS__}, LIST_COUNT(__VA_ARGS__)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
94/**
95 * Pass a list of tensor variables to NNC functions that accepts (tensor variable array, tensor variable array size).
96 * This method effectively gives two parameters as one.
97 */
98#define TENSOR_VARIABLE_LIST(...)(ccv_nnc_tensor_variable_t []){...}, (1 +1 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
TENSOR_VARIABLE_LIST_X(__VA_ARGS__)(ccv_nnc_tensor_variable_t []){__VA_ARGS__}, LIST_COUNT(__VA_ARGS__)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
99/**
100 * Pass a list of tensor bindings to NNC functions that accepts (tensor binding array, tensor binding array size).
101 * This method effectively gives two parameters as one. Since tensor binding requires two: symbol and a tensor,
102 * you should use this like: TENSOR_BIND_MAP(KV(symbol1, tensor1), KV(symbol2, tensor2)).
103 */
104#define TENSOR_BIND_MAP(...)(ccv_nnc_tensor_bind_t []){...}, (sizeof((ccv_nnc_tensor_bind_t
[]){...}) / sizeof(ccv_nnc_tensor_bind_t))
TENSOR_BIND_MAP_X(__VA_ARGS__)(ccv_nnc_tensor_bind_t []){__VA_ARGS__}, (sizeof(TENSOR_BIND_MAP_X(__VA_ARGS__)(ccv_nnc_tensor_bind_t []){__VA_ARGS__}) / sizeof(ccv_nnc_tensor_bind_t))
105/**
106 * Pass a list of tensor symbol pairs to NNC functions that accepts (tensor symbol pair array, tensor symbol pair array size).
107 * This method effectively gives two parameters as one. Since tensor symbol pair requires two: source symbol and destination symbol,
108 * you should use this like: TENSOR_SYMBOL_MAP(KV(symbol1, symbol2), KV(symbol3, symbol4)).
109 */
110#define TENSOR_SYMBOL_MAP(...)(ccv_nnc_tensor_symbol_map_t []){...}, (sizeof((ccv_nnc_tensor_symbol_map_t
[]){...}) / sizeof(ccv_nnc_tensor_symbol_map_t))
TENSOR_SYMBOL_MAP_X(__VA_ARGS__)(ccv_nnc_tensor_symbol_map_t []){__VA_ARGS__}, (sizeof(TENSOR_SYMBOL_MAP_X(__VA_ARGS__)(ccv_nnc_tensor_symbol_map_t []){__VA_ARGS__}) / sizeof(ccv_nnc_tensor_symbol_map_t))
111/**
112 * Pass a list of execution nodes to NNC functions that accepts (execution node array, execution node array size).
113 * This method effectively gives two parameters as one.
114 */
115#define GRAPH_EXEC_LIST(...)(ccv_nnc_graph_exec_t []){...}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
GRAPH_EXEC_LIST_X(__VA_ARGS__)(ccv_nnc_graph_exec_t []){__VA_ARGS__}, LIST_COUNT(__VA_ARGS__)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
116/**
117 * Pass a list of execution node symbols to NNC functions that accepts (execution node symbol array, execution node symbol array size).
118 * This method effectively gives two parameters as one.
119 */
120#define GRAPH_EXEC_SYMBOL_LIST(...)(ccv_nnc_graph_exec_symbol_t []){...}, (1 +1 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
GRAPH_EXEC_SYMBOL_LIST_X(__VA_ARGS__)(ccv_nnc_graph_exec_symbol_t []){__VA_ARGS__}, LIST_COUNT(__VA_ARGS__)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
121/**
122 * Pass both default sources and default sources size to function that accepts (sources, source size).
123 * @param x A given symbolic graph.
124 */
125#define SYMBOLIC_GRAPH_SOURCES(x)ccv_nnc_symbolic_graph_sources(x), ccv_nnc_symbolic_graph_source_size
(x)
ccv_nnc_symbolic_graph_sources(x), ccv_nnc_symbolic_graph_source_size(x)
126/**
127 * Pass both default destinations and default destinations size to function that accepts (destinations, destination size).
128 * @param x A given symbolic graph.
129 */
130#define SYMBOLIC_GRAPH_DESTINATIONS(x)ccv_nnc_symbolic_graph_destinations(x), ccv_nnc_symbolic_graph_destination_size
(x)
ccv_nnc_symbolic_graph_destinations(x), ccv_nnc_symbolic_graph_destination_size(x)
131/**
132 * Pass a list of simplification passes to NNC functions that accepts (pass array, pass array size).
133 * This method effectively gives two parameters as one.
134 */
135#define SYMBOLIC_GRAPH_PASSES(...)(int []){...}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 -1)
SYMBOLIC_GRAPH_PASSES_X(__VA_ARGS__)(int []){__VA_ARGS__}, LIST_COUNT(__VA_ARGS__)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
136/**
137 * Pass a list of CNNP models to NNC functions that accepts (model array, model array size).
138 * This method effectively gives two parameters as one.
139 */
140#define MODEL_LIST(...)(ccv_cnnp_model_t* []){...}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
MODEL_LIST_X(__VA_ARGS__)(ccv_cnnp_model_t* []){__VA_ARGS__}, LIST_COUNT(__VA_ARGS__)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
141/**
142 * Pass a list of CNNP model IOs to NNC functions that accepts (model IO array, model IO array size).
143 * This method effectively gives two parameters as one.
144 */
145#define MODEL_IO_LIST(...)(ccv_cnnp_model_io_t []){...}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 -1)
MODEL_IO_LIST_X(__VA_ARGS__)(ccv_cnnp_model_io_t []){__VA_ARGS__}, LIST_COUNT(__VA_ARGS__)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
146/**
147 * Pass a list of CNNP tensor params to ccv_cnnp_cmd_exec which accepts (tensor params array, tensor params array size).
148 * This method effectively gives two parameters as one.
149 */
150#define MODEL_CMD_TENSOR_MAP(...)(ccv_cnnp_tensor_param_t []){...}, (sizeof((ccv_cnnp_tensor_param_t
[]){...}) / sizeof(ccv_cnnp_tensor_param_t))
MODEL_CMD_TENSOR_MAP_X(__VA_ARGS__)(ccv_cnnp_tensor_param_t []){__VA_ARGS__}, (sizeof(MODEL_CMD_TENSOR_MAP_X(__VA_ARGS__)(ccv_cnnp_tensor_param_t []){__VA_ARGS__}) / sizeof(ccv_cnnp_tensor_param_t))
151/**
152 * Pass a list of CNNP tensor type to ccv_cnnp_cmd_exec which accepts (tensor type array, tensor type array size).
153 * This method effectively gives two parameters as one.
154 */
155#define MODEL_CMD_TENSOR_LIST(...)(int []){...}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 -1)
MODEL_CMD_TENSOR_LIST_X(__VA_ARGS__)(int []){__VA_ARGS__}, LIST_COUNT(__VA_ARGS__)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
156/**
157 * Pass a list of dataframe column ids to iteration function that accepts (column id array, column id array size).
158 * This method effectively gives two parameters as one.
159 */
160#define COLUMN_ID_LIST(...)(int []){...}, (1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 -1)
COLUMN_ID_LIST_X(__VA_ARGS__)(int []){__VA_ARGS__}, LIST_COUNT(__VA_ARGS__)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
161
162#define TRAVERSE_FULL0,0,0,0 0,0,0,0
163
164// We will support NUMA allocation on CPU in the future. Currently, this is not very meaningful (except enforce no memory reuse between tensors).
165#define CPU_NUMA_TENSOR_NHWC(device_id, dt, ...)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_device_id
) | CCV_TENSOR_CPU_MEMORY,.format=CCV_TENSOR_FORMAT_NHWC,.datatype
=CCV_dt,.dim={...}})
((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_##device_id) | CCV_TENSOR_CPU_MEMORY,.format=CCV_TENSOR_FORMAT_NHWC,.datatype=CCV_##dt,.dim={__VA_ARGS__}})
166#define CPU_NUMA_TENSOR_NCHW(device_id, dt, ...)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_device_id
) | CCV_TENSOR_CPU_MEMORY,.format=CCV_TENSOR_FORMAT_NCHW,.datatype
=CCV_dt,.dim={...}})
((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_##device_id) | CCV_TENSOR_CPU_MEMORY,.format=CCV_TENSOR_FORMAT_NCHW,.datatype=CCV_##dt,.dim={__VA_ARGS__}})
167#define CPU_NUMA_TENSOR_CHWN(device_id, dt, ...)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_device_id
) | CCV_TENSOR_CPU_MEMORY,.format=CCV_TENSOR_FORMAT_CHWN,.datatype
=CCV_dt,.dim={...}})
((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_##device_id) | CCV_TENSOR_CPU_MEMORY,.format=CCV_TENSOR_FORMAT_CHWN,.datatype=CCV_##dt,.dim={__VA_ARGS__}})
168#define CPU_TENSOR_NHWC(dt, ...)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_ANY) | CCV_TENSOR_CPU_MEMORY
,.format=CCV_TENSOR_FORMAT_NHWC,.datatype=CCV_dt,.dim={...}})
CPU_NUMA_TENSOR_NHWC(ANY, dt, __VA_ARGS__)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_ANY) | CCV_TENSOR_CPU_MEMORY
,.format=CCV_TENSOR_FORMAT_NHWC,.datatype=CCV_dt,.dim={__VA_ARGS__
}})
169#define CPU_TENSOR_NCHW(dt, ...)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_ANY) | CCV_TENSOR_CPU_MEMORY
,.format=CCV_TENSOR_FORMAT_NCHW,.datatype=CCV_dt,.dim={...}})
CPU_NUMA_TENSOR_NCHW(ANY, dt, __VA_ARGS__)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_ANY) | CCV_TENSOR_CPU_MEMORY
,.format=CCV_TENSOR_FORMAT_NCHW,.datatype=CCV_dt,.dim={__VA_ARGS__
}})
170#define CPU_TENSOR_CHWN(dt, ...)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_ANY) | CCV_TENSOR_CPU_MEMORY
,.format=CCV_TENSOR_FORMAT_CHWN,.datatype=CCV_dt,.dim={...}})
CPU_NUMA_TENSOR_CHWN(ANY, dt, __VA_ARGS__)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_ANY) | CCV_TENSOR_CPU_MEMORY
,.format=CCV_TENSOR_FORMAT_CHWN,.datatype=CCV_dt,.dim={__VA_ARGS__
}})
171// This way, we can do error check on the device type :)
172#define GPU_TENSOR_NHWC(device_id, dt, ...)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_device_id
) | CCV_TENSOR_GPU_MEMORY,.format=CCV_TENSOR_FORMAT_NHWC,.datatype
=CCV_dt,.dim={...}})
((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_##device_id) | CCV_TENSOR_GPU_MEMORY,.format=CCV_TENSOR_FORMAT_NHWC,.datatype=CCV_##dt,.dim={__VA_ARGS__}})
173#define GPU_TENSOR_NCHW(device_id, dt, ...)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_device_id
) | CCV_TENSOR_GPU_MEMORY,.format=CCV_TENSOR_FORMAT_NCHW,.datatype
=CCV_dt,.dim={...}})
((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_##device_id) | CCV_TENSOR_GPU_MEMORY,.format=CCV_TENSOR_FORMAT_NCHW,.datatype=CCV_##dt,.dim={__VA_ARGS__}})
174#define GPU_TENSOR_CHWN(device_id, dt, ...)((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_device_id
) | CCV_TENSOR_GPU_MEMORY,.format=CCV_TENSOR_FORMAT_CHWN,.datatype
=CCV_dt,.dim={...}})
((ccv_nnc_tensor_param_t){.type=(CCV_COMPUTE_DEVICE_##device_id) | CCV_TENSOR_GPU_MEMORY,.format=CCV_TENSOR_FORMAT_CHWN,.datatype=CCV_##dt,.dim={__VA_ARGS__}})
175/** @} */
176
177#define DIM_ALLOC(...)(int [(8)]){...} (int [CCV_NNC_MAX_DIM_ALLOC(8)]){__VA_ARGS__}
178
179#define ESCAPE_X(...)... __VA_ARGS__
180#define HINT_X_1(_stride_)((ccv_nnc_hint_t){.stride={.dim={ESCAPE_X _stride_}}, .border
={.begin={0},.end={0}}})
((ccv_nnc_hint_t){.stride={.dim={ESCAPE_X _stride_}}, .border={.begin={0},.end={0}}})
181#define HINT_X_2(_stride_, _border_)((ccv_nnc_hint_t){.stride={.dim={ESCAPE_X _stride_}}, .border
={.begin={ESCAPE_X _border_},.end={ESCAPE_X _border_}}})
((ccv_nnc_hint_t){.stride={.dim={ESCAPE_X _stride_}}, .border={.begin={ESCAPE_X _border_},.end={ESCAPE_X _border_}}})
182#define HINT_X_3(_stride_, _begin_, _end_)((ccv_nnc_hint_t){.stride={.dim={ESCAPE_X _stride_}}, .border
={.begin={ESCAPE_X _begin_},.end={ESCAPE_X _end_}}})
((ccv_nnc_hint_t){.stride={.dim={ESCAPE_X _stride_}}, .border={.begin={ESCAPE_X _begin_},.end={ESCAPE_X _end_}}})
183#define HINT_X_SEL(_1, _2, _3, _FX, ...)_FX _FX
184/**
185 * @ingroup convenience_api
186 * Simpler method to create hint.
187 * HINT(stride), HINT(stride, border), HINT(stride, border begin, border end)
188 */
189#define HINT(...)((ccv_nnc_hint_t){.stride={.dim={ESCAPE_X ...}}, .border={.begin
={0},.end={0}}})
HINT_X_SEL(__VA_ARGS__, HINT_X_3, HINT_X_2, HINT_X_1)(__VA_ARGS__)((ccv_nnc_hint_t){.stride={.dim={ESCAPE_X __VA_ARGS__}}, .border
={.begin={0},.end={0}}})
190
191static inline size_t ccv_nnc_dimension_count(const int dim[CCV_NNC_MAX_DIM_ALLOC(8)])
192{
193 if (dim[0] == 0)
194 return 0;
195 int i;
196 size_t count = 1;
197 for (i = 0; i < CCV_NNC_MAX_DIM_ALLOC(8) && dim[i] > 0; i++)
198 count *= dim[i];
199 return count;
200}
201
202static inline size_t ccv_nnc_tensor_count(const ccv_nnc_tensor_param_t params)
203{
204 return ccv_nnc_dimension_count(params.dim);
205}
206
207static inline size_t ccv_nnc_tensor_data_size(const ccv_nnc_tensor_param_t params)
208{
209 return (CCV_GET_DATA_TYPE_SIZE(params.datatype)_ccv_get_data_type_size[((params.datatype) & 0xFF000) >>
12]
* (ssize_t)ccv_nnc_tensor_count(params) + 15) & -16;
210}
211
212static inline void ccv_nnc_tensor_view_get_dim(const ccv_nnc_tensor_view_t* const tv, int dim[CCV_NNC_MAX_DIM_ALLOC(8)])
213{
214 int x;
215 const int nd = ccv_nnc_tensor_nd(tv->info.dim);
216 const int offset = CCV_NNC_MAX_DIM(2) + 2 - nd;
217 for (x = 0; x < offset; x++)
218 dim[x] = 1;
219 for (x = offset; x < CCV_NNC_MAX_DIM(2) + 2; x++)
220 dim[x] = tv->info.dim[x - offset];
221}
222
223static inline CCV_WARN_UNUSED(int)int __attribute__((warn_unused_result)) ccv_nnc_tensor_view_check_dim(const ccv_nnc_tensor_view_t* const tv, int dim[CCV_NNC_MAX_DIM_ALLOC(8)])
224{
225 int x;
226 const int nd = ccv_nnc_tensor_nd(tv->info.dim);
227 const int offset = CCV_NNC_MAX_DIM(2) + 2 - nd;
228 for (x = 0; x < offset; x++)
229 if (dim[x] != 1)
230 return 0;
231 for (x = offset; x < CCV_NNC_MAX_DIM(2) + 2; x++)
232 if (dim[x] != tv->info.dim[x - offset])
233 return 0;
234 return 1;
235}
236
237static inline void ccv_nnc_tensor_view_get_broadcast_dim(const ccv_nnc_tensor_view_t* const tv, int dim[CCV_NNC_MAX_DIM_ALLOC(8)])
238{
239 int x;
240 const int nd = ccv_nnc_tensor_nd(tv->info.dim);
241 const int offset = CCV_NNC_MAX_DIM(2) + 2 - nd;
242 for (x = 0; x < offset; x++)
243 dim[x] = ccv_max(1, dim[x])({ typeof (1) _a = (1); typeof (dim[x]) _b = (dim[x]); (_a >
_b) ? _a : _b; })
;
244 for (x = offset; x < CCV_NNC_MAX_DIM(2) + 2; x++)
245 dim[x] = ccv_max(dim[x], tv->info.dim[x - offset])({ typeof (dim[x]) _a = (dim[x]); typeof (tv->info.dim[x -
offset]) _b = (tv->info.dim[x - offset]); (_a > _b) ? _a
: _b; })
;
246}
247
248static inline CCV_WARN_UNUSED(int)int __attribute__((warn_unused_result)) ccv_nnc_tensor_view_check_broadcast_dim(const ccv_nnc_tensor_view_t* const tv, int dim[CCV_NNC_MAX_DIM_ALLOC(8)])
249{
250 int x;
251 const int nd = ccv_nnc_tensor_nd(tv->info.dim);
252 const int offset = CCV_NNC_MAX_DIM(2) + 2 - nd;
253 for (x = offset; x < CCV_NNC_MAX_DIM(2) + 2; x++)
254 if (dim[x] != tv->info.dim[x - offset] && tv->info.dim[x - offset] != 1)
255 return 0;
256 return 1;
257}
258
259static inline void ccv_nnc_tensor_view_get_inc(const ccv_nnc_tensor_view_t* const tv, int inc[CCV_NNC_MAX_DIM_ALLOC(8)])
260{
261 int x;
262 const int nd = ccv_nnc_tensor_nd(tv->info.dim);
263 const int offset = CCV_NNC_MAX_DIM(2) + 2 - nd;
264 for (x = 0; x < offset; x++)
265 inc[x] = 1;
266 for (x = offset; x < CCV_NNC_MAX_DIM(2) + 2; x++)
267 inc[x] = CCV_IS_TENSOR_VIEW(tv)((*(int*)(tv)) & CCV_TENSOR_VIEW) ? tv->inc[x - offset] : tv->info.dim[x - offset];
268}
269
270static inline int ccv_nnc_tensor_get_n(const ccv_nnc_tensor_param_t params)
271{
272 switch (params.format)
273 {
274 case CCV_TENSOR_FORMAT_NHWC:
275 case CCV_TENSOR_FORMAT_NCHW:
276 if (ccv_nnc_tensor_nd(params.dim) == CCV_NNC_MAX_DIM(2) + 1)
277 return 1;
278 else
279 return params.dim[0];
280 case CCV_TENSOR_FORMAT_CHWN:
281 return params.dim[CCV_NNC_MAX_DIM(2) + 1];
282 }
283 return 0;
284}
285
286static inline int ccv_nnc_tensor_get_c(const ccv_nnc_tensor_param_t params)
287{
288 switch (params.format)
18
'Default' branch taken. Execution continues on line 300
289 {
290 case CCV_TENSOR_FORMAT_NHWC:
291 return params.dim[ccv_nnc_tensor_nd(params.dim) - 1];
292 case CCV_TENSOR_FORMAT_NCHW:
293 if (ccv_nnc_tensor_nd(params.dim) == CCV_NNC_MAX_DIM(2) + 1)
294 return params.dim[0];
295 else
296 return params.dim[1];
297 case CCV_TENSOR_FORMAT_CHWN:
298 return params.dim[0];
299 }
300 return 0;
19
Returning zero
301}
302
303static inline void ccv_nnc_tensor_set_n(ccv_nnc_tensor_param_t* const params, const int n)
304{
305 switch (params->format)
306 {
307 case CCV_TENSOR_FORMAT_NHWC:
308 case CCV_TENSOR_FORMAT_NCHW:
309 params->dim[0] = n;
310 break;
311 case CCV_TENSOR_FORMAT_CHWN:
312 params->dim[CCV_NNC_MAX_DIM(2) + 1] = n;
313 break;
314 }
315}
316
317static inline void ccv_nnc_tensor_set_c(ccv_nnc_tensor_param_t* const params, const int nd, const int c)
318{
319 switch (params->format)
320 {
321 case CCV_TENSOR_FORMAT_NHWC:
322 params->dim[nd - 1] = c;
323 break;
324 case CCV_TENSOR_FORMAT_NCHW:
325 if (nd == CCV_NNC_MAX_DIM(2) + 1)
326 params->dim[0] = c;
327 else
328 params->dim[1] = c;
329 break;
330 case CCV_TENSOR_FORMAT_CHWN:
331 params->dim[0] = c;
332 break;
333 }
334}
335
336
337#define CMD_BLAS(...)((ccv_nnc_cmd_param_t){.size={.dim={1,1,1}},.blas={.a={...}}}
)
((ccv_nnc_cmd_param_t){.size={.dim={1,1,1}},.blas={.a={__VA_ARGS__}}})
338#define CMD_GEMM(_count)((ccv_nnc_cmd_param_t){.size={.dim={1,1,1}},.blas={.a={1,1},.
count=_count}})
((ccv_nnc_cmd_param_t){.size={.dim={1,1,1}},.blas={.a={1,1},.count=_count}}) // We default to alpha = 1 and beta = 1
339#define CMD_GENERIC_X_0()((ccv_nnc_cmd_param_t){.size={.dim={1,1,1}}}) ((ccv_nnc_cmd_param_t){.size={.dim={1,1,1}}})
340#define CMD_GENERIC_X_F(...)("This should not be used, you should have either 0 parameter or 3 parameters for CMD_GENERIC"
)
("This should not be used, you should have either 0 parameter or 3 parameters for CMD_GENERIC")
341#define CMD_GENERIC_X_3(...)((ccv_nnc_cmd_param_t){.size={.dim={...}}}) ((ccv_nnc_cmd_param_t){.size={.dim={__VA_ARGS__}}})
342#define CMD_GENERIC_X_SEL(_0, _1, _2, _3, _FX, ...)_FX _FX
343// Using ## so that if it is empty, we omit one comma.
344#define CMD_GENERIC(...)("This should not be used, you should have either 0 parameter or 3 parameters for CMD_GENERIC"
)
CMD_GENERIC_X_SEL(CMD_GENERIC_X_F, ##__VA_ARGS__, CMD_GENERIC_X_3, CMD_GENERIC_X_F, CMD_GENERIC_X_F, CMD_GENERIC_X_0)(__VA_ARGS__)("This should not be used, you should have either 0 parameter or 3 parameters for CMD_GENERIC"
)
345#define CMD_REDUCE(...)((ccv_nnc_cmd_param_t){.size={.dim={1,1,1}},.reduce={.count=(
1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 -1),.axis={...}}})
((ccv_nnc_cmd_param_t){.size={.dim={1,1,1}},.reduce={.count=LIST_COUNT(__VA_ARGS__)(1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0
+0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +
0 +0 +0 -1)
,.axis={__VA_ARGS__}}})
346/**
347 * @defgroup available_commands Available Commands
348 * @{
349 */
350#define CMD_NOOP()ccv_nnc_cmd(CCV_NNC_NOOP, 0, ccv_nnc_cmd_auto, 0) ccv_nnc_cmd(CCV_NNC_NOOP, 0, ccv_nnc_cmd_auto, 0)
351#define CMD_CUSTOM_FORWARD(f)ccv_nnc_cmd(CCV_NNC_CUSTOM_FORWARD, f, ccv_nnc_cmd_auto, 0) ccv_nnc_cmd(CCV_NNC_CUSTOM_FORWARD, f, ccv_nnc_cmd_auto, 0)
352/** @} */
353
354int ccv_nnc_is_no_hint(const ccv_nnc_hint_t hint);
355int ccv_nnc_is_cmd_auto(const ccv_nnc_cmd_param_t params);
356int ccv_nnc_is_tensor_auto(const ccv_nnc_tensor_param_t params);
357
358/**
359 * @addtogroup convenience_api
360 * @{
361 */
362/**
363 * Offsets all zero.
364 */
365extern const int ccv_nnc_no_ofs[CCV_NNC_MAX_DIM_ALLOC(8)];
366/**
367 * No hint available.
368 */
369extern const ccv_nnc_hint_t ccv_nnc_no_hint;
370/**
371 * Derive the command parameters automatically if possible.
372 */
373extern const ccv_nnc_cmd_param_t ccv_nnc_cmd_auto;
374/**
375 * Derive the tensor parameters automatically if possible.
376 */
377extern const ccv_nnc_tensor_param_t ccv_nnc_tensor_auto;
378/** @} */
379
380// Generated command flags for easy creation of ccv_nnc_cmd_t objects.
381#include "cmd/ccv_nnc_cmd_easy.h"
382
383#endif