## Coverage Report

#### Created: 2026-05-04 15:30

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

    /home/liu/actions-runner/_work/ccv/ccv/lib/nnc/cmd/ew/ccv_nnc_ew.c

    Line
    Count
    Source
    1
    #include "ccv.h"
    2
    #include "nnc/ccv_nnc.h"
    3
    #include "nnc/ccv_nnc_internal.h"
    4
    5
    static int _ccv_nnc_arbitary_inplace(const ccv_nnc_cmd_param_t cmd, const int input_idx, const int input_size, const int output_idx, const int output_size)
    6
    11.6k
    {
    7
    11.6k
      return 1;
    8
    11.6k
    }
    9
    10
    static int _ccv_nnc_ewsum_forw_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    11
    126
    {
    12
    126
      if (output_size == 1 && output_bitmasks[0] == 1)
    13
    126
      {
    14
    126
        int i, j, flag = 0;
    15
    126
        int input_bitcount = 0;
    16
    252
        for (i = 0; i < input_bitmask_size; i++126)
    17
    126
        {
    18
    382
          for (j = 0; j < 64; j++256)
    19
    382
            if (input_bitmasks[i] & (uint64_t)1 << j)
    20
    256
            {
    21
    256
              if (flag)
    22
    0
                return 0;
    23
    256
            } else
    24
    126
              break;
    25
    126
          input_bitcount += j;
    26
          // Trailing zero even if it is not the end of input_bitmask_size, mark flag,
    27
          // if we encounter additional 1, return invalid.
    28
    126
          if (j < 64)
    29
    126
            flag = 1;
    30
          // Always like 1111100000, no 1110010101
    31
    7.93k
          for (; j < 64; j++7.80k)
    32
    7.80k
            if (input_bitmasks[i] & (uint64_t)1 << j)
    33
    0
              return 0;
    34
    126
        }
    35
    126
        return input_size == input_bitcount;
    36
    126
      }
    37
    0
      return 0;
    38
    126
    }
    39
    40
    static int _ccv_nnc_ewsum_back_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    41
    351
    {
    42
    351
      if (input_size >= 1 && (input_bitmasks[0] & 1u) == 1u)
    43
    271
      {
    44
    271
        int i, j, flag = 0;
    45
    271
        int output_bitcount = 0;
    46
    530
        for (i = 0; i < output_bitmask_size; i++259)
    47
    271
        {
    48
    760
          for (j = 0; j < 64; j++489)
    49
    760
            if (output_bitmasks[i] & (uint64_t)1 << j)
    50
    489
            {
    51
    489
              if (flag)
    52
    0
                return 0;
    53
    489
            } else
    54
    271
              break;
    55
    271
          output_bitcount += j;
    56
          // Trailing zero even if it is not the end of input_bitmask_size, mark flag,
    57
          // if we encounter additional 1, return invalid.
    58
    271
          if (j < 64)
    59
    271
            flag = 1;
    60
          // Always like 1111100000, no 1110010101
    61
    16.3k
          for (; j < 64; j++16.0k)
    62
    16.1k
            if (output_bitmasks[i] & (uint64_t)1 << j)
    63
    12
              return 0;
    64
    271
        }
    65
    259
        return output_size == output_bitcount;
    66
    271
      }
    67
    80
      return 0;
    68
    351
    }
    69
    70
    REGISTER_COMMAND(CCV_NNC_EWSUM_FORWARD)(ccv_nnc_cmd_registry_t* const registry)
    71
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_cudnn.cu, mps/ccv_nnc_ew_mps.m)
    72
    1
    {
    73
    1
      registry->bitmask = _ccv_nnc_ewsum_forw_bitmask;
    74
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_forward_from_inputs;
    75
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    76
    1
    }
    77
    78
    REGISTER_COMMAND(CCV_NNC_EWSUM_BACKWARD)(ccv_nnc_cmd_registry_t* const registry)
    79
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_cudnn.cu, mps/ccv_nnc_ew_mps.m)
    80
    1
    {
    81
    1
      registry->flags = CCV_NNC_CMD_ATTR_PASSTHROUGH | CCV_NNC_CMD_ATTR_NULL_IS_ONES;
    82
    1
      registry->bitmask = _ccv_nnc_ewsum_back_bitmask;
    83
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_backward_from_gradient;
    84
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    85
    1
    }
    86
    87
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWSUM_FORWARD)
    88
    #define CMD_EWSUM_FORWARD() ccv_nnc_cmd(CCV_NNC_EWSUM_FORWARD, 0, ccv_nnc_cmd_auto, 0)
    89
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWSUM_BACKWARD)
    90
    #define CMD_EWSUM_BACKWARD() ccv_nnc_cmd(CCV_NNC_EWSUM_BACKWARD, 0, ccv_nnc_cmd_auto, 0)
    91
    92
    static int _ccv_nnc_ewprod_forw_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    93
    59
    {
    94
    59
      if (output_size == 1 && output_bitmasks[0] == 1)
    95
    59
      {
    96
    59
        int i, j, flag = 0;
    97
    59
        int input_bitcount = 0;
    98
    118
        for (i = 0; i < input_bitmask_size; i++59)
    99
    59
        {
    100
    177
          for (j = 0; j < 64; j++118)
    101
    177
            if (input_bitmasks[i] & (uint64_t)1 << j)
    102
    118
            {
    103
    118
              if (flag)
    104
    0
                return 0;
    105
    118
            } else
    106
    59
              break;
    107
    59
          input_bitcount += j;
    108
          // Trailing zero even if it is not the end of input_bitmask_size, mark flag,
    109
          // if we encounter additional 1, return invalid.
    110
    59
          if (j < 64)
    111
    59
            flag = 1;
    112
          // Always like 1111100000, no 1110010101
    113
    3.71k
          for (; j < 64; j++3.65k)
    114
    3.65k
            if (input_bitmasks[i] & (uint64_t)1 << j)
    115
    0
              return 0;
    116
    59
        }
    117
    59
        return input_size == input_bitcount;
    118
    59
      }
    119
    0
      return 0;
    120
    59
    }
    121
    122
    static int _ccv_nnc_ewprod_back_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    123
    11.3k
    {
    124
    11.3k
      int i, j;
    125
    11.3k
      int input_flag = 0;
    126
    11.3k
      int input_bitcount = 0;
    127
    15.8k
      for (i = 0; i < input_bitmask_size; i++4.54k)
    128
    11.3k
      {
    129
    34.0k
        for (j = 0; j < 64; j++22.6k)
    130
    34.0k
          if (input_bitmasks[i] & (uint64_t)1 << j)
    131
    22.6k
          {
    132
    22.6k
            if (input_flag)
    133
    0
              return 0;
    134
    22.6k
          } else
    135
    11.3k
            break;
    136
    11.3k
        input_bitcount += j;
    137
    11.3k
        if (j < 64)
    138
    11.3k
          input_flag = 1;
    139
        // Always like 1111100000, no 1110010101
    140
    292k
        for (; j < 64; j++281k)
    141
    288k
          if (input_bitmasks[i] & (uint64_t)1 << j)
    142
    6.78k
            return 0;
    143
    11.3k
      }
    144
    4.54k
      int output_flag = 0;
    145
    4.54k
      int output_bitcount = 0;
    146
    9.07k
      for (i = 0; i < output_bitmask_size; i++4.53k)
    147
    4.54k
      {
    148
    13.6k
        for (j = 0; j < 64; j++9.06k)
    149
    13.6k
          if ((output_bitmasks[i] & (uint64_t)1 << j))
    150
    9.06k
          {
    151
    9.06k
            if (output_flag)
    152
    0
              return 0;
    153
    9.06k
          } else
    154
    4.54k
            break;
    155
    4.54k
        output_bitcount += j;
    156
    4.54k
        if (j < 64)
    157
    4.54k
          output_flag = 1;
    158
    285k
        for (; j < 64; j++281k)
    159
    281k
          if (output_bitmasks[i] & (uint64_t)1 << j)
    160
    2
            return 0;
    161
    4.54k
      }
    162
    4.53k
      if (output_bitcount != output_size)
    163
    10
        return 0;
    164
    4.52k
      return output_bitcount + 2 /* Gradient + Original output */ == input_bitcount;
    165
    4.53k
    }
    166
    167
    REGISTER_COMMAND(CCV_NNC_EWPROD_FORWARD)(ccv_nnc_cmd_registry_t* const registry)
    168
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c)
    169
    1
    {
    170
    1
      registry->bitmask = _ccv_nnc_ewprod_forw_bitmask;
    171
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_forward_from_inputs;
    172
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    173
    1
    }
    174
    175
    REGISTER_COMMAND(CCV_NNC_EWPROD_BACKWARD)(ccv_nnc_cmd_registry_t* const registry)
    176
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c)
    177
    1
    {
    178
    1
      registry->flags = CCV_NNC_CMD_ATTR_NULL_IS_ONES;
    179
    1
      registry->bitmask = _ccv_nnc_ewprod_back_bitmask;
    180
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_backward_from_gradient;
    181
    1
    }
    182
    183
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWPROD_FORWARD)
    184
    #define CMD_EWPROD_FORWARD() ccv_nnc_cmd(CCV_NNC_EWPROD_FORWARD, 0, ccv_nnc_cmd_auto, 0)
    185
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWPROD_BACKWARD)
    186
    #define CMD_EWPROD_BACKWARD() ccv_nnc_cmd(CCV_NNC_EWPROD_BACKWARD, 0, ccv_nnc_cmd_auto, 0)
    187
    188
    static int _ccv_nnc_ewdiv_forw_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    189
    4
    {
    190
    4
      if ((input_bitmasks[0] & 3u) == ((1u << 0) | (1u << 1)) && output_bitmasks[0] == 1u2)
    191
    2
        return 1;
    192
      // Nominator can be null (meaning 1).
    193
    2
      if ((input_bitmasks[0] & 3u) == ((0u << 0) | (1u << 1)) && output_bitmasks[0] == 1u)
    194
    2
        return 1;
    195
    0
      return 0;
    196
    2
    }
    197
    198
    static int _ccv_nnc_ewdiv_back_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    199
    72
    {
    200
    72
      if ((input_bitmasks[0] & (15u & ~((uint64_t)1u << 1))) == ((1u << 0) | (0u << 1) | (1u << 2) | (1u << 3)) && output_bitmasks[0] == ((1u << 0) | (1u << 1))21)
    201
    5
        return 1;
    202
      // We don't need to know the original output.
    203
    67
      if ((input_bitmasks[0] & (15u & ~((uint64_t)1u << 1))) == ((1u << 0) | (0u << 1) | (1u << 2) | (0u << 3)) && output_bitmasks[0] == ((1u << 0) | (0u << 1))18)
    204
    0
        return 1;
    205
    67
      if ((input_bitmasks[0] & (15u & ~((uint64_t)1u << 1))) == ((1u << 0) | (0u << 1) | (1u << 2) | (1u << 3)) && output_bitmasks[0] == ((0u << 0) | (1u << 1))16)
    206
    16
        return 1;
    207
    51
      return 0;
    208
    67
    }
    209
    210
    static void _ccv_nnc_ewdiv_tensor_auto_forw(const ccv_nnc_cmd_param_t cmd, const ccv_nnc_tensor_param_t* const inputs, const int input_size, const ccv_nnc_hint_t hint, ccv_nnc_tensor_param_t* const outputs, const int output_size)
    211
    49
    {
    212
    49
      assert(output_size >= 1);
    213
    49
      assert(input_size >= 2);
    214
    49
      int i;
    215
    98
      for (i = 0; i < output_size; i++49)
    216
    49
        outputs[i] = inputs[1];
    217
    49
    }
    218
    219
    REGISTER_COMMAND(CCV_NNC_EWDIV_FORWARD)(ccv_nnc_cmd_registry_t* const registry)
    220
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    221
    1
    {
    222
    1
      registry->flags = CCV_NNC_CMD_ATTR_NULL_IS_ONES;
    223
    1
      registry->bitmask = _ccv_nnc_ewdiv_forw_bitmask;
    224
    1
      registry->tensor_auto = _ccv_nnc_ewdiv_tensor_auto_forw;
    225
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    226
    1
    }
    227
    228
    REGISTER_COMMAND(CCV_NNC_EWDIV_BACKWARD)(ccv_nnc_cmd_registry_t* const registry)
    229
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    230
    1
    {
    231
    1
      registry->flags = CCV_NNC_CMD_ATTR_NULL_IS_ONES;
    232
    1
      registry->bitmask = _ccv_nnc_ewdiv_back_bitmask;
    233
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_backward_from_gradient;
    234
    1
    }
    235
    236
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWDIV_FORWARD)
    237
    #define CMD_EWDIV_FORWARD() ccv_nnc_cmd(CCV_NNC_EWDIV_FORWARD, 0, ccv_nnc_cmd_auto, 0)
    238
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWDIV_BACKWARD)
    239
    #define CMD_EWDIV_BACKWARD() ccv_nnc_cmd(CCV_NNC_EWDIV_BACKWARD, 0, ccv_nnc_cmd_auto, 0)
    240
    241
    static int _ccv_nnc_ewexp_forw_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    242
    2
    {
    243
    2
      if ((input_bitmasks[0] & 1u) == 1u && output_bitmasks[0] == 1u)
    244
    2
        return 1;
    245
    0
      return 0;
    246
    2
    }
    247
    248
    static int _ccv_nnc_ewexp_back_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    249
    54
    {
    250
      // We don't care about the original input.
    251
    54
      if ((input_bitmasks[0] & (7u & ~((uint64_t)1u << 1))) == ((1u << 0) | (0u << 1) | (1u << 2)) && output_bitmasks[0] == 1u18)
    252
    18
        return 1;
    253
    36
      return 0;
    254
    54
    }
    255
    256
    REGISTER_COMMAND(CCV_NNC_EWEXP_FORWARD)(ccv_nnc_cmd_registry_t* const registry)
    257
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    258
    1
    {
    259
    1
      registry->bitmask = _ccv_nnc_ewexp_forw_bitmask;
    260
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_forward_from_inputs;
    261
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    262
    1
    }
    263
    264
    REGISTER_COMMAND(CCV_NNC_EWEXP_BACKWARD)(ccv_nnc_cmd_registry_t* const registry)
    265
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    266
    1
    {
    267
    1
      registry->flags = CCV_NNC_CMD_ATTR_NULL_IS_ONES;
    268
    1
      registry->bitmask = _ccv_nnc_ewexp_back_bitmask;
    269
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_backward_from_gradient;
    270
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    271
    1
    }
    272
    273
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWEXP_FORWARD)
    274
    #define CMD_EWEXP_FORWARD() ccv_nnc_cmd(CCV_NNC_EWEXP_FORWARD, 0, ccv_nnc_cmd_auto, 0)
    275
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWEXP_BACKWARD)
    276
    #define CMD_EWEXP_BACKWARD() ccv_nnc_cmd(CCV_NNC_EWEXP_BACKWARD, 0, ccv_nnc_cmd_auto, 0)
    277
    278
    static int _ccv_nnc_ewsoftplus_forw_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    279
    2
    {
    280
    2
      if ((input_bitmasks[0] & 1u) == 1u && output_bitmasks[0] == 1u)
    281
    2
        return 1;
    282
    0
      return 0;
    283
    2
    }
    284
    285
    static int _ccv_nnc_ewsoftplus_back_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    286
    0
    {
    287
      // We only care about the original input.
    288
    0
      if ((input_bitmasks[0] & (7u & ~((uint64_t)1u << 0) & ~((uint64_t)1u << 2))) == ((0u << 0) | (1u << 1) | (0u << 2)) && output_bitmasks[0] == 1u)
    289
    0
        return 1;
    290
    0
      return 0;
    291
    0
    }
    292
    293
    REGISTER_COMMAND(CCV_NNC_EWSOFTPLUS_FORWARD)(ccv_nnc_cmd_registry_t* const registry)
    294
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    295
    1
    {
    296
    1
      registry->bitmask = _ccv_nnc_ewsoftplus_forw_bitmask;
    297
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_forward_from_inputs;
    298
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    299
    1
    }
    300
    301
    REGISTER_COMMAND(CCV_NNC_EWSOFTPLUS_BACKWARD)(ccv_nnc_cmd_registry_t* const registry)
    302
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu)
    303
    1
    {
    304
    1
      registry->flags = CCV_NNC_CMD_ATTR_NULL_IS_ONES;
    305
    1
      registry->bitmask = _ccv_nnc_ewsoftplus_back_bitmask;
    306
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_backward_from_gradient;
    307
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    308
    1
    }
    309
    310
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWSOFTPLUS_FORWARD)
    311
    #define CMD_EWSOFTPLUS_FORWARD() ccv_nnc_cmd(CCV_NNC_EWSOFTPLUS_FORWARD, 0, ccv_nnc_cmd_auto, 0)
    312
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWSOFTPLUS_BACKWARD)
    313
    #define CMD_EWSOFTPLUS_BACKWARD() ccv_nnc_cmd(CCV_NNC_EWSOFTPLUS_BACKWARD, 0, ccv_nnc_cmd_auto, 0)
    314
    315
    static int _ccv_nnc_ewpow_forw_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    316
    2
    {
    317
    2
      if ((input_bitmasks[0] & 1u) == 1u && output_bitmasks[0] == 1u)
    318
    2
        return 1;
    319
    0
      return 0;
    320
    2
    }
    321
    322
    static int _ccv_nnc_ewpow_back_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    323
    9
    {
    324
      // We only care about the original input.
    325
    9
      if ((input_bitmasks[0] & (7u & ~((uint64_t)1u << 0) & ~((uint64_t)1u << 2))) == ((0u << 0) | (1u << 1) | (0u << 2)) && output_bitmasks[0] == 1u5)
    326
    5
        return 1;
    327
    4
      return 0;
    328
    9
    }
    329
    330
    static void _ccv_nnc_ewpow_tensor_auto_forw(const ccv_nnc_cmd_param_t cmd, const ccv_nnc_tensor_param_t* const inputs, const int input_size, const ccv_nnc_hint_t hint, ccv_nnc_tensor_param_t* const outputs, const int output_size)
    331
    8
    {
    332
    8
      assert(output_size >= 1);
    333
    8
      assert(input_size >= 1);
    334
    8
      int i;
    335
    16
      for (i = 0; i < output_size; i++8)
    336
    8
        outputs[i] = inputs[0];
    337
    8
    }
    338
    339
    REGISTER_COMMAND(CCV_NNC_EWPOW_FORWARD)(ccv_nnc_cmd_registry_t* const registry)
    340
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    341
    1
    {
    342
    1
      registry->bitmask = _ccv_nnc_ewpow_forw_bitmask;
    343
    1
      registry->tensor_auto = _ccv_nnc_ewpow_tensor_auto_forw;
    344
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    345
    1
    }
    346
    347
    REGISTER_COMMAND(CCV_NNC_EWPOW_BACKWARD)(ccv_nnc_cmd_registry_t* const registry)
    348
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu)
    349
    1
    {
    350
    1
      registry->flags = CCV_NNC_CMD_ATTR_NULL_IS_ONES;
    351
    1
      registry->bitmask = _ccv_nnc_ewpow_back_bitmask;
    352
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_backward_from_gradient;
    353
    1
    }
    354
    355
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWPOW_FORWARD)
    356
    #define CMD_EWPOW_FORWARD(_exponent) ccv_nnc_cmd(CCV_NNC_EWPOW_FORWARD, 0, ((ccv_nnc_cmd_param_t){.size={.dim={1,1,1}},.pow={.exponent=_exponent}}), 0)
    357
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWPOW_BACKWARD)
    358
    #define CMD_EWPOW_BACKWARD(_exponent) ccv_nnc_cmd(CCV_NNC_EWPOW_BACKWARD, 0, ((ccv_nnc_cmd_param_t){.size={.dim={1,1,1}},.pow={.exponent=_exponent}}), 0)
    359
    360
    static int _ccv_nnc_ewlog_forw_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    361
    2
    {
    362
    2
      if ((input_bitmasks[0] & 1u) == 1u && output_bitmasks[0] == 1u)
    363
    2
        return 1;
    364
    0
      return 0;
    365
    2
    }
    366
    367
    static int _ccv_nnc_ewlog_back_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    368
    1.32k
    {
    369
      // We don't care about the original output.
    370
    1.32k
      if ((input_bitmasks[0] & 3u) == 3u && output_bitmasks[0] == 1u442)
    371
    442
        return 1;
    372
    878
      return 0;
    373
    1.32k
    }
    374
    375
    REGISTER_COMMAND(CCV_NNC_EWLOG_FORWARD)(ccv_nnc_cmd_registry_t* const registry)
    376
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    377
    1
    {
    378
    1
      registry->bitmask = _ccv_nnc_ewlog_forw_bitmask;
    379
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_forward_from_inputs;
    380
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    381
    1
    }
    382
    383
    REGISTER_COMMAND(CCV_NNC_EWLOG_BACKWARD)(ccv_nnc_cmd_registry_t* const registry)
    384
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    385
    1
    {
    386
    1
      registry->flags = CCV_NNC_CMD_ATTR_NULL_IS_ONES;
    387
    1
      registry->bitmask = _ccv_nnc_ewlog_back_bitmask;
    388
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_backward_from_gradient;
    389
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    390
    1
    }
    391
    392
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWLOG_FORWARD)
    393
    #define CMD_EWLOG_FORWARD() ccv_nnc_cmd(CCV_NNC_EWLOG_FORWARD, 0, ccv_nnc_cmd_auto, 0)
    394
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWLOG_BACKWARD)
    395
    #define CMD_EWLOG_BACKWARD() ccv_nnc_cmd(CCV_NNC_EWLOG_BACKWARD, 0, ccv_nnc_cmd_auto, 0)
    396
    397
    static int _ccv_nnc_ewsqrt_forw_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    398
    0
    {
    399
    0
      if ((input_bitmasks[0] & 1u) == 1u && output_bitmasks[0] == 1u)
    400
    0
        return 1;
    401
    0
      return 0;
    402
    0
    }
    403
    404
    static int _ccv_nnc_ewsqrt_back_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    405
    6
    {
    406
      // We don't care about the original input.
    407
    6
      if ((input_bitmasks[0] & (7u & ~((uint64_t)1u << 1))) == ((1u << 0) | (0u << 1) | (1u << 2)) && output_bitmasks[0] == 1u2)
    408
    2
        return 1;
    409
    4
      return 0;
    410
    6
    }
    411
    412
    REGISTER_COMMAND(CCV_NNC_EWSQRT_FORWARD)(ccv_nnc_cmd_registry_t* const registry)
    413
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    414
    1
    {
    415
    1
      registry->bitmask = _ccv_nnc_ewsqrt_forw_bitmask;
    416
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_forward_from_inputs;
    417
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    418
    1
    }
    419
    420
    REGISTER_COMMAND(CCV_NNC_EWSQRT_BACKWARD)(ccv_nnc_cmd_registry_t* const registry)
    421
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    422
    1
    {
    423
    1
      registry->flags = CCV_NNC_CMD_ATTR_NULL_IS_ONES;
    424
    1
      registry->bitmask = _ccv_nnc_ewsqrt_back_bitmask;
    425
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_backward_from_gradient;
    426
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    427
    1
    }
    428
    429
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWSQRT_FORWARD)
    430
    #define CMD_EWSQRT_FORWARD() ccv_nnc_cmd(CCV_NNC_EWSQRT_FORWARD, 0, ccv_nnc_cmd_auto, 0)
    431
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWSQRT_BACKWARD)
    432
    #define CMD_EWSQRT_BACKWARD() ccv_nnc_cmd(CCV_NNC_EWSQRT_BACKWARD, 0, ccv_nnc_cmd_auto, 0)
    433
    434
    static int _ccv_nnc_ewsin_forw_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    435
    2
    {
    436
    2
      if ((input_bitmasks[0] & 1u) == 1u && output_bitmasks[0] == 1u)
    437
    2
        return 1;
    438
    0
      return 0;
    439
    2
    }
    440
    441
    static int _ccv_nnc_ewsin_back_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    442
    9
    {
    443
      // We only care about the original input.
    444
    9
      if ((input_bitmasks[0] & (7u & ~((uint64_t)1u << 0) & ~((uint64_t)1u << 2))) == ((0u << 0) | (1u << 1) | (0u << 2)) && output_bitmasks[0] == 1u5)
    445
    5
        return 1;
    446
    4
      return 0;
    447
    9
    }
    448
    449
    REGISTER_COMMAND(CCV_NNC_EWSIN_FORWARD)(ccv_nnc_cmd_registry_t* const registry)
    450
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    451
    1
    {
    452
    1
      registry->bitmask = _ccv_nnc_ewsin_forw_bitmask;
    453
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_forward_from_inputs;
    454
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    455
    1
    }
    456
    457
    REGISTER_COMMAND(CCV_NNC_EWSIN_BACKWARD)(ccv_nnc_cmd_registry_t* const registry)
    458
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu)
    459
    1
    {
    460
    1
      registry->flags = CCV_NNC_CMD_ATTR_NULL_IS_ONES;
    461
    1
      registry->bitmask = _ccv_nnc_ewsin_back_bitmask;
    462
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_backward_from_gradient;
    463
    1
    }
    464
    465
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWSIN_FORWARD)
    466
    #define CMD_EWSIN_FORWARD() ccv_nnc_cmd(CCV_NNC_EWSIN_FORWARD, 0, ccv_nnc_cmd_auto, 0)
    467
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWSIN_BACKWARD)
    468
    #define CMD_EWSIN_BACKWARD() ccv_nnc_cmd(CCV_NNC_EWSIN_BACKWARD, 0, ccv_nnc_cmd_auto, 0)
    469
    470
    static int _ccv_nnc_ewcos_forw_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    471
    2
    {
    472
    2
      if ((input_bitmasks[0] & 1u) == 1u && output_bitmasks[0] == 1u)
    473
    2
        return 1;
    474
    0
      return 0;
    475
    2
    }
    476
    477
    static int _ccv_nnc_ewcos_back_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    478
    9
    {
    479
      // We only care about the original input.
    480
    9
      if ((input_bitmasks[0] & (7u & ~((uint64_t)1u << 0) & ~((uint64_t)1u << 2))) == ((0u << 0) | (1u << 1) | (0u << 2)) && output_bitmasks[0] == 1u5)
    481
    5
        return 1;
    482
    4
      return 0;
    483
    9
    }
    484
    485
    REGISTER_COMMAND(CCV_NNC_EWCOS_FORWARD)(ccv_nnc_cmd_registry_t* const registry)
    486
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    487
    1
    {
    488
    1
      registry->bitmask = _ccv_nnc_ewcos_forw_bitmask;
    489
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_forward_from_inputs;
    490
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    491
    1
    }
    492
    493
    REGISTER_COMMAND(CCV_NNC_EWCOS_BACKWARD)(ccv_nnc_cmd_registry_t* const registry)
    494
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu)
    495
    1
    {
    496
    1
      registry->flags = CCV_NNC_CMD_ATTR_NULL_IS_ONES;
    497
    1
      registry->bitmask = _ccv_nnc_ewcos_back_bitmask;
    498
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_backward_from_gradient;
    499
    1
    }
    500
    501
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWCOS_FORWARD)
    502
    #define CMD_EWCOS_FORWARD() ccv_nnc_cmd(CCV_NNC_EWCOS_FORWARD, 0, ccv_nnc_cmd_auto, 0)
    503
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWCOS_BACKWARD)
    504
    #define CMD_EWCOS_BACKWARD() ccv_nnc_cmd(CCV_NNC_EWCOS_BACKWARD, 0, ccv_nnc_cmd_auto, 0)
    505
    506
    static int _ccv_nnc_ewabs_forw_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    507
    0
    {
    508
    0
      if ((input_bitmasks[0] & 1u) == 1u && output_bitmasks[0] == 1u)
    509
    0
        return 1;
    510
    0
      return 0;
    511
    0
    }
    512
    513
    static int _ccv_nnc_ewabs_back_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    514
    0
    {
    515
      // We only care about the original input.
    516
    0
      if ((input_bitmasks[0] & (7u & ~((uint64_t)1u << 2))) == ((1u << 0) | (1u << 1) | (0u << 2)) && output_bitmasks[0] == 1u)
    517
    0
        return 1;
    518
    0
      return 0;
    519
    0
    }
    520
    521
    REGISTER_COMMAND(CCV_NNC_EWABS_FORWARD)(ccv_nnc_cmd_registry_t* const registry)
    522
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    523
    1
    {
    524
    1
      registry->bitmask = _ccv_nnc_ewabs_forw_bitmask;
    525
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_forward_from_inputs;
    526
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    527
    1
    }
    528
    529
    REGISTER_COMMAND(CCV_NNC_EWABS_BACKWARD)(ccv_nnc_cmd_registry_t* const registry)
    530
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    531
    1
    {
    532
    1
      registry->bitmask = _ccv_nnc_ewabs_back_bitmask;
    533
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_backward_from_gradient;
    534
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    535
    1
    }
    536
    537
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWABS_FORWARD)
    538
    #define CMD_EWABS_FORWARD() ccv_nnc_cmd(CCV_NNC_EWABS_FORWARD, 0, ccv_nnc_cmd_auto, 0)
    539
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_EWABS_BACKWARD)
    540
    #define CMD_EWABS_BACKWARD() ccv_nnc_cmd(CCV_NNC_EWABS_BACKWARD, 0, ccv_nnc_cmd_auto, 0)
    541
    542
    static int _ccv_nnc_clamp_forw_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    543
    0
    {
    544
    0
      if ((input_bitmasks[0] & 1u) == 1u && output_bitmasks[0] == 1u)
    545
    0
        return 1;
    546
    0
      return 0;
    547
    0
    }
    548
    549
    static int _ccv_nnc_clamp_back_bitmask(const ccv_nnc_cmd_param_t cmd, const int input_size, const int output_size, const uint64_t* const input_bitmasks, const int input_bitmask_size, const uint64_t* const output_bitmasks, const int output_bitmask_size)
    550
    0
    {
    551
      // We don't care about the original input.
    552
    0
      if ((input_bitmasks[0] & (7u & ~((uint64_t)1u << 1))) == ((1u << 0) | (0u << 1) | (1u << 2)) && output_bitmasks[0] == 1u)
    553
    0
        return 1;
    554
    0
      return 0;
    555
    0
    }
    556
    557
    REGISTER_COMMAND(CCV_NNC_CLAMP_FORWARD)(ccv_nnc_cmd_registry_t* const registry)
    558
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    559
    1
    {
    560
    1
      registry->bitmask = _ccv_nnc_clamp_forw_bitmask;
    561
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_forward_from_inputs;
    562
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    563
    1
    }
    564
    565
    REGISTER_COMMAND(CCV_NNC_CLAMP_BACKWARD)(ccv_nnc_cmd_registry_t* const registry)
    566
      FIND_BACKEND(ccv_nnc_ew_cpu_ref.c, gpu/ccv_nnc_ew_gpu_ref.cu, mps/ccv_nnc_ew_mps.m)
    567
    1
    {
    568
    1
      registry->flags = CCV_NNC_CMD_ATTR_NULL_IS_ONES;
    569
    1
      registry->bitmask = _ccv_nnc_clamp_back_bitmask;
    570
    1
      registry->tensor_auto = ccv_nnc_hint_tensor_auto_backward_from_gradient;
    571
    1
      registry->allow_inplace = _ccv_nnc_arbitary_inplace;
    572
    1
    }
    573
    574
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_CLAMP_FORWARD)
    575
    #define CMD_CLAMP_FORWARD(_min, _max) ccv_nnc_cmd(CCV_NNC_CLAMP_FORWARD, 0, (ccv_nnc_cmd_param_t){.size={.dim={1,1,1}},.clamp={.min=_min,.max=_max}}, 0)
    576
    //@REGISTER_EASY_COMMAND_MACRO(CCV_NNC_CLAMP_BACKWARD)
    577
    #define CMD_CLAMP_BACKWARD(_min, _max) ccv_nnc_cmd(CCV_NNC_CLAMP_BACKWARD, 0, (ccv_nnc_cmd_param_t){.size={.dim={1,1,1}},.clamp={.min=_min,.max=_max}}, 0)