Coverage Report

Created: 2026-04-14 19:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/liu/actions-runner/_work/ccv/ccv/lib/nnc/cmd/swish/ccv_nnc_swish_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_swish_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
8
{
15
8
  assert(input_size == 1);
16
8
  const ccv_nnc_tensor_t* a = inputs[0];
17
8
  assert(CCV_IS_TENSOR_CONTIGUOUS(a));
18
8
  assert(output_size == 1);
19
8
  ccv_nnc_tensor_t* b = outputs[0];
20
8
  assert(CCV_IS_TENSOR_CONTIGUOUS(b));
21
8
  const int count = ccv_nnc_tensor_count(a->info);
22
8
  int i;
23
21
  for (i = 0; i < CCV_NNC_MAX_DIM_ALLOC && a->info.dim[i] > 0; 
i++13
)
24
13
  {
25
13
    assert(a->info.dim[i] == b->info.dim[i]);
26
13
  }
27
8
  const float beta = cmd.info.swish.beta;
28
8
  float* ap = a->data.f32;
29
8
  float* bp = b->data.f32;
30
3.51k
  for (i = 0; i < count; 
i++3.50k
)
31
3.50k
  {
32
3.50k
    const float x = ap[i];
33
3.50k
    const float y = 1. / (1. + exp(-beta * x));
34
3.50k
    bp[i] = x * y;
35
3.50k
  }
36
8
  return CCV_NNC_EXEC_SUCCESS;
37
8
}
38
39
static int _ccv_nnc_swish_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)
40
6
{
41
6
  assert(input_size == 3);
42
6
  const ccv_nnc_tensor_t* g = inputs[0]; // gradient
43
6
  assert(CCV_IS_TENSOR_CONTIGUOUS(g));
44
6
  const ccv_nnc_tensor_t* a = inputs[1];
45
6
  assert(CCV_IS_TENSOR_CONTIGUOUS(a));
46
6
  assert(output_size == 1);
47
6
  ccv_nnc_tensor_t* h = outputs[0];
48
6
  assert(CCV_IS_TENSOR_CONTIGUOUS(h));
49
6
  const int count = ccv_nnc_tensor_count(g->info);
50
6
  int i;
51
15
  for (i = 0; i < CCV_NNC_MAX_DIM_ALLOC && g->info.dim[i] > 0; 
i++9
)
52
9
  {
53
9
    assert(a->info.dim[i] == g->info.dim[i]);
54
9
    assert(g->info.dim[i] == h->info.dim[i]);
55
9
  }
56
6
  const float beta = cmd.info.swish.beta;
57
6
  float* ap = a->data.f32;
58
6
  float* gp = g->data.f32;
59
6
  float* hp = h->data.f32;
60
  /* d/dx (x * sigmoid(beta * x)) = sigmoid(beta * x) + beta * x * sigmoid(beta * x) * (1 - sigmoid(beta * x)). */
61
3.11k
  for (i = 0; i < count; 
i++3.10k
)
62
3.10k
  {
63
3.10k
    const float x = ap[i];
64
3.10k
    const float y = 1. / (1. + exp(-beta * x));
65
3.10k
    const float y2 = y * y;
66
3.10k
    hp[i] = gp[i] * (beta * x * (y - y2) + y);
67
3.10k
  }
68
6
  return CCV_NNC_EXEC_SUCCESS;
69
6
}
70
71
REGISTER_COMMAND_BACKEND(CCV_NNC_SWISH_FORWARD, CCV_NNC_BACKEND_CPU_REF)(ccv_nnc_cmd_backend_registry_t* const registry)
72
1
{
73
1
  registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW | CCV_TENSOR_FORMAT_CHWN;
74
1
  registry->tensor_datatypes = CCV_32F;
75
1
  registry->tensor_memory = CCV_TENSOR_CPU_MEMORY;
76
1
  registry->algorithms = 1;
77
1
  registry->exec = _ccv_nnc_swish_forw;
78
1
}
79
80
REGISTER_COMMAND_BACKEND(CCV_NNC_SWISH_BACKWARD, CCV_NNC_BACKEND_CPU_REF)(ccv_nnc_cmd_backend_registry_t* const registry)
81
1
{
82
1
  registry->tensor_formats = CCV_TENSOR_FORMAT_NHWC | CCV_TENSOR_FORMAT_NCHW | CCV_TENSOR_FORMAT_CHWN;
83
1
  registry->tensor_datatypes = CCV_32F;
84
1
  registry->tensor_memory = CCV_TENSOR_CPU_MEMORY;
85
1
  registry->algorithms = 1;
86
1
  registry->exec = _ccv_nnc_swish_back;
87
1
}