## Coverage Report

#### Created: 2026-04-14 11:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/liu/actions-runner/_work/ccv/ccv/lib/nnc/cmd/reduce/ccv_nnc_argmax_cpu_ref.c

    Line
    Count
    Source
    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; 4i < 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
    }