Coverage Report

Created: 2024-08-19 11:27

/home/liu/actions-runner/_work/ccv/ccv/test/unit/nnc/transform.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("data transfer between different tensor views")
15
1
{
16
1
  ccv_nnc_tensor_t* a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 56, 56, 128), 0);
17
1
  ccv_nnc_tensor_t* b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 24, 32, 64), 0);
18
1
  ccv_nnc_cmd_t cmd = CMD_DATA_TRANSFER_FORWARD();
19
1
  int i;
20
401k
  for (i = 0; i < 128 * 56 * 56; 
i++401k
)
21
401k
    a->data.f32[i] = i;
22
  // 6 values, manageable.
23
1
  ccv_nnc_tensor_view_t a_view = ccv_nnc_tensor_view(a, CPU_TENSOR_NHWC(32F, 2, 3, 4), DIM_ALLOC(4, 3, 2), DIM_ALLOC(56 * 128, 128, 1));
24
1
  ccv_nnc_tensor_view_t b_view = ccv_nnc_tensor_view(b, CPU_TENSOR_NHWC(32F, 2, 3, 4), DIM_ALLOC(0, 0, 0), DIM_ALLOC(32 * 64, 64, 1));
25
1
  memset(b->data.f32, 0, sizeof(float) * 64 * 32 * 24);
26
1
  ccv_nnc_cmd_exec(cmd, ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)&a_view), TENSOR_LIST((ccv_nnc_tensor_t*)&b_view), 0);
27
1
  ccv_nnc_tensor_t* c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 24, 32, 64), 0);
28
1
  memset(c->data.f32, 0, sizeof(float) * 64 * 32 * 24);
29
1
  c->data.f32[0] = 128 * 56 * 4 + 128 * 3 + 2;
30
1
  c->data.f32[1] = 128 * 56 * 4 + 128 * 3 + 3;
31
1
  c->data.f32[2] = 128 * 56 * 4 + 128 * 3 + 4;
32
1
  c->data.f32[3] = 128 * 56 * 4 + 128 * 3 + 5;
33
1
  c->data.f32[64] = 128 * 56 * 4 + 128 * (3 + 1) + 2;
34
1
  c->data.f32[65] = 128 * 56 * 4 + 128 * (3 + 1) + 3;
35
1
  c->data.f32[66] = 128 * 56 * 4 + 128 * (3 + 1) + 4;
36
1
  c->data.f32[67] = 128 * 56 * 4 + 128 * (3 + 1) + 5;
37
1
  c->data.f32[128] = 128 * 56 * 4 + 128 * (3 + 2) + 2;
38
1
  c->data.f32[129] = 128 * 56 * 4 + 128 * (3 + 2) + 3;
39
1
  c->data.f32[130] = 128 * 56 * 4 + 128 * (3 + 2) + 4;
40
1
  c->data.f32[131] = 128 * 56 * 4 + 128 * (3 + 2) + 5;
41
1
  c->data.f32[64 * 32] = 128 * 56 * (4 + 1) + 128 * 3 + 2;
42
1
  c->data.f32[64 * 32 + 1] = 128 * 56 * (4 + 1) + 128 * 3 + 3;
43
1
  c->data.f32[64 * 32 + 2] = 128 * 56 * (4 + 1) + 128 * 3 + 4;
44
1
  c->data.f32[64 * 32 + 3] = 128 * 56 * (4 + 1) + 128 * 3 + 5;
45
1
  c->data.f32[64 * 32 + 64] = 128 * 56 * (4 + 1) + 128 * (3 + 1) + 2;
46
1
  c->data.f32[64 * 32 + 65] = 128 * 56 * (4 + 1) + 128 * (3 + 1) + 3;
47
1
  c->data.f32[64 * 32 + 66] = 128 * 56 * (4 + 1) + 128 * (3 + 1) + 4;
48
1
  c->data.f32[64 * 32 + 67] = 128 * 56 * (4 + 1) + 128 * (3 + 1) + 5;
49
1
  c->data.f32[64 * 32 + 128] = 128 * 56 * (4 + 1) + 128 * (3 + 2) + 2;
50
1
  c->data.f32[64 * 32 + 129] = 128 * 56 * (4 + 1) + 128 * (3 + 2) + 3;
51
1
  c->data.f32[64 * 32 + 130] = 128 * 56 * (4 + 1) + 128 * (3 + 2) + 4;
52
1
  c->data.f32[64 * 32 + 131] = 128 * 56 * (4 + 1) + 128 * (3 + 2) + 5;
53
1
  REQUIRE_TENSOR_EQ(b, c, "64x32x24 tensor should be exactly the same.");
54
1
  ccv_nnc_tensor_free(a);
55
1
  ccv_nnc_tensor_free(b);
56
1
  ccv_nnc_tensor_free(c);
57
1
}
58
59
TEST_CASE("format transform between NHWC and NCHW tensors")
60
1
{
61
1
  ccv_nnc_tensor_t* a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 3, 2), 0);
62
1
  ccv_nnc_tensor_t* b = ccv_nnc_tensor_new(0, CPU_TENSOR_NCHW(32F, 2, 4, 3), 0);
63
1
  ccv_nnc_cmd_t cmd = CMD_FORMAT_TRANSFORM_FORWARD();
64
1
  int i;
65
25
  for (i = 0; i < 2 * 3 * 4; 
i++24
)
66
24
    a->data.f32[i] = i;
67
1
  ccv_nnc_cmd_exec(cmd, ccv_nnc_no_hint, 0, TENSOR_LIST(a), TENSOR_LIST(b), 0);
68
1
  ccv_nnc_tensor_t* c = ccv_nnc_tensor_new(0, CPU_TENSOR_NCHW(32F, 2, 4, 3), 0);
69
1
  c->data.f32[0] = 0;
70
1
  c->data.f32[1] = 2;
71
1
  c->data.f32[2] = 4;
72
1
  c->data.f32[3] = 6;
73
1
  c->data.f32[4] = 8;
74
1
  c->data.f32[5] = 10;
75
1
  c->data.f32[6] = 12;
76
1
  c->data.f32[7] = 14;
77
1
  c->data.f32[8] = 16;
78
1
  c->data.f32[9] = 18;
79
1
  c->data.f32[10] = 20;
80
1
  c->data.f32[11] = 22;
81
1
  c->data.f32[12] = 1;
82
1
  c->data.f32[13] = 3;
83
1
  c->data.f32[14] = 5;
84
1
  c->data.f32[15] = 7;
85
1
  c->data.f32[16] = 9;
86
1
  c->data.f32[17] = 11;
87
1
  c->data.f32[18] = 13;
88
1
  c->data.f32[19] = 15;
89
1
  c->data.f32[20] = 17;
90
1
  c->data.f32[21] = 19;
91
1
  c->data.f32[22] = 21;
92
1
  c->data.f32[23] = 23;
93
1
  REQUIRE_TENSOR_EQ(b, c, "3x4x2 tensor should be exactly the same.");
94
1
  ccv_nnc_tensor_t* d = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 4, 3, 2), 0);
95
1
  ccv_nnc_cmd_exec(cmd, ccv_nnc_no_hint, 0, TENSOR_LIST(c), TENSOR_LIST(d), 0);
96
1
  REQUIRE_TENSOR_EQ(d, a, "2x3x4 tensor should be exactly the same.");
97
1
  ccv_nnc_tensor_free(a);
98
1
  ccv_nnc_tensor_free(b);
99
1
  ccv_nnc_tensor_free(c);
100
1
  ccv_nnc_tensor_free(d);
101
1
}
102
103
TEST_CASE("format transform between NHWC and NCHW tensor views")
104
1
{
105
1
  ccv_nnc_tensor_t* a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 7, 6, 5), 0);
106
1
  ccv_nnc_tensor_view_t a_view = ccv_nnc_tensor_view(a, CPU_TENSOR_NHWC(32F, 4, 3, 2), DIM_ALLOC(3, 2, 1), DIM_ALLOC(6 * 5, 5, 1));
107
1
  memset(a->data.f32, 0, sizeof(float) * 5 * 6 * 7);
108
1
  ccv_nnc_tensor_t* b = ccv_nnc_tensor_new(0, CPU_TENSOR_NCHW(32F, 8, 10, 8), 0);
109
1
  memset(b->data.f32, 0, sizeof(float) * 8 * 10 * 8);
110
1
  ccv_nnc_tensor_view_t b_view = ccv_nnc_tensor_view(b, CPU_TENSOR_NCHW(32F, 2, 4, 3), DIM_ALLOC(0, 0, 0), DIM_ALLOC(10 * 8, 8, 1));
111
1
  ccv_nnc_cmd_t cmd = CMD_FORMAT_TRANSFORM_FORWARD();
112
1
  int i, j, k;
113
5
  for (i = 0; i < 4; 
i++4
)
114
16
    
for (j = 0; 4
j < 3;
j++12
)
115
36
      
for (k = 0; 12
k < 2;
k++24
)
116
24
        a->data.f32[(i + 3) * 5 * 6 + (j + 2) * 5 + (k + 1)] = k + j * 2 + i * 3 * 2;
117
1
  ccv_nnc_cmd_exec(cmd, ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)&a_view), TENSOR_LIST((ccv_nnc_tensor_t*)&b_view), 0);
118
1
  ccv_nnc_tensor_t* c = ccv_nnc_tensor_new(0, CPU_TENSOR_NCHW(32F, 8, 10, 8), 0);
119
1
  memset(c->data.f32, 0, sizeof(float) * 8 * 10 * 8);
120
1
  c->data.f32[0] = 0;
121
1
  c->data.f32[1] = 2;
122
1
  c->data.f32[2] = 4;
123
1
  c->data.f32[8] = 6;
124
1
  c->data.f32[9] = 8;
125
1
  c->data.f32[10] = 10;
126
1
  c->data.f32[16] = 12;
127
1
  c->data.f32[17] = 14;
128
1
  c->data.f32[18] = 16;
129
1
  c->data.f32[24] = 18;
130
1
  c->data.f32[25] = 20;
131
1
  c->data.f32[26] = 22;
132
1
  c->data.f32[80] = 1;
133
1
  c->data.f32[81] = 3;
134
1
  c->data.f32[82] = 5;
135
1
  c->data.f32[88] = 7;
136
1
  c->data.f32[89] = 9;
137
1
  c->data.f32[90] = 11;
138
1
  c->data.f32[96] = 13;
139
1
  c->data.f32[97] = 15;
140
1
  c->data.f32[98] = 17;
141
1
  c->data.f32[104] = 19;
142
1
  c->data.f32[105] = 21;
143
1
  c->data.f32[106] = 23;
144
1
  REQUIRE_TENSOR_EQ(b, c, "3x4x2 tensor view should be exactly the same.");
145
1
  ccv_nnc_tensor_view_t c_view = ccv_nnc_tensor_view(c, CPU_TENSOR_NCHW(32F, 2, 4, 3), DIM_ALLOC(0, 0, 0), DIM_ALLOC(10 * 8, 8, 1));
146
1
  ccv_nnc_tensor_t* d = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 7, 6, 5), 0);
147
1
  memset(d->data.f32, 0, sizeof(float) * 5 * 6 * 7);
148
1
  ccv_nnc_tensor_view_t d_view = ccv_nnc_tensor_view(d, CPU_TENSOR_NHWC(32F, 4, 3, 2), DIM_ALLOC(3, 2, 1), DIM_ALLOC(6 * 5, 5, 1));
149
1
  ccv_nnc_cmd_exec(cmd, ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)&c_view), TENSOR_LIST((ccv_nnc_tensor_t*)&d_view), 0);
150
1
  REQUIRE_TENSOR_EQ(d, a, "2x3x4 tensor should be exactly the same.");
151
1
  ccv_nnc_tensor_free(a);
152
1
  ccv_nnc_tensor_free(b);
153
1
  ccv_nnc_tensor_free(c);
154
1
  ccv_nnc_tensor_free(d);
155
1
}
156
157
TEST_CASE("transpose two 4d tensor views")
158
1
{
159
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 7, 6, 5, 4), 0);
160
1
  memset(a->data.f32, 0, sizeof(float) * 7 * 6 * 5 * 4);
161
1
  ccv_nnc_tensor_view_t a_view = ccv_nnc_tensor_view(a, CPU_TENSOR_NHWC(32F, 4, 3, 2, 2), DIM_ALLOC(3, 2, 1, 0), DIM_ALLOC(6 * 5 * 4, 5 * 4, 4, 1));
162
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 8, 7, 6, 5), 0);
163
1
  memset(b->data.f32, 0, sizeof(float) * 8 * 7 * 6 * 5);
164
1
  ccv_nnc_tensor_view_t b_view = ccv_nnc_tensor_view(b, CPU_TENSOR_NHWC(32F, 4, 2, 2, 3), DIM_ALLOC(3, 2, 1, 0), DIM_ALLOC(7 * 6 * 5, 6 * 5, 5, 1));
165
1
  int i, j, k, l;
166
5
  for (i = 0; i < 4; 
i++4
)
167
16
    
for (j = 0; 4
j < 3;
j++12
)
168
36
      
for (k = 0; 12
k < 2;
k++24
)
169
72
        
for (l = 0; 24
l < 2;
l++48
)
170
48
          a->data.f32[(i + 3) * 6 * 5 * 4 + (j + 2) * 5 * 4 + (k + 1) * 4 + l] = i * 3 * 2 * 2 + j * 2 * 2 + k * 2 + l;
171
1
  ccv_nnc_cmd_exec(CMD_TRANSPOSE_FORWARD(1, 3), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)&a_view), TENSOR_LIST((ccv_nnc_tensor_t*)&b_view), 0);
172
1
  ccv_nnc_tensor_t* c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 8, 7, 6, 5), 0);
173
1
  memset(c->data.f32, 0, sizeof(float) * 8 * 7 * 6 * 5);
174
5
  for (i = 0; i < 4; 
i++4
)
175
16
    
for (j = 0; 4
j < 3;
j++12
)
176
36
      
for (k = 0; 12
k < 2;
k++24
)
177
72
        
for (l = 0; 24
l < 2;
l++48
)
178
48
          c->data.f32[(i + 3) * 7 * 6 * 5 + (l + 2) * 6 * 5 + (k + 1) * 5 + j] = i * 3 * 2 * 2 + j * 2 * 2 + k * 2 + l;
179
1
  REQUIRE_TENSOR_EQ(b, c, "4x2x2x3 tensor view should be exactly the same.");
180
1
  ccv_nnc_tensor_view_t c_view = ccv_nnc_tensor_view(c, CPU_TENSOR_NHWC(32F, 4, 2, 2, 3), DIM_ALLOC(3, 2, 1, 0), DIM_ALLOC(7 * 6 * 5, 6 * 5, 5, 1));
181
1
  ccv_nnc_tensor_t* d = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 7, 6, 5, 4), 0);
182
1
  memset(d->data.f32, 0, sizeof(float) * 7 * 6 * 5 * 4);
183
1
  ccv_nnc_tensor_view_t d_view = ccv_nnc_tensor_view(d, CPU_TENSOR_NHWC(32F, 4, 3, 2, 2), DIM_ALLOC(3, 2, 1, 0), DIM_ALLOC(6 * 5 * 4, 5 * 4, 4, 1));
184
1
  ccv_nnc_cmd_exec(CMD_TRANSPOSE_FORWARD(1, 3), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)&c_view), TENSOR_LIST((ccv_nnc_tensor_t*)&d_view), 0);
185
1
  REQUIRE_TENSOR_EQ(d, a, "4x3x2x2 tensor should be exactly the same.");
186
1
  ccv_nnc_tensor_free(a);
187
1
  ccv_nnc_tensor_free(b);
188
1
  ccv_nnc_tensor_free(c);
189
1
  ccv_nnc_tensor_free(d);
190
1
}
191
192
TEST_CASE("transpose two 3d tensor views")
193
1
{
194
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 6, 5, 4), 0);
195
1
  memset(a->data.f32, 0, sizeof(float) * 6 * 5 * 4);
196
1
  ccv_nnc_tensor_view_t a_view = ccv_nnc_tensor_view(a, CPU_TENSOR_NHWC(32F, 3, 2, 2), DIM_ALLOC(2, 1, 0), DIM_ALLOC(5 * 4, 4, 1));
197
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 7, 6, 5), 0);
198
1
  memset(b->data.f32, 0, sizeof(float) * 7 * 6 * 5);
199
1
  ccv_nnc_tensor_view_t b_view = ccv_nnc_tensor_view(b, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(2, 1, 0), DIM_ALLOC(6 * 5, 5, 1));
200
1
  int j, k, l;
201
4
  for (j = 0; j < 3; 
j++3
)
202
9
    
for (k = 0; 3
k < 2;
k++6
)
203
18
      
for (l = 0; 6
l < 2;
l++12
)
204
12
        a->data.f32[(j + 2) * 5 * 4 + (k + 1) * 4 + l] = j * 2 * 2 + k * 2 + l;
205
1
  ccv_nnc_cmd_exec(CMD_TRANSPOSE_FORWARD(0, 2), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)&a_view), TENSOR_LIST((ccv_nnc_tensor_t*)&b_view), 0);
206
1
  ccv_nnc_tensor_t* c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 7, 6, 5), 0);
207
1
  memset(c->data.f32, 0, sizeof(float) * 7 * 6 * 5);
208
4
  for (j = 0; j < 3; 
j++3
)
209
9
    
for (k = 0; 3
k < 2;
k++6
)
210
18
      
for (l = 0; 6
l < 2;
l++12
)
211
12
        c->data.f32[(l + 2) * 6 * 5 + (k + 1) * 5 + j] = j * 2 * 2 + k * 2 + l;
212
1
  REQUIRE_TENSOR_EQ(b, c, "2x2x3 tensor view should be exactly the same.");
213
1
  ccv_nnc_tensor_view_t c_view = ccv_nnc_tensor_view(c, CPU_TENSOR_NHWC(32F, 2, 2, 3), DIM_ALLOC(2, 1, 0), DIM_ALLOC(6 * 5, 5, 1));
214
1
  ccv_nnc_tensor_t* d = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 6, 5, 4), 0);
215
1
  memset(d->data.f32, 0, sizeof(float) * 6 * 5 * 4);
216
1
  ccv_nnc_tensor_view_t d_view = ccv_nnc_tensor_view(d, CPU_TENSOR_NHWC(32F, 3, 2, 2), DIM_ALLOC(2, 1, 0), DIM_ALLOC(5 * 4, 4, 1));
217
1
  ccv_nnc_cmd_exec(CMD_TRANSPOSE_FORWARD(0, 2), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)&c_view), TENSOR_LIST((ccv_nnc_tensor_t*)&d_view), 0);
218
1
  REQUIRE_TENSOR_EQ(d, a, "3x2x2 tensor should be exactly the same.");
219
1
  ccv_nnc_tensor_free(a);
220
1
  ccv_nnc_tensor_free(b);
221
1
  ccv_nnc_tensor_free(c);
222
1
  ccv_nnc_tensor_free(d);
223
1
}
224
225
TEST_CASE("masked fill forward a 3d tensor")
226
1
{
227
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 6, 5, 4), 0);
228
1
  int i, j;
229
1
  dsfmt_t dsfmt;
230
1
  dsfmt_init_gen_rand(&dsfmt, 0);
231
121
  for (i = 0; i < 6 * 5 * 4; 
i++120
)
232
120
    a->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
233
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32S, 5, 4), 0);
234
21
  for (i = 0; i < 5 * 4; 
i++20
)
235
20
    b->data.i32[i] = (i % 2 == 1) ? 
010
:
110
;
236
1
  ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 6, 5, 4), 0);
237
1
  ccv_nnc_cmd_exec(CMD_MASKED_FILL_FORWARD(0, -1e8), ccv_nnc_no_hint, 0, TENSOR_LIST(a, b), TENSOR_LIST(c), 0);
238
1
  ccv_nnc_tensor_t* const d = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 6, 5, 4), 0);
239
7
  for (i = 0; i < 6; 
i++6
)
240
126
    
for (j = 0; 6
j < 5 * 4;
j++120
)
241
120
      d->data.f32[i * 5 * 4 + j] = (j % 2 == 1) ? 
-1e860
:
a->data.f32[i * 5 * 4 + j]60
;
242
1
  REQUIRE_TENSOR_EQ(d, c, "6x5x4 tensor should be exactly the same.");
243
1
  ccv_nnc_tensor_free(a);
244
1
  ccv_nnc_tensor_free(b);
245
1
  ccv_nnc_tensor_free(c);
246
1
  ccv_nnc_tensor_free(d);
247
1
}
248
249
TEST_CASE("masked fill backward a 3d tensor")
250
1
{
251
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 6, 5, 4), 0);
252
1
  int i, j;
253
1
  dsfmt_t dsfmt;
254
1
  dsfmt_init_gen_rand(&dsfmt, 0);
255
121
  for (i = 0; i < 6 * 5 * 4; 
i++120
)
256
120
    a->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
257
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32S, 5, 4), 0);
258
21
  for (i = 0; i < 5 * 4; 
i++20
)
259
20
    b->data.i32[i] = (i % 2 == 1) ? 
010
:
110
;
260
1
  ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 6, 5, 4), 0);
261
1
  ccv_nnc_cmd_exec(CMD_MASKED_FILL_BACKWARD(0, -1e8), ccv_nnc_no_hint, 0, TENSOR_LIST(a, 0, b), TENSOR_LIST(c), 0);
262
1
  ccv_nnc_tensor_t* const d = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 6, 5, 4), 0);
263
7
  for (i = 0; i < 6; 
i++6
)
264
126
    
for (j = 0; 6
j < 5 * 4;
j++120
)
265
120
      d->data.f32[i * 5 * 4 + j] = (j % 2 == 1) ? 
060
:
a->data.f32[i * 5 * 4 + j]60
;
266
1
  REQUIRE_TENSOR_EQ(d, c, "6x5x4 tensor should be exactly the same.");
267
1
  ccv_nnc_tensor_free(a);
268
1
  ccv_nnc_tensor_free(b);
269
1
  ccv_nnc_tensor_free(c);
270
1
  ccv_nnc_tensor_free(d);
271
1
}
272
273
TEST_CASE("compare permute with transpose")
274
1
{
275
1
  ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NCHW(32F, 6, 5, 4, 3), 0);
276
1
  int i;
277
1
  dsfmt_t dsfmt;
278
1
  dsfmt_init_gen_rand(&dsfmt, 0);
279
361
  for (i = 0; i < 6 * 5 * 4 * 3; 
i++360
)
280
360
    a->data.f32[i] = dsfmt_genrand_open_close(&dsfmt);
281
1
  ccv_nnc_tensor_view_t* const av = ccv_nnc_tensor_view_new(a, CPU_TENSOR_NCHW(32F, 6, 4, 5, 3), ccv_nnc_no_ofs, DIM_ALLOC(5 * 4 * 3, 3, 4 * 3, 1));
282
1
  ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NCHW(32F, 6, 4, 5, 3), 0);
283
1
  ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, CPU_TENSOR_NCHW(32F, 6, 4, 5, 3), 0);
284
1
  ccv_nnc_cmd_exec(CMD_FORMAT_TRANSFORM_FORWARD(), ccv_nnc_no_hint, 0, TENSOR_LIST((ccv_nnc_tensor_t*)av), TENSOR_LIST(b), 0);
285
1
  ccv_nnc_cmd_exec(CMD_TRANSPOSE_FORWARD(1, 2), ccv_nnc_no_hint, 0, TENSOR_LIST(a), TENSOR_LIST(c), 0);
286
1
  REQUIRE_TENSOR_EQ(b, c, "transposed and permuted should be exactly the same.");
287
1
  ccv_nnc_tensor_free(a);
288
1
  ccv_nnc_tensor_view_free(av);
289
1
  ccv_nnc_tensor_free(b);
290
1
  ccv_nnc_tensor_free(c);
291
1
}
292
293
#include "case_main.h"