## Coverage Report

#### Created: 2026-04-14 20:48

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

    /home/liu/actions-runner/_work/ccv/ccv/lib/nnc/cmd/pad/ccv_nnc_pad_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
    static int _ccv_nnc_pad_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)
    14
    16
    {
    15
    16
      assert(input_size == 1);
    16
    16
      ccv_nnc_tensor_view_t* const a = (ccv_nnc_tensor_view_t*)inputs[0];
    17
    16
      ccv_nnc_tensor_view_t* const b = (ccv_nnc_tensor_view_t*)outputs[0];
    18
    16
      assert(ccv_nnc_tensor_nd(a->info.dim) <= CCV_NNC_MAX_DIM + 2);
    19
    16
      assert(ccv_nnc_tensor_nd(b->info.dim) <= CCV_NNC_MAX_DIM + 2);
    20
      // Assuming this is float 32.
    21
    16
      int adim[CCV_NNC_MAX_DIM_ALLOC];
    22
    16
      int bdim[CCV_NNC_MAX_DIM_ALLOC];
    23
    16
      ccv_nnc_tensor_view_get_dim(a, adim);
    24
    16
      ccv_nnc_tensor_view_get_dim(b, bdim);
    25
    16
      int astride[CCV_NNC_MAX_DIM_ALLOC];
    26
    16
      int bstride[CCV_NNC_MAX_DIM_ALLOC];
    27
    16
      assert(CCV_NNC_MAX_DIM == 2); // Need to change this logic for CCV_NNC_MAX_DIM == other number.
    28
    16
      ccv_nnc_tensor_view_get_stride(a, astride);
    29
    16
      ccv_nnc_tensor_view_get_stride(b, bstride);
    30
    16
      int i[CCV_NNC_MAX_DIM + 2];
    31
    16
      int x;
    32
    16
      float* const ap = a->data.f32;
    33
    16
      float* const bp = b->data.f32;
    34
    16
      const int nd = ccv_nnc_tensor_nd(a->info.dim);
    35
    16
      const int offset = CCV_NNC_MAX_DIM + 2 - nd;
    36
    16
      assert(offset >= 0);
    37
    56
      for (x = 0; 16x < nd; x++40) // We don't support negative pad.
    38
    40
        { assert(cmd.info.size.dim[x] >= 0 && cmd.info.pad.end[x] >= 0); }
    39
    16
      int begin[CCV_NNC_MAX_DIM_ALLOC];
    40
    56
      for (x = 0; x < nd; x++40)
    41
    40
        begin[x + offset] = cmd.info.size.dim[x];
    42
    40
      for (x = 0; x < offset; x++24)
    43
    24
        begin[x] = 0;
    44
      // Non-optimal case, need to do skip if needed.
    45
    16
      if (cmd.info.pad.type == CCV_NNC_PAD_ZERO)
    46
    6
      {
    47
    16
        for (i[0] = 0; i[0] < bdim[0]; i[0]++10)
    48
    10
        {
    49
    10
          float* const ap0 = (i[0] >= begin[0] && i[0] < adim[0] + begin[0]8) ? ap + (i[0] - begin[0]) * astride[0]7 : 03;
    50
    10
          float* const bp0 = bp + i[0] * bstride[0];
    51
    42
          for (i[1] = 0; i[1] < bdim[1]; i[1]++32)
    52
    32
          {
    53
    32
            float* const ap1 = (ap0 && i[1] >= begin[1]20 && i[1] < adim[1] + begin[1]15) ? ap0 + (i[1] - begin[1]) * astride[1]11 : 021;
    54
    32
            float* bp1 = bp0 + i[1] * bstride[1];
    55
    154
            for (i[2] = 0; i[2] < bdim[2]; i[2]++122)
    56
    122
            {
    57
    122
              float* const ap2 = (ap1 && i[2] >= begin[2]47 && i[2] < adim[2] + begin[2]32) ? ap1 + (i[2] - begin[2]) * astride[2]24 : 098;
    58
    789
              for (x = 0; x < bdim[3]; x++667)
    59
    667
                bp1[x] = (ap2 && x >= begin[3]148 && x < adim[3] + begin[3]142) ? ap2[x - begin[3]]122 : 0545;
    60
    122
              bp1 += bstride[2];
    61
    122
            }
    62
    32
          }
    63
    10
        }
    64
    10
      } else if (cmd.info.pad.type == CCV_NNC_PAD_REFLECT) {
    65
    15
        for (i[0] = 0; i[0] < bdim[0]; i[0]++10)
    66
    10
        {
    67
    10
          float* const ap0 = ap + (i[0] - begin[0] > adim[0] - 1 ? adim[0] - 2 - (i[0] - begin[0] - adim[0])1 : abs(i[0] - begin[0])9) * astride[0];
    68
    10
          float* const bp0 = bp + i[0] * bstride[0];
    69
    41
          for (i[1] = 0; i[1] < bdim[1]; i[1]++31)
    70
    31
          {
    71
    31
            float* const ap1 = ap0 + (i[1] - begin[1] > adim[1] - 1 ? adim[1] - 2 - (i[1] - begin[1] - adim[1])7 : abs(i[1] - begin[1])24) * astride[1];
    72
    31
            float* bp1 = bp0 + i[1] * bstride[1];
    73
    126
            for (i[2] = 0; i[2] < bdim[2]; i[2]++95)
    74
    95
            {
    75
    95
              float* const ap2 = ap1 + (i[2] - begin[2] > adim[2] - 1 ? adim[2] - 2 - (i[2] - begin[2] - adim[2])0 : abs(i[2] - begin[2])) * astride[2];
    76
    341
              for (x = 0; x < bdim[3]; x++246)
    77
    246
                bp1[x] = ap2[(x - begin[3] > adim[3] - 1 ? adim[3] - 2 - (x - begin[3] - adim[3])95 : abs(x - begin[3])151)];
    78
    95
              bp1 += bstride[2];
    79
    95
            }
    80
    31
          }
    81
    10
        }
    82
    5
      } else {
    83
    5
        assert(cmd.info.pad.type == CCV_NNC_PAD_REPLICATE);
    84
    14
        for (i[0] = 0; 5i[0] < bdim[0]; i[0]++9)
    85
    9
        {
    86
    9
          float* const ap0 = ap + ccv_min(adim[0] - 1, ccv_max(0, i[0] - begin[0])) * astride[0];
    87
    9
          float* const bp0 = bp + i[0] * bstride[0];
    88
    35
          for (i[1] = 0; i[1] < bdim[1]; i[1]++26)
    89
    26
          {
    90
    26
            float* const ap1 = ap0 + ccv_min(adim[1] - 1, ccv_max(0, i[1] - begin[1])) * astride[1];
    91
    26
            float* bp1 = bp0 + i[1] * bstride[1];
    92
    106
            for (i[2] = 0; i[2] < bdim[2]; i[2]++80)
    93
    80
            {
    94
    80
              float* const ap2 = ap1 + ccv_min(adim[2] - 1, ccv_max(0, i[2] - begin[2])) * astride[2];
    95
    290
              for (x = 0; x < bdim[3]; x++210)
    96
    210
                bp1[x] = ap2[ccv_min(adim[3] - 1, ccv_max(0, x - begin[3]))];
    97
    80
              bp1 += bstride[2];
    98
    80
            }
    99
    26
          }
    100
    9
        }
    101
    5
      }
    102
    16
      return CCV_NNC_EXEC_SUCCESS;
    103
    16
    }
    104
    105
    static int _ccv_nnc_pad_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)
    106
    4
    {
    107
    4
      assert(input_size == 1);
    108
    4
      ccv_nnc_tensor_view_t* const a = (ccv_nnc_tensor_view_t*)inputs[0];
    109
    4
      ccv_nnc_tensor_view_t* const b = (ccv_nnc_tensor_view_t*)outputs[0];
    110
    4
      assert(ccv_nnc_tensor_nd(a->info.dim) <= CCV_NNC_MAX_DIM + 2);
    111
    4
      assert(ccv_nnc_tensor_nd(b->info.dim) <= CCV_NNC_MAX_DIM + 2);
    112
      // Assuming this is float 32.
    113
    4
      int adim[CCV_NNC_MAX_DIM_ALLOC];
    114
    4
      int bdim[CCV_NNC_MAX_DIM_ALLOC];
    115
    4
      ccv_nnc_tensor_view_get_dim(a, adim);
    116
    4
      ccv_nnc_tensor_view_get_dim(b, bdim);
    117
    4
      int astride[CCV_NNC_MAX_DIM_ALLOC];
    118
    4
      int bstride[CCV_NNC_MAX_DIM_ALLOC];
    119
    4
      assert(CCV_NNC_MAX_DIM == 2); // Need to change this logic for CCV_NNC_MAX_DIM == other number.
    120
    4
      ccv_nnc_tensor_view_get_stride(a, astride);
    121
    4
      ccv_nnc_tensor_view_get_stride(b, bstride);
    122
    4
      int i[CCV_NNC_MAX_DIM + 2];
    123
    4
      int x;
    124
    4
      float* const ap = a->data.f32;
    125
    4
      float* const bp = b->data.f32;
    126
    4
      const int nd = ccv_nnc_tensor_nd(a->info.dim);
    127
    4
      const int offset = CCV_NNC_MAX_DIM + 2 - nd;
    128
    4
      assert(offset >= 0);
    129
    14
      for (x = 0; 4x < nd; x++10) // We don't support negative pad.
    130
    10
        { assert(cmd.info.size.dim[x] >= 0 && cmd.info.pad.end[x] >= 0); }
    131
    4
      int begin[CCV_NNC_MAX_DIM_ALLOC];
    132
    14
      for (x = 0; x < nd; x++10)
    133
    10
        begin[x + offset] = cmd.info.size.dim[x];
    134
    10
      for (x = 0; x < offset; x++6)
    135
    6
        begin[x] = 0;
    136
      // Non-optimal case, need to do skip if needed.
    137
    9
      for (i[0] = 0; i[0] < bdim[0]; i[0]++5)
    138
    5
      {
    139
    5
        float* const ap0 = ap + (i[0] + begin[0]) * astride[0];
    140
    5
        float* const bp0 = bp + i[0] * bstride[0];
    141
    12
        for (i[1] = 0; i[1] < bdim[1]; i[1]++7)
    142
    7
        {
    143
    7
          float* const ap1 = ap0 + (i[1] + begin[1]) * astride[1];
    144
    7
          float* bp1 = bp0 + i[1] * bstride[1];
    145
    20
          for (i[2] = 0; i[2] < bdim[2]; i[2]++13)
    146
    13
          {
    147
    13
            float* const ap2 = ap1 + (i[2] + begin[2]) * astride[2];
    148
    39
            for (x = 0; x < bdim[3]; x++26)
    149
    26
              bp1[x] = ap2[x + begin[3]];
    150
    13
            bp1 += bstride[2];
    151
    13
          }
    152
    7
        }
    153
    5
      }
    154
    4
      return CCV_NNC_EXEC_SUCCESS;
    155
    4
    }
    156
    157
    REGISTER_COMMAND_BACKEND(CCV_NNC_PAD_FORWARD, CCV_NNC_BACKEND_CPU_REF)(ccv_nnc_cmd_backend_registry_t* const registry)
    158
    1
    {
    159
    1
      registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW;
    160
    1
      registry->tensor_datatypes = CCV_32F;
    161
    1
      registry->tensor_memory = CCV_TENSOR_CPU_MEMORY;
    162
    1
      registry->algorithms = 1;
    163
    1
      registry->exec = _ccv_nnc_pad_forw;
    164
    1
    }
    165
    166
    REGISTER_COMMAND_BACKEND(CCV_NNC_PAD_BACKWARD, CCV_NNC_BACKEND_CPU_REF)(ccv_nnc_cmd_backend_registry_t* const registry)
    167
    1
    {
    168
    1
      registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW;
    169
    1
      registry->tensor_datatypes = CCV_32F;
    170
    1
      registry->tensor_memory = CCV_TENSOR_CPU_MEMORY;
    171
    1
      registry->algorithms = 1;
    172
    1
      registry->exec = _ccv_nnc_pad_back;
    173
    1
    }