Coverage Report

Created: 2025-05-09 10:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/liu/actions-runner/_work/ccv/ccv/test/unit/nnc/scatter_add.tests.c
Line
Count
Source
1
#include "case.h"
2
#include "ccv_case.h"
3
#include "ccv_nnc_case.h"
4
#include <ccv.h>
5
#include <nnc/ccv_nnc.h>
6
#include <nnc/ccv_nnc_easy.h>
7
8
TEST_SETUP()
9
{
10
  ccv_nnc_init();
11
}
12
13
TEST_CASE("scatter add a tensor")
14
1
{
15
1
  float bp[] = {
16
1
    1, 2,
17
1
    2, 3,
18
1
  };
19
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 3, 2), 0);
20
1
  int ip[] = {1, 1};
21
1
  ccv_nnc_tensor_t* const indices = ccv_nnc_tensor_new(ip, CPU_TENSOR_NHWC(32S, 2), 0);
22
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(bp, CPU_TENSOR_NHWC(32F, 2, 2), 0);
23
1
  ccv_nnc_cmd_exec(CMD_SCATTER_ADD_FORWARD(3), ccv_nnc_no_hint, 0, TENSOR_LIST(b, indices), TENSOR_LIST(a), 0);
24
1
  float atp[] = {
25
1
    0, 0,
26
1
    3, 5,
27
1
    0, 0,
28
1
  };
29
1
  ccv_nnc_tensor_t const at = ccv_nnc_tensor(atp, CPU_TENSOR_NHWC(32F, 3, 2), 0);
30
1
  REQUIRE_TENSOR_EQ(a, &at, "should be equal");
31
1
  ccv_nnc_tensor_free(a);
32
1
  ccv_nnc_tensor_free(indices);
33
1
  ccv_nnc_tensor_free(b);
34
1
}
35
36
TEST_CASE("scatter add a 1d tensor")
37
1
{
38
1
  float bp[] = {
39
1
    4, 3, 5,
40
1
  };
41
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5), 0);
42
1
  int ip[] = {3, 2, 4};
43
1
  ccv_nnc_tensor_t* const indices = ccv_nnc_tensor_new(ip, CPU_TENSOR_NHWC(32S, 3), 0);
44
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(bp, CPU_TENSOR_NHWC(32F, 3), 0);
45
1
  ccv_nnc_cmd_exec(CMD_SCATTER_ADD_FORWARD(5), ccv_nnc_no_hint, 0, TENSOR_LIST(b, indices), TENSOR_LIST(a), 0);
46
1
  float atp[] = {
47
1
    0, 0, 3, 4, 5
48
1
  };
49
1
  ccv_nnc_tensor_t const at = ccv_nnc_tensor(atp, CPU_TENSOR_NHWC(32F, 5), 0);
50
1
  REQUIRE_TENSOR_EQ(a, &at, "should be equal");
51
1
  ccv_nnc_tensor_free(a);
52
1
  ccv_nnc_tensor_free(indices);
53
1
  ccv_nnc_tensor_free(b);
54
1
}
55
56
TEST_CASE("scatter add a tensor view")
57
1
{
58
1
  float bp[] = {
59
1
    0, 3, 4, 0,
60
1
    0, 1, 5, 0,
61
1
  };
62
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 3, 4), 0);
63
1
  int i;
64
13
  for (i = 0; i < 3 * 4; 
i++12
)
65
12
    a->data.f32[i] = i;
66
1
  ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 3, 2), DIM_ALLOC(0, 1), DIM_ALLOC(4, 1));
67
1
  int ip[] = {1, 1};
68
1
  ccv_nnc_tensor_t* const indices = ccv_nnc_tensor_new(ip, CPU_TENSOR_NHWC(32S, 2), 0);
69
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(bp, CPU_TENSOR_NHWC(32F, 2, 4), 0);
70
1
  ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2), DIM_ALLOC(0, 1), DIM_ALLOC(4, 1));
71
1
  ccv_nnc_cmd_exec(CMD_SCATTER_ADD_FORWARD(3), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)bv, indices), TENSOR_LIST((ccv_nnc_tensor_t*)av), 0);
72
1
  float atp[] = {
73
1
    0, 0, 0, 3,
74
1
    4, 4, 9, 7,
75
1
    8, 0, 0, 11,
76
1
  };
77
1
  ccv_nnc_tensor_t const at = ccv_nnc_tensor(atp, CPU_TENSOR_NHWC(32F, 3, 4), 0);
78
1
  REQUIRE_TENSOR_EQ(a, &at, "should be equal");
79
1
  ccv_nnc_tensor_free(a);
80
1
  ccv_nnc_tensor_view_free(av);
81
1
  ccv_nnc_tensor_free(indices);
82
1
  ccv_nnc_tensor_free(b);
83
1
  ccv_nnc_tensor_view_free(bv);
84
1
}
85
86
TEST_CASE("backward scatter add a tensor")
87
1
{
88
1
  float ap[] = {
89
1
    1, 2,
90
1
    2, 3,
91
1
    3, 4,
92
1
  };
93
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(ap, CPU_TENSOR_NHWC(32F, 3, 2), 0);
94
1
  int ip[] = {1, 1};
95
1
  ccv_nnc_tensor_t* const indices = ccv_nnc_tensor_new(ip, CPU_TENSOR_NHWC(32S, 2), 0);
96
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2), 0);
97
1
  ccv_nnc_cmd_exec(CMD_SCATTER_ADD_BACKWARD(3), ccv_nnc_no_hint, 0, TENSOR_LIST(a, 0, indices), TENSOR_LIST(b), 0);
98
1
  float btp[] = {
99
1
    2, 3,
100
1
    2, 3,
101
1
  };
102
1
  ccv_nnc_tensor_t const bt = ccv_nnc_tensor(btp, CPU_TENSOR_NHWC(32F, 2, 2), 0);
103
1
  REQUIRE_TENSOR_EQ(b, &bt, "should be equal");
104
1
  ccv_nnc_tensor_free(a);
105
1
  ccv_nnc_tensor_free(indices);
106
1
  ccv_nnc_tensor_free(b);
107
1
}
108
109
TEST_CASE("backward scatter add a 1d tensor")
110
1
{
111
1
  float ap[] = {
112
1
    1, 2, 3, 4, 5
113
1
  };
114
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(ap, CPU_TENSOR_NHWC(32F, 5), 0);
115
1
  int ip[] = {3, 2, 4};
116
1
  ccv_nnc_tensor_t* const indices = ccv_nnc_tensor_new(ip, CPU_TENSOR_NHWC(32S, 3), 0);
117
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 3), 0);
118
1
  ccv_nnc_cmd_exec(CMD_SCATTER_ADD_BACKWARD(5), ccv_nnc_no_hint, 0, TENSOR_LIST(a, 0, indices), TENSOR_LIST(b), 0);
119
1
  float btp[] = {
120
1
    4, 3, 5
121
1
  };
122
1
  ccv_nnc_tensor_t const bt = ccv_nnc_tensor(btp, CPU_TENSOR_NHWC(32F, 3), 0);
123
1
  REQUIRE_TENSOR_EQ(b, &bt, "should be equal");
124
1
  ccv_nnc_tensor_free(a);
125
1
  ccv_nnc_tensor_free(indices);
126
1
  ccv_nnc_tensor_free(b);
127
1
}
128
129
TEST_CASE("backward scatter add a tensor view")
130
1
{
131
1
  float ap[] = {
132
1
    1, 2, 3, 4,
133
1
    2, 3, 4, 5,
134
1
    3, 4, 5, 6,
135
1
  };
136
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(ap, CPU_TENSOR_NHWC(32F, 3, 4), 0);
137
1
  ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 3, 2), DIM_ALLOC(0, 1), DIM_ALLOC(4, 1));
138
1
  int ip[] = {1, 1};
139
1
  ccv_nnc_tensor_t* const indices = ccv_nnc_tensor_new(ip, CPU_TENSOR_NHWC(32S, 2), 0);
140
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 4), 0);
141
1
  memset(b->data.f32, 0, 2 * 4 * sizeof(float));
142
1
  ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2), DIM_ALLOC(0, 1), DIM_ALLOC(4, 1));
143
1
  ccv_nnc_cmd_exec(CMD_SCATTER_ADD_BACKWARD(3), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)av, 0, indices), TENSOR_LIST((ccv_nnc_tensor_t*)bv), 0);
144
1
  float btp[] = {
145
1
    0, 3, 4, 0,
146
1
    0, 3, 4, 0,
147
1
  };
148
1
  ccv_nnc_tensor_t const bt = ccv_nnc_tensor(btp, CPU_TENSOR_NHWC(32F, 2, 4), 0);
149
1
  REQUIRE_TENSOR_EQ(b, &bt, "should be equal");
150
1
  ccv_nnc_tensor_free(a);
151
1
  ccv_nnc_tensor_view_free(av);
152
1
  ccv_nnc_tensor_free(indices);
153
1
  ccv_nnc_tensor_free(b);
154
1
  ccv_nnc_tensor_view_free(bv);
155
1
}
156
157
TEST_CASE("scatter add a tensor with model")
158
1
{
159
1
  float bp[] = {
160
1
    1, 2,
161
1
    2, 3,
162
1
  };
163
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 3, 2), 0);
164
1
  int ip[] = {1, 1};
165
1
  ccv_nnc_tensor_t* const indices = ccv_nnc_tensor_new(ip, CPU_TENSOR_NHWC(32S, 2), 0);
166
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(bp, CPU_TENSOR_NHWC(32F, 2, 2), 0);
167
1
  ccv_cnnp_model_t* const scatter_add = ccv_cnnp_scatter_add(3, "scatter_add");
168
1
  ccv_cnnp_model_compile(scatter_add, TENSOR_PARAM_LIST(b->info, indices->info), CMD_NOOP(), CMD_NOOP());
169
1
  ccv_cnnp_model_evaluate(scatter_add, (ccv_cnnp_evaluate_param_t){
170
1
    .requires_grad = 0,
171
1
  }, TENSOR_LIST(b, indices), TENSOR_LIST(a), 0, 0);
172
1
  float atp[] = {
173
1
    0, 0,
174
1
    3, 5,
175
1
    0, 0,
176
1
  };
177
1
  ccv_nnc_tensor_t const at = ccv_nnc_tensor(atp, CPU_TENSOR_NHWC(32F, 3, 2), 0);
178
1
  REQUIRE_TENSOR_EQ(a, &at, "should be equal");
179
1
  ccv_nnc_tensor_free(a);
180
1
  ccv_nnc_tensor_free(indices);
181
1
  ccv_nnc_tensor_free(b);
182
1
  ccv_cnnp_model_free(scatter_add);
183
1
}
184
185
#include "case_main.h"