Coverage Report

Created: 2021-04-06 03:49

/home/liu/buildslave/linux-x64-runtests/build/test/unit/nnc/compare.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
#include "3rdparty/dsfmt/dSFMT.h"
8
9
TEST_SETUP()
10
{
11
  ccv_nnc_init();
12
}
13
14
TEST_CASE("min of two tensors")
15
1
{
16
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
17
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
18
1
  ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
19
1
  int i;
20
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
21
12
    a->data.f32[i] = i;
22
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
23
12
    b->data.f32[i] = i - 1;
24
1
  ccv_nnc_cmd_exec(CMD_MIN_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(a, b), TENSOR_LIST(c), 0);
25
1
  REQUIRE_TENSOR_EQ(b, c, "c should be the minimal of the two");
26
1
  ccv_nnc_tensor_free(a);
27
1
  ccv_nnc_tensor_free(b);
28
1
  ccv_nnc_tensor_free(c);
29
1
}
30
31
TEST_CASE("min of two tensor views")
32
1
{
33
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0);
34
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0);
35
1
  ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
36
1
  int i;
37
49
  for (i = 0; i < 4 * 4 * 3; 
i++48
)
38
48
    a->data.f32[i] = i;
39
49
  for (i = 0; i < 4 * 4 * 3; 
i++48
)
40
48
    b->data.f32[i] = i - 1;
41
1
  ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4, 4, 3));
42
1
  ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4, 4, 3));
43
1
  ccv_nnc_cmd_exec(CMD_MIN_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)av, (ccv_nnc_tensor_t*)bv), TENSOR_LIST(c), 0);
44
1
  ccv_nnc_tensor_t* const bvt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
45
1
  ccv_nnc_cmd_exec(CMD_DATATYPE_CONVERSION_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)bv), TENSOR_LIST(bvt), 0);
46
1
  REQUIRE_TENSOR_EQ(bvt, c, "c should be the minimal of the two");
47
1
  ccv_nnc_tensor_free(a);
48
1
  ccv_nnc_tensor_free(b);
49
1
  ccv_nnc_tensor_free(c);
50
1
  ccv_nnc_tensor_free(bvt);
51
1
  ccv_nnc_tensor_view_free(av);
52
1
  ccv_nnc_tensor_view_free(bv);
53
1
}
54
55
TEST_CASE("min of two tensors backward")
56
1
{
57
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
58
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
59
1
  ccv_nnc_tensor_t* const g = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
60
1
  ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
61
1
  ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
62
1
  ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
63
1
  ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
64
1
  int i;
65
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
66
12
    a->data.f32[i] = i;
67
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
68
12
    b->data.f32[i] = i < 3 ? 
i3
:
i - 19
;
69
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
70
12
    g->data.f32[i] = -1;
71
1
  ccv_nnc_cmd_exec(CMD_MIN_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(g, a, b), TENSOR_LIST(ha, hb), 0);
72
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
73
12
    hat->data.f32[i] = i < 3 ? 
-13
:
09
;
74
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
75
12
    hbt->data.f32[i] = -1;
76
1
  REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3");
77
1
  REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients");
78
1
  ccv_nnc_tensor_free(a);
79
1
  ccv_nnc_tensor_free(b);
80
1
  ccv_nnc_tensor_free(g);
81
1
  ccv_nnc_tensor_free(ha);
82
1
  ccv_nnc_tensor_free(hb);
83
1
  ccv_nnc_tensor_free(hat);
84
1
  ccv_nnc_tensor_free(hbt);
85
1
}
86
87
TEST_CASE("min of two tensors backward with null")
88
1
{
89
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
90
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
91
1
  ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
92
1
  ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
93
1
  ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
94
1
  ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
95
1
  int i;
96
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
97
12
    a->data.f32[i] = i;
98
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
99
12
    b->data.f32[i] = i < 3 ? 
i3
:
i - 19
;
100
1
  ccv_nnc_cmd_exec(CMD_MIN_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(0, a, b), TENSOR_LIST(ha, hb), 0);
101
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
102
12
    hat->data.f32[i] = i < 3 ? 
13
:
09
;
103
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
104
12
    hbt->data.f32[i] = 1;
105
1
  REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3");
106
1
  REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients");
107
1
  ccv_nnc_tensor_free(a);
108
1
  ccv_nnc_tensor_free(b);
109
1
  ccv_nnc_tensor_free(ha);
110
1
  ccv_nnc_tensor_free(hb);
111
1
  ccv_nnc_tensor_free(hat);
112
1
  ccv_nnc_tensor_free(hbt);
113
1
}
114
115
TEST_CASE("min of two tensor views backward")
116
1
{
117
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0);
118
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0);
119
1
  ccv_nnc_tensor_t* const g = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
120
1
  ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
121
1
  ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
122
1
  ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
123
1
  ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
124
1
  int i;
125
49
  for (i = 0; i < 4 * 4 * 3; 
i++48
)
126
48
    a->data.f32[i] = i;
127
49
  for (i = 0; i < 4 * 4 * 3; 
i++48
)
128
48
    b->data.f32[i] = i < 3 ? 
i3
:
i - 145
;
129
1
  ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4, 4, 3));
130
1
  ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4, 4, 3));
131
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
132
12
    g->data.f32[i] = -1;
133
1
  ccv_nnc_cmd_exec(CMD_MIN_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(g, (ccv_nnc_tensor_t*)av, (ccv_nnc_tensor_t*)bv), TENSOR_LIST(ha, hb), 0);
134
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
135
12
    hat->data.f32[i] = i < 3 ? 
-13
:
09
;
136
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
137
12
    hbt->data.f32[i] = -1;
138
1
  REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3");
139
1
  REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients");
140
1
  ccv_nnc_tensor_free(a);
141
1
  ccv_nnc_tensor_free(b);
142
1
  ccv_nnc_tensor_view_free(av);
143
1
  ccv_nnc_tensor_view_free(bv);
144
1
  ccv_nnc_tensor_free(g);
145
1
  ccv_nnc_tensor_free(ha);
146
1
  ccv_nnc_tensor_free(hb);
147
1
  ccv_nnc_tensor_free(hat);
148
1
  ccv_nnc_tensor_free(hbt);
149
1
}
150
151
TEST_CASE("min of two tensor views backward with null")
152
1
{
153
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0);
154
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0);
155
1
  ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
156
1
  ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
157
1
  ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
158
1
  ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
159
1
  int i;
160
49
  for (i = 0; i < 4 * 4 * 3; 
i++48
)
161
48
    a->data.f32[i] = i;
162
49
  for (i = 0; i < 4 * 4 * 3; 
i++48
)
163
48
    b->data.f32[i] = i < 3 ? 
i3
:
i - 145
;
164
1
  ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4, 4, 3));
165
1
  ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4, 4, 3));
166
1
  ccv_nnc_cmd_exec(CMD_MIN_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(0, (ccv_nnc_tensor_t*)av, (ccv_nnc_tensor_t*)bv), TENSOR_LIST(ha, hb), 0);
167
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
168
12
    hat->data.f32[i] = i < 3 ? 
13
:
09
;
169
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
170
12
    hbt->data.f32[i] = 1;
171
1
  REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3");
172
1
  REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients");
173
1
  ccv_nnc_tensor_free(a);
174
1
  ccv_nnc_tensor_free(b);
175
1
  ccv_nnc_tensor_view_free(av);
176
1
  ccv_nnc_tensor_view_free(bv);
177
1
  ccv_nnc_tensor_free(ha);
178
1
  ccv_nnc_tensor_free(hb);
179
1
  ccv_nnc_tensor_free(hat);
180
1
  ccv_nnc_tensor_free(hbt);
181
1
}
182
183
TEST_CASE("min of two tensors with model")
184
1
{
185
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
186
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
187
1
  ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
188
1
  int i;
189
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
190
12
    a->data.f32[i] = i;
191
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
192
12
    b->data.f32[i] = i - 1;
193
1
  ccv_cnnp_model_t* const min = ccv_cnnp_min(0);
194
1
  const ccv_nnc_tensor_param_t a_params = CPU_TENSOR_NHWC(32F, 2, 2, 3);
195
1
  const ccv_nnc_tensor_param_t b_params = CPU_TENSOR_NHWC(32F, 2, 2, 3);
196
1
  ccv_cnnp_model_compile(min, TENSOR_PARAM_LIST(a_params, b_params), CMD_NOOP(), CMD_NOOP());
197
1
  ccv_cnnp_model_evaluate(min, (ccv_cnnp_evaluate_param_t){
198
1
    .requires_grad = 0,
199
1
    .is_test = 0,
200
1
    .disable_outgrad = CCV_CNNP_DISABLE_OUTGRAD_ALL
201
1
  }, TENSOR_LIST(a, b), TENSOR_LIST(c), 0, 0);
202
1
  REQUIRE_TENSOR_EQ(b, c, "c should be the minimal of the two");
203
1
  ccv_cnnp_model_free(min);
204
1
  ccv_nnc_tensor_free(a);
205
1
  ccv_nnc_tensor_free(b);
206
1
  ccv_nnc_tensor_free(c);
207
1
}
208
209
TEST_CASE("max of two tensors")
210
1
{
211
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
212
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
213
1
  ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
214
1
  int i;
215
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
216
12
    a->data.f32[i] = i;
217
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
218
12
    b->data.f32[i] = i + 1;
219
1
  ccv_nnc_cmd_exec(CMD_MAX_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(a, b), TENSOR_LIST(c), 0);
220
1
  REQUIRE_TENSOR_EQ(b, c, "c should be the maximal of the two");
221
1
  ccv_nnc_tensor_free(a);
222
1
  ccv_nnc_tensor_free(b);
223
1
  ccv_nnc_tensor_free(c);
224
1
}
225
226
TEST_CASE("max of two tensor views")
227
1
{
228
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0);
229
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0);
230
1
  ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
231
1
  int i;
232
49
  for (i = 0; i < 4 * 4 * 3; 
i++48
)
233
48
    a->data.f32[i] = i;
234
49
  for (i = 0; i < 4 * 4 * 3; 
i++48
)
235
48
    b->data.f32[i] = i + 1;
236
1
  ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4, 4, 3));
237
1
  ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4, 4, 3));
238
1
  ccv_nnc_cmd_exec(CMD_MAX_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)av, (ccv_nnc_tensor_t*)bv), TENSOR_LIST(c), 0);
239
1
  ccv_nnc_tensor_t* const bvt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
240
1
  ccv_nnc_cmd_exec(CMD_DATATYPE_CONVERSION_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)bv), TENSOR_LIST(bvt), 0);
241
1
  REQUIRE_TENSOR_EQ(bvt, c, "c should be the maximal of the two");
242
1
  ccv_nnc_tensor_free(a);
243
1
  ccv_nnc_tensor_free(b);
244
1
  ccv_nnc_tensor_free(c);
245
1
  ccv_nnc_tensor_free(bvt);
246
1
  ccv_nnc_tensor_view_free(av);
247
1
  ccv_nnc_tensor_view_free(bv);
248
1
}
249
250
TEST_CASE("max of two tensors backward")
251
1
{
252
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
253
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
254
1
  ccv_nnc_tensor_t* const g = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
255
1
  ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
256
1
  ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
257
1
  ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
258
1
  ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
259
1
  int i;
260
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
261
12
    a->data.f32[i] = i;
262
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
263
12
    b->data.f32[i] = i < 3 ? 
i3
:
i + 19
;
264
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
265
12
    g->data.f32[i] = -1;
266
1
  ccv_nnc_cmd_exec(CMD_MAX_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(g, a, b), TENSOR_LIST(ha, hb), 0);
267
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
268
12
    hat->data.f32[i] = i < 3 ? 
-13
:
09
;
269
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
270
12
    hbt->data.f32[i] = -1;
271
1
  REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3");
272
1
  REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients");
273
1
  ccv_nnc_tensor_free(a);
274
1
  ccv_nnc_tensor_free(b);
275
1
  ccv_nnc_tensor_free(g);
276
1
  ccv_nnc_tensor_free(ha);
277
1
  ccv_nnc_tensor_free(hb);
278
1
  ccv_nnc_tensor_free(hat);
279
1
  ccv_nnc_tensor_free(hbt);
280
1
}
281
282
TEST_CASE("max of two tensors backward with null")
283
1
{
284
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
285
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
286
1
  ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
287
1
  ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
288
1
  ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
289
1
  ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
290
1
  int i;
291
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
292
12
    a->data.f32[i] = i;
293
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
294
12
    b->data.f32[i] = i < 3 ? 
i3
:
i + 19
;
295
1
  ccv_nnc_cmd_exec(CMD_MAX_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(0, a, b), TENSOR_LIST(ha, hb), 0);
296
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
297
12
    hat->data.f32[i] = i < 3 ? 
13
:
09
;
298
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
299
12
    hbt->data.f32[i] = 1;
300
1
  REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3");
301
1
  REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients");
302
1
  ccv_nnc_tensor_free(a);
303
1
  ccv_nnc_tensor_free(b);
304
1
  ccv_nnc_tensor_free(ha);
305
1
  ccv_nnc_tensor_free(hb);
306
1
  ccv_nnc_tensor_free(hat);
307
1
  ccv_nnc_tensor_free(hbt);
308
1
}
309
310
TEST_CASE("max of two tensor views backward")
311
1
{
312
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0);
313
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0);
314
1
  ccv_nnc_tensor_t* const g = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
315
1
  ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
316
1
  ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
317
1
  ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
318
1
  ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
319
1
  int i;
320
49
  for (i = 0; i < 4 * 4 * 3; 
i++48
)
321
48
    a->data.f32[i] = i;
322
49
  for (i = 0; i < 4 * 4 * 3; 
i++48
)
323
48
    b->data.f32[i] = i < 3 ? 
i3
:
i + 145
;
324
1
  ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4, 4, 3));
325
1
  ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4, 4, 3));
326
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
327
12
    g->data.f32[i] = -1;
328
1
  ccv_nnc_cmd_exec(CMD_MAX_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(g, (ccv_nnc_tensor_t*)av, (ccv_nnc_tensor_t*)bv), TENSOR_LIST(ha, hb), 0);
329
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
330
12
    hat->data.f32[i] = i < 3 ? 
-13
:
09
;
331
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
332
12
    hbt->data.f32[i] = -1;
333
1
  REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3");
334
1
  REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients");
335
1
  ccv_nnc_tensor_free(a);
336
1
  ccv_nnc_tensor_free(b);
337
1
  ccv_nnc_tensor_view_free(av);
338
1
  ccv_nnc_tensor_view_free(bv);
339
1
  ccv_nnc_tensor_free(g);
340
1
  ccv_nnc_tensor_free(ha);
341
1
  ccv_nnc_tensor_free(hb);
342
1
  ccv_nnc_tensor_free(hat);
343
1
  ccv_nnc_tensor_free(hbt);
344
1
}
345
346
TEST_CASE("max of two tensor views backward with null")
347
1
{
348
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0);
349
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 4, 3), 0);
350
1
  ccv_nnc_tensor_t* const ha = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
351
1
  ccv_nnc_tensor_t* const hb = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
352
1
  ccv_nnc_tensor_t* const hat = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
353
1
  ccv_nnc_tensor_t* const hbt = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
354
1
  int i;
355
49
  for (i = 0; i < 4 * 4 * 3; 
i++48
)
356
48
    a->data.f32[i] = i;
357
49
  for (i = 0; i < 4 * 4 * 3; 
i++48
)
358
48
    b->data.f32[i] = i < 3 ? 
i3
:
i + 145
;
359
1
  ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4, 4, 3));
360
1
  ccv_nnc_tensor_view_t* const bv = ccv_nnc_tensor_view_new(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(), DIM_ALLOC(4, 4, 3));
361
1
  ccv_nnc_cmd_exec(CMD_MAX_BACKWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST(0, (ccv_nnc_tensor_t*)av, (ccv_nnc_tensor_t*)bv), TENSOR_LIST(ha, hb), 0);
362
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
363
12
    hat->data.f32[i] = i < 3 ? 
13
:
09
;
364
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
365
12
    hbt->data.f32[i] = 1;
366
1
  REQUIRE_TENSOR_EQ(ha, hat, "ha should only carry gradients for the first 3");
367
1
  REQUIRE_TENSOR_EQ(hb, hbt, "hb should only carry all gradients");
368
1
  ccv_nnc_tensor_free(a);
369
1
  ccv_nnc_tensor_free(b);
370
1
  ccv_nnc_tensor_view_free(av);
371
1
  ccv_nnc_tensor_view_free(bv);
372
1
  ccv_nnc_tensor_free(ha);
373
1
  ccv_nnc_tensor_free(hb);
374
1
  ccv_nnc_tensor_free(hat);
375
1
  ccv_nnc_tensor_free(hbt);
376
1
}
377
378
TEST_CASE("max of two tensors with model")
379
1
{
380
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
381
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
382
1
  ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 2, 2, 3), 0);
383
1
  int i;
384
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
385
12
    a->data.f32[i] = i;
386
13
  for (i = 0; i < 2 * 2 * 3; 
i++12
)
387
12
    b->data.f32[i] = i + 1;
388
1
  ccv_cnnp_model_t* const max = ccv_cnnp_max(0);
389
1
  const ccv_nnc_tensor_param_t a_params = CPU_TENSOR_NHWC(32F, 2, 2, 3);
390
1
  const ccv_nnc_tensor_param_t b_params = CPU_TENSOR_NHWC(32F, 2, 2, 3);
391
1
  ccv_cnnp_model_compile(max, TENSOR_PARAM_LIST(a_params, b_params), CMD_NOOP(), CMD_NOOP());
392
1
  ccv_cnnp_model_evaluate(max, (ccv_cnnp_evaluate_param_t){
393
1
    .requires_grad = 0,
394
1
    .is_test = 0,
395
1
    .disable_outgrad = CCV_CNNP_DISABLE_OUTGRAD_ALL
396
1
  }, TENSOR_LIST(a, b), TENSOR_LIST(c), 0, 0);
397
1
  REQUIRE_TENSOR_EQ(b, c, "c should be the maximal of the two");
398
1
  ccv_cnnp_model_free(max);
399
1
  ccv_nnc_tensor_free(a);
400
1
  ccv_nnc_tensor_free(b);
401
1
  ccv_nnc_tensor_free(c);
402
1
}
403
404
#include "case_main.h"