/home/liu/actions-runner/_work/ccv/ccv/lib/nnc/cmd/reduce/ccv_nnc_argmax_cpu_ref.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "ccv.h" |
2 | | #include "ccv_internal.h" |
3 | | #include "nnc/ccv_nnc.h" |
4 | | #include "nnc/ccv_nnc_easy.h" |
5 | | #include "nnc/ccv_nnc_internal.h" |
6 | | #ifdef USE_OPENMP |
7 | | #include <omp.h> |
8 | | #endif |
9 | | #ifdef USE_DISPATCH |
10 | | #include <dispatch/dispatch.h> |
11 | | #endif |
12 | | |
13 | | // Shared methods. |
14 | | #include "../_ccv_nnc_cpu_ref.h" |
15 | | |
16 | | static int _ccv_nnc_argmax_forw(const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint, const int flags, ccv_nnc_tensor_t* const* const inputs, const int input_size, ccv_nnc_tensor_t* const* const outputs, const int output_size, ccv_nnc_stream_context_t* const stream_context) |
17 | 4 | { |
18 | 4 | assert(input_size == 1); |
19 | 4 | ccv_nnc_tensor_t* const a = inputs[0]; |
20 | 4 | assert(CCV_IS_TENSOR_CONTIGUOUS(a)); |
21 | 4 | assert(output_size == 1); |
22 | 4 | ccv_nnc_tensor_t* const b = outputs[0]; |
23 | 4 | assert(CCV_IS_TENSOR_CONTIGUOUS(b)); |
24 | 4 | const int axis = cmd.info.reduce.axis[0]; |
25 | 4 | assert(cmd.info.reduce.count == 1); |
26 | 4 | assert(axis >= 0); |
27 | 4 | const int a_nd = ccv_nnc_tensor_nd(a->info.dim); |
28 | 4 | assert(axis < a_nd); |
29 | 4 | const int b_nd = ccv_nnc_tensor_nd(b->info.dim); |
30 | 4 | int i, j, k; |
31 | 12 | for (i = axis; i < a_nd; i++8 ) |
32 | 8 | { assert(a->info.dim[i] == (b_nd - (a_nd - i) >= 0) ? b->info.dim[b_nd - (a_nd - i)] : 1); } |
33 | 4 | assert(1 == (b_nd - (a_nd - axis) >= 0) ? b->info.dim[b_nd - (a_nd - axis)] : 1); |
34 | 6 | for (i = 0; 4 i < axis; i++2 ) |
35 | 2 | { assert(a->info.dim[i] == (b_nd - (a_nd - i) >= 0) ? b->info.dim[b_nd - (a_nd - i)] : 1); } |
36 | 4 | const int tensor_count = ccv_nnc_tensor_count(a->info); |
37 | 4 | const int axis_dim = a->info.dim[axis]; |
38 | 4 | int dim_after_axis = 1; |
39 | 8 | for (i = axis + 1; i < a_nd; i++4 ) |
40 | 4 | dim_after_axis *= a->info.dim[i]; |
41 | 4 | const int dim_before_axis = tensor_count / axis_dim / dim_after_axis; |
42 | 4 | assert(ccv_nnc_tensor_count(b->info) == tensor_count / axis_dim); |
43 | 4 | const float* const ap = a->data.f32; |
44 | 4 | assert(b->info.datatype == CCV_32F || b->info.datatype == CCV_32S); |
45 | 4 | if (b->info.datatype == CCV_32S) |
46 | 4 | { |
47 | 4 | int* const bp = b->data.i32; |
48 | 18 | for (i = 0; i < dim_before_axis; i++14 ) |
49 | 14 | { |
50 | 14 | const float* const ap0 = ap + i * dim_after_axis * axis_dim; |
51 | 14 | int* const bp0 = bp + i * dim_after_axis; |
52 | 172 | for (j = 0; j < dim_after_axis; j++158 ) |
53 | 158 | { |
54 | 158 | float max = ap0[j]; |
55 | 158 | int idx = 0; |
56 | 468 | for (k = 1; k < axis_dim; k++310 ) |
57 | 310 | if (ap0[j + k * dim_after_axis] > max) |
58 | 128 | max = ap0[j + k * dim_after_axis], idx = k; |
59 | 158 | bp0[j] = idx; |
60 | 158 | } |
61 | 14 | } |
62 | 4 | } else { |
63 | 0 | float* const bp = b->data.f32; |
64 | 0 | for (i = 0; i < dim_before_axis; i++) |
65 | 0 | { |
66 | 0 | const float* const ap0 = ap + i * dim_after_axis * axis_dim; |
67 | 0 | float* const bp0 = bp + i * dim_after_axis; |
68 | 0 | for (j = 0; j < dim_after_axis; j++) |
69 | 0 | { |
70 | 0 | float max = ap0[j]; |
71 | 0 | int idx = 0; |
72 | 0 | for (k = 1; k < axis_dim; k++) |
73 | 0 | if (ap0[j + k * dim_after_axis] > max) |
74 | 0 | max = ap0[j + k * dim_after_axis], idx = k; |
75 | 0 | bp0[j] = idx; |
76 | 0 | } |
77 | 0 | } |
78 | 0 | } |
79 | 4 | return CCV_NNC_EXEC_SUCCESS; |
80 | 4 | } |
81 | | |
82 | | static int _ccv_nnc_argmax_back(const ccv_nnc_cmd_t cmd, const ccv_nnc_hint_t hint, const int flags, ccv_nnc_tensor_t* const* const inputs, const int input_size, ccv_nnc_tensor_t* const* const outputs, const int output_size, ccv_nnc_stream_context_t* const stream_context) |
83 | 0 | { |
84 | 0 | return CCV_NNC_EXEC_INVALID; |
85 | 0 | } |
86 | | |
87 | | REGISTER_COMMAND_BACKEND(CCV_NNC_ARGMAX_FORWARD, CCV_NNC_BACKEND_CPU_REF)(ccv_nnc_cmd_backend_registry_t* const registry) |
88 | 1 | { |
89 | 1 | registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW | CCV_TENSOR_FORMAT_CHWN; |
90 | 1 | registry->tensor_datatypes = CCV_32F | CCV_32S; |
91 | 1 | registry->tensor_memory = CCV_TENSOR_CPU_MEMORY; |
92 | 1 | registry->algorithms = 1; |
93 | 1 | registry->exec = _ccv_nnc_argmax_forw; |
94 | 1 | } |
95 | | |
96 | | REGISTER_COMMAND_BACKEND(CCV_NNC_ARGMAX_BACKWARD, CCV_NNC_BACKEND_CPU_REF)(ccv_nnc_cmd_backend_registry_t* const registry) |
97 | 1 | { |
98 | 1 | registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW | CCV_TENSOR_FORMAT_CHWN; |
99 | 1 | registry->tensor_datatypes = CCV_32F | CCV_32S; |
100 | 1 | registry->tensor_memory = CCV_TENSOR_CPU_MEMORY; |
101 | 1 | registry->algorithms = 1; |
102 | 1 | registry->exec = _ccv_nnc_argmax_back; |
103 | 1 | } |