/home/liu/actions-runner/_work/ccv/ccv/lib/nnc/ccv_nnc_micro_interpret.c
Line | Count | Source (jump to first uncovered line) |
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_nnc_micro.h" |
6 | | |
7 | | // MARK - Level-1 API |
8 | | |
9 | | static int _ccv_nnc_micro_index_interpret(const ccv_nnc_micro_loop_index_term_t index, const int* const loop_counter, const int* const shapes, const ccv_nnc_micro_scalar_t* const values, const int parameter_size) |
10 | 40.3k | { |
11 | 40.3k | switch (index.type) |
12 | 40.3k | { |
13 | 5.32k | case CCV_NNC_MICRO_LOOP_INDEX_TYPE_VAL: |
14 | 5.32k | return index.immediate_value; |
15 | 30.6k | case CCV_NNC_MICRO_LOOP_INDEX_TYPE_ID: |
16 | 30.6k | switch (index.id.type) |
17 | 30.6k | { |
18 | 955 | case CCV_NNC_MICRO_AXIS_SIZE_ID: |
19 | 955 | return shapes[index.id.id * CCV_NNC_MAX_DIM_ALLOC + index.id.d]; |
20 | 29.6k | case CCV_NNC_MICRO_LOOP_ID: |
21 | 29.6k | return loop_counter[index.id.id]; |
22 | 20 | case CCV_NNC_MICRO_SCALAR_ID: |
23 | 20 | switch (values[index.id.id].type) |
24 | 20 | { |
25 | 0 | case CCV_8U: |
26 | 0 | return values[index.id.id].u8; |
27 | 20 | case CCV_32S: |
28 | 20 | return values[index.id.id].i32; |
29 | 0 | case CCV_64S: |
30 | 0 | return (int)values[index.id.id].i64; |
31 | 20 | } |
32 | 0 | break; |
33 | 30.6k | } |
34 | 0 | break; |
35 | 4.35k | case CCV_NNC_MICRO_LOOP_INDEX_TYPE_BINARY: { |
36 | 4.35k | const int left = _ccv_nnc_micro_index_interpret(index.binary->left, loop_counter, shapes, values, parameter_size); |
37 | 4.35k | const int right = _ccv_nnc_micro_index_interpret(index.binary->right, loop_counter, shapes, values, parameter_size); |
38 | 4.35k | switch (index.binary->op) |
39 | 4.35k | { |
40 | 4.33k | case CCV_NNC_MICRO_BINARY_OP_PLUS: |
41 | 4.33k | return left + right; |
42 | 16 | case CCV_NNC_MICRO_BINARY_OP_MINUS: |
43 | 16 | return left - right; |
44 | 0 | case CCV_NNC_MICRO_BINARY_OP_MUL: |
45 | 0 | return left * right; |
46 | 0 | case CCV_NNC_MICRO_BINARY_OP_DIV: |
47 | 0 | return left / right; |
48 | 0 | case CCV_NNC_MICRO_BINARY_OP_MAX: |
49 | 0 | return ccv_max(left, right); |
50 | 0 | case CCV_NNC_MICRO_BINARY_OP_MIN: |
51 | 0 | return ccv_min(left, right); |
52 | 4.35k | } |
53 | 0 | break; |
54 | 4.35k | } |
55 | 40.3k | } |
56 | 0 | return 0; |
57 | 40.3k | } |
58 | | |
59 | | static float _ccv_nnc_micro_expression_interpret(const ccv_nnc_micro_loop_expression_t* const expression, const int* const loop_counter, const ccv_nnc_micro_scalar_t* const carrieds, const int carried_count, float* const* const vars_mem, const int* const shapes, const ccv_nnc_micro_scalar_t* const values, const int parameter_size, int* const out_of_bound_ref) |
60 | 7.15k | { |
61 | 7.15k | int i; |
62 | 7.15k | switch (expression->type) |
63 | 7.15k | { |
64 | 28 | case CCV_NNC_MICRO_LOOP_EXPR_TYPE_ID: { |
65 | 28 | assert(expression->id.type == CCV_NNC_MICRO_LOOP_CARRIED_ID); |
66 | 28 | return carrieds[expression->id.id].f32; |
67 | 28 | } |
68 | 354 | case CCV_NNC_MICRO_LOOP_EXPR_TYPE_VAL: { |
69 | 354 | return expression->immediate_value.f32; |
70 | 28 | } |
71 | 4.53k | case CCV_NNC_MICRO_LOOP_EXPR_TYPE_VAR: { |
72 | 4.53k | const ccv_nnc_micro_loop_variable_t variable = expression->variable; |
73 | 4.53k | assert(variable.id.type == CCV_NNC_MICRO_TENSOR_ID); |
74 | 4.53k | float* ptr = vars_mem[variable.id.id]; |
75 | 4.53k | size_t size = 1; |
76 | 4.53k | int out_of_bound = 0; |
77 | 26.6k | for (i = variable.index_count - 1; !out_of_bound && i >= 0; i--22.1k ) |
78 | 22.1k | { |
79 | 22.1k | const int index = _ccv_nnc_micro_index_interpret(variable.index[i], loop_counter, shapes, values, parameter_size); |
80 | 22.1k | if (!variable.no_check_bound[i] && |
81 | 22.1k | (2.88k index < 02.88k || index >= shapes[variable.id.id * 2.88k CCV_NNC_MAX_DIM_ALLOC2.88k + i])) |
82 | 0 | out_of_bound = 1; |
83 | 22.1k | ptr += index * size; |
84 | 22.1k | size *= shapes[variable.id.id * CCV_NNC_MAX_DIM_ALLOC + i]; |
85 | 22.1k | } |
86 | 4.53k | if (out_of_bound) |
87 | 0 | { |
88 | 0 | *out_of_bound_ref = 1; |
89 | 0 | return 0; |
90 | 0 | } |
91 | 4.53k | return ptr[0]; |
92 | 4.53k | } |
93 | 0 | case CCV_NNC_MICRO_LOOP_EXPR_TYPE_UNARY: { |
94 | 0 | const float left = _ccv_nnc_micro_expression_interpret(expression->unary.x, loop_counter, carrieds, carried_count, vars_mem, shapes, values, parameter_size, out_of_bound_ref); |
95 | 0 | if (*out_of_bound_ref) |
96 | 0 | return 0; |
97 | 0 | switch (expression->unary.unary_op) |
98 | 0 | { |
99 | 0 | case CCV_NNC_MICRO_UNARY_OP_EXP: |
100 | 0 | return exp(left); |
101 | 0 | case CCV_NNC_MICRO_UNARY_OP_LOG: |
102 | 0 | return log(left); |
103 | 0 | } |
104 | 0 | break; |
105 | 0 | } |
106 | 2.23k | case CCV_NNC_MICRO_LOOP_EXPR_TYPE_BINARY: { |
107 | 2.23k | const float left = _ccv_nnc_micro_expression_interpret(expression->binary.left, loop_counter, carrieds, carried_count, vars_mem, shapes, values, parameter_size, out_of_bound_ref); |
108 | 2.23k | if (*out_of_bound_ref) |
109 | 0 | return 0; |
110 | 2.23k | const float right = _ccv_nnc_micro_expression_interpret(expression->binary.right, loop_counter, carrieds, carried_count, vars_mem, shapes, values, parameter_size, out_of_bound_ref); |
111 | 2.23k | if (*out_of_bound_ref) |
112 | 0 | return 0; |
113 | 2.23k | switch (expression->binary.binary_op) |
114 | 2.23k | { |
115 | 0 | case CCV_NNC_MICRO_BINARY_OP_PLUS: |
116 | 0 | return left + right; |
117 | 0 | case CCV_NNC_MICRO_BINARY_OP_MINUS: |
118 | 0 | return left - right; |
119 | 2.23k | case CCV_NNC_MICRO_BINARY_OP_MUL: |
120 | 2.23k | return left * right; |
121 | 0 | case CCV_NNC_MICRO_BINARY_OP_DIV: |
122 | 0 | return left / right; |
123 | 0 | case CCV_NNC_MICRO_BINARY_OP_MAX: |
124 | 0 | return ccv_max(left, right); |
125 | 0 | case CCV_NNC_MICRO_BINARY_OP_MIN: |
126 | 0 | return ccv_min(left, right); |
127 | 2.23k | } |
128 | 0 | break; |
129 | 2.23k | } |
130 | 7.15k | } |
131 | 0 | return 0; |
132 | 7.15k | } |
133 | | |
134 | | static void _ccv_nnc_micro_statement_interpret(const ccv_nnc_micro_loop_statement_t statement, const int* const loop_counter, ccv_nnc_micro_scalar_t* const carrieds, const int carried_count, float* const* const vars_mem, const int* const shapes, const ccv_nnc_micro_scalar_t* const values, const int parameter_size) |
135 | 2.68k | { |
136 | 2.68k | int i; |
137 | 2.68k | switch (statement.type) |
138 | 2.68k | { |
139 | 454 | case CCV_NNC_MICRO_LOOP_STATEMENT_TYPE_ASSIGNMENT: { |
140 | 454 | assert(statement.assignment.lvalue.id.type == CCV_NNC_MICRO_TENSOR_ID); |
141 | 454 | const ccv_nnc_micro_loop_variable_t variable = statement.assignment.lvalue; |
142 | 454 | float* ptr = vars_mem[variable.id.id]; |
143 | 454 | size_t size = 1; |
144 | 454 | int out_of_bound = 0; |
145 | 2.20k | for (i = variable.index_count - 1; !out_of_bound && i >= 0; i--1.75k ) |
146 | 1.75k | { |
147 | 1.75k | const int index = _ccv_nnc_micro_index_interpret(variable.index[i], loop_counter, shapes, values, parameter_size); |
148 | 1.75k | if (!variable.no_check_bound[i] && |
149 | 1.75k | (0 index < 00 || index >= shapes[variable.id.id * 0 CCV_NNC_MAX_DIM_ALLOC0 + i])) |
150 | 0 | out_of_bound = 1; |
151 | 1.75k | ptr += index * size; |
152 | 1.75k | size *= shapes[variable.id.id * CCV_NNC_MAX_DIM_ALLOC + i]; |
153 | 1.75k | } |
154 | 454 | if (out_of_bound) |
155 | 0 | return; |
156 | 454 | const float val = _ccv_nnc_micro_expression_interpret(&statement.assignment.rvalue, loop_counter, carrieds, carried_count, vars_mem, shapes, values, parameter_size, &out_of_bound); |
157 | 454 | if (out_of_bound) |
158 | 0 | return; |
159 | 454 | ptr[0] = val; |
160 | 454 | break; |
161 | 454 | } |
162 | 2.23k | case CCV_NNC_MICRO_LOOP_STATEMENT_TYPE_COMPOUND_ASSIGNMENT: { |
163 | 2.23k | int out_of_bound = 0; |
164 | 2.23k | const float rvalue = _ccv_nnc_micro_expression_interpret(&statement.compound_assignment.rvalue, loop_counter, carrieds, carried_count, vars_mem, shapes, values, parameter_size, &out_of_bound); |
165 | 2.23k | if (out_of_bound) |
166 | 0 | return; |
167 | 2.23k | switch (statement.compound_assignment.lvalue.type) |
168 | 2.23k | { |
169 | 744 | case CCV_NNC_MICRO_LOOP_EXPR_TYPE_ID: { |
170 | 744 | assert(statement.compound_assignment.lvalue.id.type == CCV_NNC_MICRO_LOOP_CARRIED_ID); |
171 | 744 | switch (statement.compound_assignment.lvalue.id.d) |
172 | 744 | { |
173 | 0 | case CCV_NNC_MICRO_REDUCE_OP_MAX: |
174 | 0 | carrieds[statement.compound_assignment.lvalue.id.id].f32 = ccv_max(carrieds[statement.compound_assignment.lvalue.id.id].f32, rvalue); |
175 | 0 | break; |
176 | 0 | case CCV_NNC_MICRO_REDUCE_OP_MIN: |
177 | 0 | carrieds[statement.compound_assignment.lvalue.id.id].f32 = ccv_min(carrieds[statement.compound_assignment.lvalue.id.id].f32, rvalue); |
178 | 0 | break; |
179 | 0 | case CCV_NNC_MICRO_REDUCE_OP_ARGMAX: |
180 | 0 | assert(0); |
181 | 0 | break; |
182 | 0 | case CCV_NNC_MICRO_REDUCE_OP_ARGMIN: |
183 | 0 | assert(0); |
184 | 0 | break; |
185 | 0 | case CCV_NNC_MICRO_REDUCE_OP_MEAN: |
186 | 0 | carrieds[statement.compound_assignment.lvalue.id.id].f32 += rvalue; |
187 | 0 | break; |
188 | 744 | case CCV_NNC_MICRO_REDUCE_OP_SUM: |
189 | 744 | carrieds[statement.compound_assignment.lvalue.id.id].f32 += rvalue; |
190 | 744 | break; |
191 | 0 | case CCV_NNC_MICRO_REDUCE_OP_PROD: |
192 | 0 | carrieds[statement.compound_assignment.lvalue.id.id].f32 *= rvalue; |
193 | 0 | break; |
194 | 744 | } |
195 | 744 | break; |
196 | 744 | } |
197 | 1.48k | case CCV_NNC_MICRO_LOOP_EXPR_TYPE_VAR: { |
198 | 1.48k | assert(statement.compound_assignment.lvalue.id.type == CCV_NNC_MICRO_TENSOR_ID); |
199 | 1.48k | const ccv_nnc_micro_loop_variable_t variable = statement.compound_assignment.lvalue.variable; |
200 | 1.48k | float* ptr = vars_mem[variable.id.id]; |
201 | 1.48k | size_t size = 1; |
202 | 7.34k | for (i = variable.index_count - 1; !out_of_bound && i >= 0; i--5.85k ) |
203 | 5.85k | { |
204 | 5.85k | const int index = _ccv_nnc_micro_index_interpret(variable.index[i], loop_counter, shapes, values, parameter_size); |
205 | 5.85k | if (!variable.no_check_bound[i] && |
206 | 5.85k | (1.44k index < 01.44k || index >= shapes[variable.id.id * 1.44k CCV_NNC_MAX_DIM_ALLOC1.44k + i])) |
207 | 0 | out_of_bound = 1; |
208 | 5.85k | ptr += index * size; |
209 | 5.85k | size *= shapes[variable.id.id * CCV_NNC_MAX_DIM_ALLOC + i]; |
210 | 5.85k | } |
211 | 1.48k | if (out_of_bound) |
212 | 0 | return; |
213 | 1.48k | ptr[0] += rvalue; |
214 | 1.48k | break; |
215 | 1.48k | } |
216 | 2.23k | } |
217 | 2.23k | break; |
218 | 2.23k | } |
219 | 2.68k | } |
220 | 2.68k | } |
221 | | |
222 | | static void _ccv_nnc_micro_loop_interpret(const ccv_nnc_micro_loop_t* const loops, const int loop_count, const int index, int* const loop_counter, ccv_nnc_micro_scalar_t* const carrieds, const int carried_count, float* const* const vars_mem, const int* const shapes, const ccv_nnc_micro_scalar_t* const values, const int parameter_size) |
223 | 2.78k | { |
224 | 2.78k | if (index >= loop_count) |
225 | 1.91k | return; |
226 | 871 | const int start_index = _ccv_nnc_micro_index_interpret(loops[index].start_index, loop_counter, shapes, values, parameter_size); |
227 | 871 | const int end_index = _ccv_nnc_micro_index_interpret(loops[index].end_index, loop_counter, shapes, values, parameter_size); |
228 | 871 | int i, j; |
229 | 871 | const ccv_nnc_micro_loop_statement_t* const statements = loops[index].statements; |
230 | 871 | const int statement_count = loops[index].statement_count; |
231 | 871 | const ccv_nnc_micro_loop_carried_t* const carried_refs = loops[index].carrieds; |
232 | 871 | const int carried_ref_count = loops[index].carried_count; |
233 | 3.64k | for (i = start_index; i < end_index; i++2.77k ) |
234 | 2.77k | { |
235 | 2.77k | loop_counter[loops[index].id.id] = i; |
236 | 2.79k | for (j = 0; j < carried_ref_count; j++28 ) |
237 | 28 | { |
238 | 28 | assert(carried_refs[j].id.type == CCV_NNC_MICRO_LOOP_CARRIED_ID); |
239 | 28 | assert(carried_refs[j].id.id < carried_count); |
240 | 28 | switch (carried_refs[j].id.d) |
241 | 28 | { |
242 | 0 | case CCV_NNC_MICRO_REDUCE_OP_MAX: |
243 | 0 | carrieds[carried_refs[j].id.id].f32 = -FLT_MAX; |
244 | 0 | break; |
245 | 0 | case CCV_NNC_MICRO_REDUCE_OP_MIN: |
246 | 0 | carrieds[carried_refs[j].id.id].f32 = FLT_MAX; |
247 | 0 | break; |
248 | 0 | case CCV_NNC_MICRO_REDUCE_OP_ARGMAX: |
249 | 0 | carrieds[carried_refs[j].id.id].i32 = -1; |
250 | 0 | break; |
251 | 0 | case CCV_NNC_MICRO_REDUCE_OP_ARGMIN: |
252 | 0 | carrieds[carried_refs[j].id.id].i32 = -1; |
253 | 0 | break; |
254 | 0 | case CCV_NNC_MICRO_REDUCE_OP_MEAN: |
255 | 0 | carrieds[carried_refs[j].id.id].f32 = 0; |
256 | 0 | break; |
257 | 28 | case CCV_NNC_MICRO_REDUCE_OP_SUM: |
258 | 28 | carrieds[carried_refs[j].id.id].f32 = 0; |
259 | 28 | break; |
260 | 0 | case CCV_NNC_MICRO_REDUCE_OP_PROD: |
261 | 0 | carrieds[carried_refs[j].id.id].f32 = 1; |
262 | 0 | break; |
263 | 28 | } |
264 | 28 | } |
265 | 2.77k | _ccv_nnc_micro_loop_interpret(loops, loop_count, index + 1, loop_counter, carrieds, carried_count, vars_mem, shapes, values, parameter_size); |
266 | 5.45k | for (j = 0; j < statement_count; j++2.68k ) |
267 | 2.68k | _ccv_nnc_micro_statement_interpret(statements[j], loop_counter, carrieds, carried_count, vars_mem, shapes, values, parameter_size); |
268 | 2.77k | } |
269 | 871 | } |
270 | | |
271 | | void ccv_nnc_micro_combine_interpret(ccv_nnc_micro_combine_t* const combine, const uint32_t cmd, ccv_nnc_tensor_t* const* const inputs, const int input_size, const ccv_nnc_micro_scalar_t* const values, const int parameter_size, ccv_nnc_tensor_t* const* const outputs, const int output_size) |
272 | 6 | { |
273 | | // We haven't optimized for emit_grad at the moment yet. |
274 | 6 | assert(cmd == CCV_NNC_CUSTOM_FORWARD || cmd == CCV_NNC_CUSTOM_BACKWARD); |
275 | 6 | int i, j; |
276 | 6 | const ccv_nnc_micro_program_t* const program = cmd == CCV_NNC_CUSTOM_FORWARD ? &combine->forward3 : &combine->backward3 ; |
277 | 6 | const int var_count = program->var_count; |
278 | 6 | assert(input_size == program->input_size); |
279 | 6 | assert(output_size == program->output_size); |
280 | 6 | assert(parameter_size == combine->parameter_size); |
281 | 6 | int* const shapes = (int*)cccalloc(var_count, sizeof(int) * CCV_NNC_MAX_DIM_ALLOC); |
282 | 6 | ccv_nnc_micro_tensor_t* const vars = program->vars; |
283 | 21 | for (i = 0; i < input_size; i++15 ) |
284 | 15 | memcpy(shapes + program->inputs[i] * CCV_NNC_MAX_DIM_ALLOC, &inputs[i]->info.dim, sizeof(int) * CCV_NNC_MAX_DIM_ALLOC); |
285 | 6 | int loop_counter[CCV_NNC_MAX_DIM_ALLOC]; |
286 | 60 | for (i = 0; i < var_count; i++54 ) |
287 | 54 | { |
288 | 54 | int flag = 0; |
289 | 186 | for (j = 0; !flag && j < input_size171 ; j++132 ) |
290 | 132 | flag = (program->inputs[j] == i); |
291 | 54 | if (flag) |
292 | 15 | continue; |
293 | 39 | if (vars[i].shape) |
294 | 18 | { |
295 | 120 | for (j = 0; j < vars[i].dimensions; j++102 ) |
296 | 102 | shapes[i * CCV_NNC_MAX_DIM_ALLOC + j] = _ccv_nnc_micro_index_interpret(vars[i].shape[j], loop_counter, shapes, values, parameter_size); |
297 | 18 | } else |
298 | 21 | memcpy(shapes + i * CCV_NNC_MAX_DIM_ALLOC, shapes + vars[i].input * CCV_NNC_MAX_DIM_ALLOC, sizeof(int) * CCV_NNC_MAX_DIM_ALLOC); |
299 | 39 | } |
300 | 6 | const ccv_array_t* const equal_assertions = combine->equal_assertions; |
301 | 14 | for (i = 0; i < equal_assertions->rnum; i++8 ) |
302 | 8 | { |
303 | 8 | ccv_nnc_micro_id_equal_assertion_t* const equal_assertion = ccv_array_get(equal_assertions, i); |
304 | 8 | assert(shapes[equal_assertion->left.id * CCV_NNC_MAX_DIM_ALLOC + equal_assertion->left.d] == shapes[equal_assertion->right.id * CCV_NNC_MAX_DIM_ALLOC + equal_assertion->right.d]); |
305 | 8 | } |
306 | 6 | size_t total_size = 0; |
307 | 60 | for (i = 0; i < var_count; i++54 ) |
308 | 54 | { |
309 | 54 | int flag = 0; |
310 | 186 | for (j = 0; !flag && j < input_size171 ; j++132 ) |
311 | 132 | flag = (program->inputs[j] == i); |
312 | 117 | for (j = 0; !flag && j < output_size93 ; j++63 ) |
313 | 63 | flag = (program->outputs[j] == i); |
314 | 54 | if (flag) |
315 | 24 | continue; |
316 | 30 | if (vars[i].no_alloc) // This is skipped. |
317 | 27 | continue; |
318 | | // allocating memory for these. |
319 | 3 | size_t size = 1; |
320 | 12 | for (j = 0; j < vars[i].dimensions; j++9 ) |
321 | 9 | size *= shapes[i * CCV_NNC_MAX_DIM_ALLOC + j]; |
322 | 3 | total_size += size; |
323 | 3 | } |
324 | 6 | float** const vars_mem = (float**)ccmalloc(sizeof(float*) * var_count + sizeof(float) * total_size); |
325 | 6 | float* ptr = (float*)(vars_mem + var_count); |
326 | | // Assuming these are not tensor_view_t. |
327 | 15 | for (i = 0; i < output_size; i++9 ) |
328 | 9 | { |
329 | 9 | assert(CCV_IS_TENSOR_CONTIGUOUS(outputs[i])); |
330 | 9 | vars_mem[program->outputs[i]] = outputs[i]->data.f32; |
331 | 9 | } |
332 | 60 | for (i = 0; 6 i < var_count; i++54 ) |
333 | 54 | { |
334 | 54 | int flag = 0; |
335 | 186 | for (j = 0; !flag && j < input_size171 ; j++132 ) |
336 | 132 | flag = (program->inputs[j] == i); |
337 | 117 | for (j = 0; !flag && j < output_size93 ; j++63 ) |
338 | 63 | flag = (program->outputs[j] == i); |
339 | 54 | if (flag) |
340 | 24 | continue; |
341 | 30 | if (vars[i].no_alloc) // This is skipped. |
342 | 27 | { |
343 | 27 | vars_mem[i] = 0; |
344 | 27 | continue; |
345 | 27 | } |
346 | | // allocating memory for these. |
347 | 3 | size_t size = 1; |
348 | 12 | for (j = 0; j < vars[i].dimensions; j++9 ) |
349 | 9 | size *= shapes[i * CCV_NNC_MAX_DIM_ALLOC + j]; |
350 | 3 | vars_mem[i] = ptr; |
351 | 3 | ptr += size; |
352 | 3 | } |
353 | 21 | for (i = 0; i < input_size; i++15 ) |
354 | 15 | { |
355 | 15 | assert(CCV_IS_TENSOR_CONTIGUOUS(inputs[i])); |
356 | 15 | vars_mem[program->inputs[i]] = inputs[i]->data.f32; |
357 | 15 | } |
358 | 6 | ccv_nnc_micro_function_t* const functions = program->functions; |
359 | 6 | const int function_count = program->function_count; |
360 | 6 | int max_carried_count = 0; |
361 | 12 | for (i = 0; i < function_count; i++6 ) |
362 | 6 | { |
363 | 6 | const int block_count = functions[i].block_count; |
364 | 6 | ccv_nnc_micro_loop_block_t* const blocks = block_count == 1 ? &functions[i].one_block2 : functions[i].blocks4 ; |
365 | 21 | for (j = 0; j < block_count; j++15 ) |
366 | 15 | max_carried_count = ccv_max(max_carried_count, blocks[j].carried_count); |
367 | 6 | } |
368 | 6 | ccv_nnc_micro_scalar_t* const carrieds = max_carried_count > 0 ? (ccv_nnc_micro_scalar_t*)ccmalloc(sizeof(ccv_nnc_micro_scalar_t) * max_carried_count) : 00 ; |
369 | 12 | for (i = 0; i < function_count; i++6 ) |
370 | 6 | { |
371 | 6 | const int block_count = functions[i].block_count; |
372 | 6 | ccv_nnc_micro_loop_block_t* const blocks = block_count == 1 ? &functions[i].one_block2 : functions[i].blocks4 ; |
373 | 21 | for (j = 0; j < block_count; j++15 ) |
374 | 15 | _ccv_nnc_micro_loop_interpret(blocks[j].loops, blocks[j].loop_count, 0, loop_counter, carrieds, blocks[j].carried_count, vars_mem, shapes, values, parameter_size); |
375 | 6 | } |
376 | 6 | if (carrieds) |
377 | 6 | ccfree(carrieds); |
378 | 6 | ccfree(vars_mem); |
379 | 6 | ccfree(shapes); |
380 | 6 | } |