/home/liu/actions-runner/_work/ccv/ccv/test/unit/nnc/tensor.tests.c
Line | Count | Source |
1 | | #include "ccv.h" |
2 | | #include "case.h" |
3 | | #include "ccv_case.h" |
4 | | #include "ccv_nnc_case.h" |
5 | | #include "nnc/ccv_nnc.h" |
6 | | #include "nnc/ccv_nnc_easy.h" |
7 | | #include "3rdparty/sqlite3/sqlite3.h" |
8 | | #include "3rdparty/dsfmt/dSFMT.h" |
9 | | |
10 | | TEST_SETUP() |
11 | | { |
12 | | ccv_nnc_init(); |
13 | | } |
14 | | |
15 | | TEST_CASE("zero out a tensor") |
16 | | { |
17 | | const ccv_nnc_tensor_param_t params = { |
18 | | .type = CCV_TENSOR_CPU_MEMORY, |
19 | | .format = CCV_TENSOR_FORMAT_NHWC, |
20 | | .datatype = CCV_32F, |
21 | | .dim = { |
22 | | 10, 20, 30, 4, 5, 6, |
23 | | }, |
24 | | }; |
25 | | ccv_nnc_tensor_t* tensor = ccv_nnc_tensor_new(0, params, 0); |
26 | | int i; |
27 | | for (i = 0; i < 10 * 20 * 30 * 4 * 5 * 6; i++) |
28 | | tensor->data.f32[i] = 1; |
29 | | ccv_nnc_tensor_zero(tensor); |
30 | | for (i = 0; i < 10 * 20 * 30 * 4 * 5 * 6; i++) |
31 | | REQUIRE_EQ(0, tensor->data.f32[i], "should be zero'ed at %d", i); |
32 | | ccv_nnc_tensor_free(tensor); |
33 | | } |
34 | | |
35 | | TEST_CASE("zero out a tensor view") |
36 | 1 | { |
37 | 1 | const ccv_nnc_tensor_param_t params = { |
38 | 1 | .type = CCV_TENSOR_CPU_MEMORY, |
39 | 1 | .format = CCV_TENSOR_FORMAT_NHWC, |
40 | 1 | .datatype = CCV_32F, |
41 | 1 | .dim = { |
42 | 1 | 10, 20, 30, 4, 5, 6, |
43 | 1 | }, |
44 | 1 | }; |
45 | 1 | ccv_nnc_tensor_t* a_tensor = ccv_nnc_tensor_new(0, params, 0); |
46 | 1 | int c; |
47 | 720k | for (c = 0; c < 10 * 20 * 30 * 4 * 5 * 6; c++720k ) |
48 | 720k | a_tensor->data.f32[c] = 1; |
49 | 1 | int ofs[CCV_NNC_MAX_DIM_ALLOC] = { |
50 | 1 | 1, 2, 5, 1, 1, 1, |
51 | 1 | }; |
52 | 1 | const ccv_nnc_tensor_param_t new_params = { |
53 | 1 | .type = CCV_TENSOR_CPU_MEMORY, |
54 | 1 | .format = CCV_TENSOR_FORMAT_NHWC, |
55 | 1 | .datatype = CCV_32F, |
56 | 1 | .dim = { |
57 | 1 | 8, 12, 15, 2, 3, 4, |
58 | 1 | }, |
59 | 1 | }; |
60 | 1 | ccv_nnc_tensor_view_t a_tensor_view = ccv_nnc_tensor_view(a_tensor, new_params, ofs, DIM_ALLOC(20 * 30 * 4 * 5 * 6, 30 * 4 * 5 * 6, 4 * 5 * 6, 5 * 6, 6, 1)); |
61 | 1 | ccv_nnc_tensor_zero(&a_tensor_view); |
62 | 1 | ccv_nnc_tensor_t* b_tensor = ccv_nnc_tensor_new(0, params, 0); |
63 | 720k | for (c = 0; c < 10 * 20 * 30 * 4 * 5 * 6; c++720k ) |
64 | 720k | b_tensor->data.f32[c] = 1; |
65 | 1 | ccv_nnc_tensor_view_t b_tensor_view = ccv_nnc_tensor_view(b_tensor, new_params, ofs, DIM_ALLOC(20 * 30 * 4 * 5 * 6, 30 * 4 * 5 * 6, 4 * 5 * 6, 5 * 6, 6, 1)); |
66 | 1 | int i[6]; |
67 | 1 | float* tvp[6]; |
68 | 1 | tvp[5] = b_tensor_view.data.f32; |
69 | 9 | for (i[5] = 0; i[5] < b_tensor_view.info.dim[0]; i[5]++8 ) |
70 | 8 | { |
71 | 8 | tvp[4] = tvp[5]; |
72 | 104 | for (i[4] = 0; i[4] < b_tensor_view.info.dim[1]; i[4]++96 ) |
73 | 96 | { |
74 | 96 | tvp[3] = tvp[4]; |
75 | 1.53k | for (i[3] = 0; i[3] < b_tensor_view.info.dim[2]; i[3]++1.44k ) |
76 | 1.44k | { |
77 | 1.44k | tvp[2] = tvp[3]; |
78 | 4.32k | for (i[2] = 0; i[2] < b_tensor_view.info.dim[3]; i[2]++2.88k ) |
79 | 2.88k | { |
80 | 2.88k | tvp[1] = tvp[2]; |
81 | 11.5k | for (i[1] = 0; i[1] < b_tensor_view.info.dim[4]; i[1]++8.64k ) |
82 | 8.64k | { |
83 | 8.64k | tvp[0] = tvp[1]; |
84 | 43.2k | for (i[0] = 0; i[0] < b_tensor_view.info.dim[5]; i[0]++34.5k ) |
85 | 34.5k | { |
86 | 34.5k | tvp[0][i[0]] = 0; |
87 | 34.5k | } |
88 | 8.64k | tvp[1] += b_tensor_view.stride[4]; |
89 | 8.64k | } |
90 | 2.88k | tvp[2] += b_tensor_view.stride[3]; |
91 | 2.88k | } |
92 | 1.44k | tvp[3] += b_tensor_view.stride[2]; |
93 | 1.44k | } |
94 | 96 | tvp[4] += b_tensor_view.stride[1]; |
95 | 96 | } |
96 | 8 | tvp[5] += b_tensor_view.stride[0]; |
97 | 8 | } |
98 | 1 | REQUIRE_TENSOR_EQ(a_tensor, b_tensor, "zero'ed tensor view should be equal"); |
99 | 1 | ccv_nnc_tensor_free(a_tensor); |
100 | 1 | ccv_nnc_tensor_free(b_tensor); |
101 | 1 | } |
102 | | |
103 | | TEST_CASE("hint tensor") |
104 | 1 | { |
105 | 1 | ccv_nnc_tensor_param_t a = CPU_TENSOR_NHWC(32F, 234, 128, 3); |
106 | 1 | ccv_nnc_hint_t hint = { |
107 | 1 | .border = { |
108 | 1 | .begin = {1, 1}, |
109 | 1 | .end = {1, 2} |
110 | 1 | }, |
111 | 1 | .stride = { |
112 | 1 | .dim = {8, 7} |
113 | 1 | } |
114 | 1 | }; |
115 | 1 | ccv_nnc_cmd_t cmd = CMD_CONVOLUTION_FORWARD(1, 128, 4, 5, 3); |
116 | 1 | ccv_nnc_tensor_param_t b; |
117 | 1 | ccv_nnc_tensor_param_t w = CPU_TENSOR_NHWC(32F, 128, 4, 5, 3); |
118 | 1 | ccv_nnc_tensor_param_t bias = CPU_TENSOR_NHWC(32F, 128); |
119 | 1 | ccv_nnc_hint_tensor_auto(cmd, TENSOR_PARAM_LIST(a, w, bias), hint, &b, 1); |
120 | 1 | REQUIRE_EQ(b.dim[0], 30, "height should be 30"); |
121 | 1 | REQUIRE_EQ(b.dim[1], 19, "width should be 19"); |
122 | 1 | REQUIRE_EQ(b.dim[2], 128, "channel should be the convolution filter count"); |
123 | 1 | } |
124 | | |
125 | | TEST_CASE("tensor mapped from file") |
126 | 1 | { |
127 | 1 | FILE* w = fopen("data/tensor.bin", "w+"); |
128 | 1 | float* w_a = (float*)ccmalloc(sizeof(float) * 4096 * 5); |
129 | 1 | int i; |
130 | 20.4k | for (i = 0; i < 4096 * 5; i++20.4k ) |
131 | 20.4k | w_a[i] = (float)(i + 1); |
132 | 1 | fwrite(w_a, 1, sizeof(float) * 4096 * 5, w); |
133 | 1 | fclose(w); |
134 | 1 | ccfree(w_a); |
135 | 1 | float a[] = {1, 2, 3, 4, 5}; |
136 | 1 | ccv_nnc_tensor_t* tensor_a = ccv_nnc_tensor_new_from_file(CPU_TENSOR_NHWC(32F, 5), "data/tensor.bin", 0, 0); |
137 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor_a->data.f32, a, 5, 1e-5, "the first 5 element should be equal"); |
138 | 1 | float b[] = {4096 * 4 + 1, 4096 * 4 + 2, 4096 * 4 + 3, 4096 * 4 + 4}; |
139 | 1 | ccv_nnc_tensor_t* tensor_b = ccv_nnc_tensor_new_from_file(CPU_TENSOR_NHWC(32F, 4), "data/tensor.bin", (4096 * 4 * 4), 0); |
140 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor_b->data.f32, b, 4, 1e-5, "the first 4 element should be equal"); |
141 | 1 | ccv_nnc_tensor_free(tensor_a); |
142 | 1 | ccv_nnc_tensor_free(tensor_b); |
143 | 1 | } |
144 | | |
145 | | TEST_CASE("tensor persistence") |
146 | 1 | { |
147 | 1 | sqlite3* handle; |
148 | 1 | sqlite3_open("tensors.sqlite3", &handle); |
149 | 1 | ccv_nnc_tensor_t* const tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
150 | 1 | int i; |
151 | 1 | dsfmt_t dsfmt; |
152 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
153 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
154 | 6.00k | tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
155 | 1 | ccv_nnc_tensor_write(tensor, handle, "x", 0); |
156 | 1 | sqlite3_close(handle); |
157 | 1 | handle = 0; |
158 | 1 | sqlite3_open("tensors.sqlite3", &handle); |
159 | 1 | ccv_nnc_tensor_t* tensor1 = 0; |
160 | 1 | ccv_nnc_tensor_read(handle, "x", 0, 0, 0, &tensor1); |
161 | 1 | ccv_nnc_tensor_t* tensor2 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
162 | 1 | ccv_nnc_tensor_read(handle, "x", 0, 0, 0, &tensor2); |
163 | 1 | sqlite3_close(handle); |
164 | 1 | REQUIRE_TENSOR_EQ(tensor1, tensor, "the first tensor should equal to the second"); |
165 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor2->data.f32, tensor->data.f32, 10, 1e-5, "the first 10 element should be equal"); |
166 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor2->info.dim) == 1, "should be 1-d tensor"); |
167 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
168 | 1 | ccv_nnc_tensor_free(tensor1); |
169 | 1 | ccv_nnc_tensor_free(tensor2); |
170 | 1 | ccv_nnc_tensor_free(tensor); |
171 | 1 | } |
172 | | |
173 | | static int _tensor_split_count(sqlite3* const handle, const char* const name) |
174 | 3 | { |
175 | 3 | const char tensor_split_count_qs[] = "SELECT COUNT(*) FROM tensor_splits WHERE name=$name"; |
176 | 3 | sqlite3_stmt* tensor_split_count_stmt = 0; |
177 | 3 | if (sqlite3_prepare_v2(handle, tensor_split_count_qs, sizeof(tensor_split_count_qs), &tensor_split_count_stmt, 0) != SQLITE_OK) |
178 | 0 | return -1; |
179 | 3 | sqlite3_bind_text(tensor_split_count_stmt, 1, name, -1, SQLITE_STATIC); |
180 | 3 | int count = -1; |
181 | 3 | if (sqlite3_step(tensor_split_count_stmt) == SQLITE_ROW) |
182 | 3 | count = sqlite3_column_int(tensor_split_count_stmt, 0); |
183 | 3 | sqlite3_finalize(tensor_split_count_stmt); |
184 | 3 | return count; |
185 | 3 | } |
186 | | |
187 | | static int _tensor_split_table_exists(sqlite3* const handle) |
188 | 1 | { |
189 | 1 | const char tensor_split_table_qs[] = "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='tensor_splits'"; |
190 | 1 | sqlite3_stmt* tensor_split_table_stmt = 0; |
191 | 1 | if (sqlite3_prepare_v2(handle, tensor_split_table_qs, sizeof(tensor_split_table_qs), &tensor_split_table_stmt, 0) != SQLITE_OK) |
192 | 0 | return -1; |
193 | 1 | int exists = -1; |
194 | 1 | if (sqlite3_step(tensor_split_table_stmt) == SQLITE_ROW) |
195 | 1 | exists = sqlite3_column_int(tensor_split_table_stmt, 0); |
196 | 1 | sqlite3_finalize(tensor_split_table_stmt); |
197 | 1 | return exists; |
198 | 1 | } |
199 | | |
200 | | static sqlite_int64 _tensor_format(sqlite3* const handle, const char* const name) |
201 | 1 | { |
202 | 1 | const char tensor_format_qs[] = "SELECT format FROM tensors WHERE name=$name"; |
203 | 1 | sqlite3_stmt* tensor_format_stmt = 0; |
204 | 1 | if (sqlite3_prepare_v2(handle, tensor_format_qs, sizeof(tensor_format_qs), &tensor_format_stmt, 0) != SQLITE_OK) |
205 | 0 | return -1; |
206 | 1 | sqlite3_bind_text(tensor_format_stmt, 1, name, -1, SQLITE_STATIC); |
207 | 1 | sqlite_int64 format = -1; |
208 | 1 | if (sqlite3_step(tensor_format_stmt) == SQLITE_ROW) |
209 | 1 | format = sqlite3_column_int64(tensor_format_stmt, 0); |
210 | 1 | sqlite3_finalize(tensor_format_stmt); |
211 | 1 | return format; |
212 | 1 | } |
213 | | |
214 | | TEST_CASE("tensor persistence without split blobs does not create split table") |
215 | 1 | { |
216 | 1 | sqlite3* handle; |
217 | 1 | sqlite3_open(":memory:", &handle); |
218 | 1 | ccv_nnc_tensor_t* const tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
219 | 1 | int i; |
220 | 11 | for (i = 0; i < 10; i++10 ) |
221 | 10 | tensor->data.f32[i] = (float)(i + 1); |
222 | 1 | REQUIRE_EQ(ccv_nnc_tensor_write(tensor, handle, "x", 0), CCV_IO_FINAL, "write should succeed"); |
223 | 1 | REQUIRE_EQ(_tensor_split_table_exists(handle), 0, "non-split write should not create tensor_splits"); |
224 | 1 | ccv_nnc_tensor_t* tensor1 = 0; |
225 | 1 | REQUIRE_EQ(ccv_nnc_tensor_read(handle, "x", 0, 0, 0, &tensor1), CCV_IO_FINAL, "read should succeed"); |
226 | 1 | REQUIRE_TENSOR_EQ(tensor1, tensor, "tensor should round-trip"); |
227 | 1 | sqlite3_close(handle); |
228 | 1 | ccv_nnc_tensor_free(tensor1); |
229 | 1 | ccv_nnc_tensor_free(tensor); |
230 | 1 | } |
231 | | |
232 | | TEST_CASE("tensor persistence with split blobs") |
233 | 1 | { |
234 | 1 | sqlite3* handle; |
235 | 1 | sqlite3_open("tensors_split.sqlite3", &handle); |
236 | 1 | sqlite3_limit(handle, SQLITE_LIMIT_LENGTH, 8192); |
237 | 1 | ccv_nnc_tensor_t* const tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5000), 0); |
238 | 1 | int i; |
239 | 5.00k | for (i = 0; i < 5000; i++5.00k ) |
240 | 5.00k | tensor->data.f32[i] = (float)(i + 1); |
241 | 1 | REQUIRE_EQ(ccv_nnc_tensor_write(tensor, handle, "x", 0), CCV_IO_FINAL, "write should succeed"); |
242 | 1 | const int split_count = _tensor_split_count(handle, "x"); |
243 | 1 | REQUIRE(split_count > 0, "large tensor should be split"); |
244 | 1 | ccv_nnc_tensor_t* tensor1 = 0; |
245 | 1 | REQUIRE_EQ(ccv_nnc_tensor_read(handle, "x", 0, 0, 0, &tensor1), CCV_IO_FINAL, "read should succeed"); |
246 | 1 | REQUIRE_TENSOR_EQ(tensor1, tensor, "split tensor should round-trip"); |
247 | 1 | ccv_nnc_tensor_t* const small_tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
248 | 11 | for (i = 0; i < 10; i++10 ) |
249 | 10 | small_tensor->data.f32[i] = (float)(i + 1) * 0.5; |
250 | 1 | REQUIRE_EQ(ccv_nnc_tensor_write(small_tensor, handle, "x", 0), CCV_IO_FINAL, "small rewrite should succeed"); |
251 | 1 | REQUIRE_EQ(_tensor_format(handle, "x") >> 32, 0, "small rewrite should clear split marker"); |
252 | 1 | REQUIRE_EQ(_tensor_split_count(handle, "x"), split_count, "small rewrite should not touch old split rows"); |
253 | 1 | ccv_nnc_tensor_t* small_tensor1 = 0; |
254 | 1 | REQUIRE_EQ(ccv_nnc_tensor_read(handle, "x", 0, 0, 0, &small_tensor1), CCV_IO_FINAL, "small read should succeed"); |
255 | 1 | REQUIRE_TENSOR_EQ(small_tensor1, small_tensor, "rewritten small tensor should round-trip"); |
256 | 1 | sqlite3_close(handle); |
257 | 1 | ccv_nnc_tensor_free(tensor1); |
258 | 1 | ccv_nnc_tensor_free(small_tensor1); |
259 | 1 | ccv_nnc_tensor_free(tensor); |
260 | 1 | ccv_nnc_tensor_free(small_tensor); |
261 | 1 | } |
262 | | |
263 | | static int _tensor_xor_encode(const void* const data, const size_t data_size, const int datatype, const int* const dimensions, const int dimension_count, void* const context, void* const encoded, size_t* const encoded_size, ccv_nnc_tensor_param_t* const params, unsigned int* const identifier) |
264 | | { |
265 | | unsigned char* const u8 = (unsigned char*)data; |
266 | | unsigned char* const u8enc = (unsigned char*)encoded; |
267 | | int i; |
268 | | for (i = 0; i < data_size; i++) |
269 | | u8enc[i] = u8[i] ^ 0x13; |
270 | | *encoded_size = data_size; |
271 | | *identifier = 1; |
272 | | return 1; |
273 | | } |
274 | | |
275 | | static int _tensor_xor_decode(const void* const data, const size_t data_size, const int datatype, const int* const dimensions, const int dimension_count, const unsigned int identifier, void* const context, const ccv_nnc_tensor_param_t tensor_params, ccv_nnc_tensor_t** const tensor_out, void* decoded, size_t* const decoded_size) |
276 | | { |
277 | | if (identifier != 1) |
278 | | return 0; |
279 | | if (!tensor_out[0]) |
280 | | { |
281 | | tensor_out[0] = ccv_nnc_tensor_new(0, tensor_params, 0); |
282 | | if (!decoded) |
283 | | decoded = tensor_out[0]->data.u8; |
284 | | } |
285 | | unsigned char* const u8 = (unsigned char*)data; |
286 | | unsigned char* const u8dec = (unsigned char*)decoded; |
287 | | const size_t expected_size = *decoded_size; |
288 | | int i; |
289 | | for (i = 0; i < ccv_min(expected_size, data_size); i++) |
290 | | u8dec[i] = u8[i] ^ 0x13; |
291 | | *decoded_size = ccv_min(expected_size, data_size); |
292 | | return 1; |
293 | | } |
294 | | |
295 | | static int _tensor_noop_encode(const void* const data, const size_t data_size, const int datatype, const int* const dimensions, const int dimension_count, void* const context, void* const encoded, size_t* const encoded_size, ccv_nnc_tensor_param_t* const params, unsigned int* const identifier) |
296 | | { |
297 | | return 0; |
298 | | } |
299 | | |
300 | | static int _tensor_noop_decode(const void* const data, const size_t data_size, const int datatype, const int* const dimensions, const int dimension_count, const unsigned int identifier, void* const context, const ccv_nnc_tensor_param_t tensor_params, ccv_nnc_tensor_t** const tensor_out, void* const decoded, size_t* const decoded_size) |
301 | | { |
302 | | return 0; |
303 | | } |
304 | | |
305 | | TEST_CASE("tensor persistence with split blobs and encoder / decoder") |
306 | 1 | { |
307 | 1 | sqlite3* handle; |
308 | 1 | sqlite3_open("tensors_split_de.sqlite3", &handle); |
309 | 1 | sqlite3_limit(handle, SQLITE_LIMIT_LENGTH, 8192); |
310 | 1 | ccv_nnc_tensor_t* const tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 5000), 0); |
311 | 1 | int i; |
312 | 5.00k | for (i = 0; i < 5000; i++5.00k ) |
313 | 5.00k | tensor->data.f32[i] = (float)(i + 1); |
314 | 1 | ccv_nnc_tensor_io_option_t options = { |
315 | 1 | .encode = _tensor_xor_encode, |
316 | 1 | .decode = _tensor_xor_decode |
317 | 1 | }; |
318 | 1 | REQUIRE_EQ(ccv_nnc_tensor_write(tensor, handle, "x", &options), CCV_IO_FINAL, "write should succeed"); |
319 | 1 | REQUIRE(_tensor_split_count(handle, "x") > 0, "encoded large tensor should be split"); |
320 | 1 | ccv_nnc_tensor_t* tensor1 = 0; |
321 | 1 | REQUIRE_EQ(ccv_nnc_tensor_read(handle, "x", &options, 0, 0, &tensor1), CCV_IO_FINAL, "read should succeed"); |
322 | 1 | REQUIRE_TENSOR_EQ(tensor1, tensor, "split encoded tensor should round-trip"); |
323 | 1 | sqlite3_close(handle); |
324 | 1 | ccv_nnc_tensor_free(tensor1); |
325 | 1 | ccv_nnc_tensor_free(tensor); |
326 | 1 | } |
327 | | |
328 | | TEST_CASE("tensor persistence with encoder / decoder") |
329 | 1 | { |
330 | 1 | sqlite3* handle; |
331 | 1 | sqlite3_open("tensors_de.sqlite3", &handle); |
332 | 1 | ccv_nnc_tensor_t* const tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
333 | 1 | int i; |
334 | 1 | dsfmt_t dsfmt; |
335 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
336 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
337 | 6.00k | tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
338 | 1 | ccv_nnc_tensor_io_option_t options = { |
339 | 1 | .encode = _tensor_xor_encode, |
340 | 1 | .decode = _tensor_xor_decode |
341 | 1 | }; |
342 | 1 | ccv_nnc_tensor_write(tensor, handle, "y", &options); |
343 | 1 | sqlite3_close(handle); |
344 | 1 | handle = 0; |
345 | 1 | sqlite3_open("tensors_de.sqlite3", &handle); |
346 | 1 | ccv_nnc_tensor_t* tensor1 = 0; |
347 | 1 | ccv_nnc_tensor_read(handle, "y", &options, 0, 0, &tensor1); |
348 | 1 | ccv_nnc_tensor_t* tensor2 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
349 | 1 | ccv_nnc_tensor_read(handle, "y", &options, 0, 0, &tensor2); |
350 | 1 | sqlite3_close(handle); |
351 | 1 | REQUIRE_TENSOR_EQ(tensor1, tensor, "the first tensor should equal to the second"); |
352 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor2->data.f32, tensor->data.f32, 10, 1e-5, "the first 10 element should be equal"); |
353 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor2->info.dim) == 1, "should be 1-d tensor"); |
354 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
355 | 1 | ccv_nnc_tensor_free(tensor1); |
356 | 1 | ccv_nnc_tensor_free(tensor2); |
357 | 1 | ccv_nnc_tensor_free(tensor); |
358 | 1 | } |
359 | | |
360 | | TEST_CASE("tensor persistence with noop encoder / decoder") |
361 | 1 | { |
362 | 1 | sqlite3* handle; |
363 | 1 | sqlite3_open("tensors_noop_de.sqlite3", &handle); |
364 | 1 | ccv_nnc_tensor_t* const tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
365 | 1 | int i; |
366 | 1 | dsfmt_t dsfmt; |
367 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
368 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
369 | 6.00k | tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
370 | 1 | ccv_nnc_tensor_io_option_t options = { |
371 | 1 | .encode = _tensor_noop_encode, |
372 | 1 | .decode = _tensor_noop_decode |
373 | 1 | }; |
374 | 1 | ccv_nnc_tensor_write(tensor, handle, "y", &options); |
375 | 1 | sqlite3_close(handle); |
376 | 1 | handle = 0; |
377 | 1 | sqlite3_open("tensors_noop_de.sqlite3", &handle); |
378 | 1 | ccv_nnc_tensor_t* tensor1 = 0; |
379 | 1 | ccv_nnc_tensor_read(handle, "y", &options, 0, 0, &tensor1); |
380 | 1 | ccv_nnc_tensor_t* tensor2 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
381 | 1 | ccv_nnc_tensor_read(handle, "y", &options, 0, 0, &tensor2); |
382 | 1 | sqlite3_close(handle); |
383 | 1 | REQUIRE_TENSOR_EQ(tensor1, tensor, "the first tensor should equal to the second"); |
384 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor2->data.f32, tensor->data.f32, 10, 1e-5, "the first 10 element should be equal"); |
385 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor2->info.dim) == 1, "should be 1-d tensor"); |
386 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
387 | 1 | ccv_nnc_tensor_free(tensor1); |
388 | 1 | ccv_nnc_tensor_free(tensor2); |
389 | 1 | ccv_nnc_tensor_free(tensor); |
390 | 1 | } |
391 | | |
392 | | TEST_CASE("tensor persistence and read metadata only") |
393 | 1 | { |
394 | 1 | sqlite3* handle; |
395 | 1 | sqlite3_open("tensors_md.sqlite3", &handle); |
396 | 1 | ccv_nnc_tensor_t* const tensorf32 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
397 | 1 | int i; |
398 | 1 | dsfmt_t dsfmt; |
399 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
400 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
401 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
402 | 1 | ccv_nnc_tensor_t* const tensorf16 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10, 20, 30), 0); |
403 | 1 | ccv_float_to_half_precision(tensorf32->data.f32, (uint16_t*)tensorf16->data.f16, 10 * 20 * 30); |
404 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
405 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
406 | 1 | ccv_nnc_tensor_write(tensorf16, handle, "x", 0); |
407 | 1 | ccv_nnc_tensor_write(tensorf32, handle, "y", 0); |
408 | 1 | sqlite3_close(handle); |
409 | 1 | handle = 0; |
410 | 1 | sqlite3_open("tensors_md.sqlite3", &handle); |
411 | 1 | ccv_nnc_tensor_t* tensor1 = 0; |
412 | 1 | ccv_nnc_tensor_read(handle, "x", 0, CCV_NNC_TENSOR_READ_METADATA_ONLY, 0, &tensor1); |
413 | 1 | ccv_nnc_tensor_t* tensor2 = 0; |
414 | 1 | ccv_nnc_tensor_read(handle, "y", 0, CCV_NNC_TENSOR_READ_METADATA_ONLY, 0, &tensor2); |
415 | 1 | sqlite3_close(handle); |
416 | 1 | REQUIRE(tensor1->data.u8 == 0, "should have no data"); |
417 | 1 | REQUIRE(tensor2->data.u8 == 0, "should have no data"); |
418 | 1 | REQUIRE_EQ(tensor1->info.dim[0], 10, "should be 3-d tensor with 10, 20, 30"); |
419 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 3-d tensor with 10, 20, 30"); |
420 | 1 | REQUIRE_EQ(tensor1->info.dim[1], 20, "should be 3-d tensor with 10, 20, 30"); |
421 | 1 | REQUIRE_EQ(tensor2->info.dim[1], 20, "should be 3-d tensor with 10, 20, 30"); |
422 | 1 | REQUIRE_EQ(tensor1->info.dim[2], 30, "should be 3-d tensor with 10, 20, 30"); |
423 | 1 | REQUIRE_EQ(tensor2->info.dim[2], 30, "should be 3-d tensor with 10, 20, 30"); |
424 | 1 | REQUIRE_EQ(tensor1->info.dim[3], 0, "should be 3-d tensor with 10, 20, 30"); |
425 | 1 | REQUIRE_EQ(tensor2->info.dim[3], 0, "should be 3-d tensor with 10, 20, 30"); |
426 | 1 | ccv_nnc_tensor_free(tensor1); |
427 | 1 | ccv_nnc_tensor_free(tensor2); |
428 | 1 | ccv_nnc_tensor_free(tensorf16); |
429 | 1 | ccv_nnc_tensor_free(tensorf32); |
430 | 1 | } |
431 | | |
432 | | TEST_CASE("tensor persistence with type coercion") |
433 | 1 | { |
434 | 1 | sqlite3* handle; |
435 | 1 | sqlite3_open("tensors_tc.sqlite3", &handle); |
436 | 1 | ccv_nnc_tensor_t* const tensorf32 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
437 | 1 | int i; |
438 | 1 | dsfmt_t dsfmt; |
439 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
440 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
441 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
442 | 1 | ccv_nnc_tensor_t* const tensorf16 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10, 20, 30), 0); |
443 | 1 | ccv_float_to_half_precision(tensorf32->data.f32, (uint16_t*)tensorf16->data.f16, 10 * 20 * 30); |
444 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
445 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
446 | 1 | ccv_nnc_tensor_write(tensorf16, handle, "x", 0); |
447 | 1 | ccv_nnc_tensor_write(tensorf32, handle, "y", 0); |
448 | 1 | sqlite3_close(handle); |
449 | 1 | handle = 0; |
450 | 1 | sqlite3_open("tensors_tc.sqlite3", &handle); |
451 | 1 | ccv_nnc_tensor_t* tensor1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
452 | 1 | ccv_nnc_tensor_read(handle, "x", 0, 0, 0, &tensor1); |
453 | 1 | ccv_nnc_tensor_t* tensor2 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10), 0); |
454 | 1 | ccv_nnc_tensor_read(handle, "y", 0, 0, 0, &tensor2); |
455 | 1 | sqlite3_close(handle); |
456 | 1 | float* tensor1_ref = (float*)ccmalloc(sizeof(float) * 10); |
457 | 1 | ccv_half_precision_to_float((uint16_t*)tensorf16->data.f16, tensor1_ref, 10); |
458 | 1 | float* tensor2_ret = (float*)ccmalloc(sizeof(float) * 10); |
459 | 1 | ccv_half_precision_to_float((uint16_t*)tensor2->data.f16, tensor2_ret, 10); |
460 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor1->data.f32, tensor1_ref, 10, 1e-3, "the first 10 element should be equal"); |
461 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor2_ret, tensorf32->data.f32, 10, 1e-3, "the first 10 element should be equal"); |
462 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor1->info.dim) == 1, "should be 1-d tensor"); |
463 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor2->info.dim) == 1, "should be 1-d tensor"); |
464 | 1 | REQUIRE_EQ(tensor1->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
465 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
466 | 1 | ccv_nnc_tensor_free(tensor1); |
467 | 1 | ccv_nnc_tensor_free(tensor2); |
468 | 1 | ccv_nnc_tensor_free(tensorf16); |
469 | 1 | ccv_nnc_tensor_free(tensorf32); |
470 | 1 | ccfree(tensor1_ref); |
471 | 1 | ccfree(tensor2_ret); |
472 | 1 | } |
473 | | |
474 | | TEST_CASE("tensor persistence with type coercion and encoder / decoder") |
475 | 1 | { |
476 | 1 | sqlite3* handle; |
477 | 1 | sqlite3_open("tensors_tc_de.sqlite3", &handle); |
478 | 1 | ccv_nnc_tensor_t* const tensorf32 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
479 | 1 | int i; |
480 | 1 | dsfmt_t dsfmt; |
481 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
482 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
483 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
484 | 1 | ccv_nnc_tensor_t* const tensorf16 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10, 20, 30), 0); |
485 | 1 | ccv_float_to_half_precision(tensorf32->data.f32, (uint16_t*)tensorf16->data.f16, 10 * 20 * 30); |
486 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
487 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
488 | 1 | ccv_nnc_tensor_io_option_t options = { |
489 | 1 | .encode = _tensor_xor_encode, |
490 | 1 | .decode = _tensor_xor_decode |
491 | 1 | }; |
492 | 1 | ccv_nnc_tensor_write(tensorf16, handle, "x", &options); |
493 | 1 | ccv_nnc_tensor_write(tensorf32, handle, "y", &options); |
494 | 1 | sqlite3_close(handle); |
495 | 1 | handle = 0; |
496 | 1 | sqlite3_open("tensors_tc_de.sqlite3", &handle); |
497 | 1 | ccv_nnc_tensor_t* tensor1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
498 | 1 | ccv_nnc_tensor_read(handle, "x", &options, 0, 0, &tensor1); |
499 | 1 | ccv_nnc_tensor_t* tensor2 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10), 0); |
500 | 1 | ccv_nnc_tensor_read(handle, "y", &options, 0, 0, &tensor2); |
501 | 1 | sqlite3_close(handle); |
502 | 1 | float* tensor1_ref = (float*)ccmalloc(sizeof(float) * 10); |
503 | 1 | ccv_half_precision_to_float((uint16_t*)tensorf16->data.f16, tensor1_ref, 10); |
504 | 1 | float* tensor2_ret = (float*)ccmalloc(sizeof(float) * 10); |
505 | 1 | ccv_half_precision_to_float((uint16_t*)tensor2->data.f16, tensor2_ret, 10); |
506 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor1->data.f32, tensor1_ref, 10, 1e-3, "the first 10 element should be equal"); |
507 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor2_ret, tensorf32->data.f32, 10, 1e-3, "the first 10 element should be equal"); |
508 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor1->info.dim) == 1, "should be 1-d tensor"); |
509 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor2->info.dim) == 1, "should be 1-d tensor"); |
510 | 1 | REQUIRE_EQ(tensor1->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
511 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
512 | 1 | ccv_nnc_tensor_free(tensor1); |
513 | 1 | ccv_nnc_tensor_free(tensor2); |
514 | 1 | ccv_nnc_tensor_free(tensorf16); |
515 | 1 | ccv_nnc_tensor_free(tensorf32); |
516 | 1 | ccfree(tensor1_ref); |
517 | 1 | ccfree(tensor2_ret); |
518 | 1 | } |
519 | | |
520 | | TEST_CASE("tensor persistence with type coercion and noop encoder / decoder") |
521 | 1 | { |
522 | 1 | sqlite3* handle; |
523 | 1 | sqlite3_open("tensors_tc_noop_de.sqlite3", &handle); |
524 | 1 | ccv_nnc_tensor_t* const tensorf32 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
525 | 1 | int i; |
526 | 1 | dsfmt_t dsfmt; |
527 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
528 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
529 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
530 | 1 | ccv_nnc_tensor_t* const tensorf16 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10, 20, 30), 0); |
531 | 1 | ccv_float_to_half_precision(tensorf32->data.f32, (uint16_t*)tensorf16->data.f16, 10 * 20 * 30); |
532 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
533 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
534 | 1 | ccv_nnc_tensor_io_option_t options = { |
535 | 1 | .encode = _tensor_noop_encode, |
536 | 1 | .decode = _tensor_noop_decode |
537 | 1 | }; |
538 | 1 | ccv_nnc_tensor_write(tensorf16, handle, "x", &options); |
539 | 1 | ccv_nnc_tensor_write(tensorf32, handle, "y", &options); |
540 | 1 | sqlite3_close(handle); |
541 | 1 | handle = 0; |
542 | 1 | sqlite3_open("tensors_tc_noop_de.sqlite3", &handle); |
543 | 1 | ccv_nnc_tensor_t* tensor1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
544 | 1 | ccv_nnc_tensor_read(handle, "x", &options, 0, 0, &tensor1); |
545 | 1 | ccv_nnc_tensor_t* tensor2 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10), 0); |
546 | 1 | ccv_nnc_tensor_read(handle, "y", &options, 0, 0, &tensor2); |
547 | 1 | sqlite3_close(handle); |
548 | 1 | float* tensor1_ref = (float*)ccmalloc(sizeof(float) * 10); |
549 | 1 | ccv_half_precision_to_float((uint16_t*)tensorf16->data.f16, tensor1_ref, 10); |
550 | 1 | float* tensor2_ret = (float*)ccmalloc(sizeof(float) * 10); |
551 | 1 | ccv_half_precision_to_float((uint16_t*)tensor2->data.f16, tensor2_ret, 10); |
552 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor1->data.f32, tensor1_ref, 10, 1e-3, "the first 10 element should be equal"); |
553 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor2_ret, tensorf32->data.f32, 10, 1e-3, "the first 10 element should be equal"); |
554 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor1->info.dim) == 1, "should be 1-d tensor"); |
555 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor2->info.dim) == 1, "should be 1-d tensor"); |
556 | 1 | REQUIRE_EQ(tensor1->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
557 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
558 | 1 | ccv_nnc_tensor_free(tensor1); |
559 | 1 | ccv_nnc_tensor_free(tensor2); |
560 | 1 | ccv_nnc_tensor_free(tensorf16); |
561 | 1 | ccv_nnc_tensor_free(tensorf32); |
562 | 1 | ccfree(tensor1_ref); |
563 | 1 | ccfree(tensor2_ret); |
564 | 1 | } |
565 | | |
566 | | TEST_CASE("resize tensor") |
567 | 1 | { |
568 | 1 | ccv_nnc_tensor_t* tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 12, 12, 3), 0); |
569 | 1 | int i; |
570 | 433 | for (i = 0; i < 12 * 12 * 3; i++432 ) |
571 | 432 | tensor->data.f32[i] = i; |
572 | 1 | tensor = ccv_nnc_tensor_resize(tensor, CPU_TENSOR_NHWC(32F, 23, 23, 3)); |
573 | 1.15k | for (i = 12 * 12 * 3; i < 23 * 23 * 3; i++1.15k ) |
574 | 1.15k | tensor->data.f32[i] = i; |
575 | 1 | ccv_nnc_tensor_t* b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 23, 23, 3), 0); |
576 | 1.58k | for (i = 0; i < 23 * 23 * 3; i++1.58k ) |
577 | 1.58k | b->data.f32[i] = i; |
578 | 1 | REQUIRE_TENSOR_EQ(tensor, b, "should retain the content when resize a tensor"); |
579 | 1 | ccv_nnc_tensor_free(tensor); |
580 | 1 | ccv_nnc_tensor_free(b); |
581 | 1 | } |
582 | | |
583 | | TEST_CASE("format 5-d tensor into string") |
584 | 1 | { |
585 | 1 | ccv_nnc_tensor_t* tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32S, 2, 5, 2, 9, 9), 0); |
586 | 1 | int i; |
587 | 1.62k | for (i = 0; i < 81 * 2 * 5 * 2; i++1.62k ) |
588 | 1.62k | tensor->data.i32[i] = i; |
589 | 1 | char* str = ccv_nnc_tensor_format_new(tensor); |
590 | 1 | const char t[] = "[\n" |
591 | 1 | " [[[[ 0, 1, 2, ..., 6, 7, 8],\n" |
592 | 1 | " [ 9, 10, 11, ..., 15, 16, 17],\n" |
593 | 1 | " [ 18, 19, 20, ..., 24, 25, 26],\n" |
594 | 1 | " ...,\n" |
595 | 1 | " [ 54, 55, 56, ..., 60, 61, 62],\n" |
596 | 1 | " [ 63, 64, 65, ..., 69, 70, 71],\n" |
597 | 1 | " [ 72, 73, 74, ..., 78, 79, 80]],\n" |
598 | 1 | " [[ 81, 82, 83, ..., 87, 88, 89],\n" |
599 | 1 | " [ 90, 91, 92, ..., 96, 97, 98],\n" |
600 | 1 | " [ 99, 100, 101, ..., 105, 106, 107],\n" |
601 | 1 | " ...,\n" |
602 | 1 | " [ 135, 136, 137, ..., 141, 142, 143],\n" |
603 | 1 | " [ 144, 145, 146, ..., 150, 151, 152],\n" |
604 | 1 | " [ 153, 154, 155, ..., 159, 160, 161]]],\n" |
605 | 1 | " [[[ 162, 163, 164, ..., 168, 169, 170],\n" |
606 | 1 | " [ 171, 172, 173, ..., 177, 178, 179],\n" |
607 | 1 | " [ 180, 181, 182, ..., 186, 187, 188],\n" |
608 | 1 | " ...,\n" |
609 | 1 | " [ 216, 217, 218, ..., 222, 223, 224],\n" |
610 | 1 | " [ 225, 226, 227, ..., 231, 232, 233],\n" |
611 | 1 | " [ 234, 235, 236, ..., 240, 241, 242]],\n" |
612 | 1 | " [[ 243, 244, 245, ..., 249, 250, 251],\n" |
613 | 1 | " [ 252, 253, 254, ..., 258, 259, 260],\n" |
614 | 1 | " [ 261, 262, 263, ..., 267, 268, 269],\n" |
615 | 1 | " ...,\n" |
616 | 1 | " [ 297, 298, 299, ..., 303, 304, 305],\n" |
617 | 1 | " [ 306, 307, 308, ..., 312, 313, 314],\n" |
618 | 1 | " [ 315, 316, 317, ..., 321, 322, 323]]],\n" |
619 | 1 | " ...,\n" |
620 | 1 | " [[[ 486, 487, 488, ..., 492, 493, 494],\n" |
621 | 1 | " [ 495, 496, 497, ..., 501, 502, 503],\n" |
622 | 1 | " [ 504, 505, 506, ..., 510, 511, 512],\n" |
623 | 1 | " ...,\n" |
624 | 1 | " [ 540, 541, 542, ..., 546, 547, 548],\n" |
625 | 1 | " [ 549, 550, 551, ..., 555, 556, 557],\n" |
626 | 1 | " [ 558, 559, 560, ..., 564, 565, 566]],\n" |
627 | 1 | " [[ 567, 568, 569, ..., 573, 574, 575],\n" |
628 | 1 | " [ 576, 577, 578, ..., 582, 583, 584],\n" |
629 | 1 | " [ 585, 586, 587, ..., 591, 592, 593],\n" |
630 | 1 | " ...,\n" |
631 | 1 | " [ 621, 622, 623, ..., 627, 628, 629],\n" |
632 | 1 | " [ 630, 631, 632, ..., 636, 637, 638],\n" |
633 | 1 | " [ 639, 640, 641, ..., 645, 646, 647]]],\n" |
634 | 1 | " [[[ 648, 649, 650, ..., 654, 655, 656],\n" |
635 | 1 | " [ 657, 658, 659, ..., 663, 664, 665],\n" |
636 | 1 | " [ 666, 667, 668, ..., 672, 673, 674],\n" |
637 | 1 | " ...,\n" |
638 | 1 | " [ 702, 703, 704, ..., 708, 709, 710],\n" |
639 | 1 | " [ 711, 712, 713, ..., 717, 718, 719],\n" |
640 | 1 | " [ 720, 721, 722, ..., 726, 727, 728]],\n" |
641 | 1 | " [[ 729, 730, 731, ..., 735, 736, 737],\n" |
642 | 1 | " [ 738, 739, 740, ..., 744, 745, 746],\n" |
643 | 1 | " [ 747, 748, 749, ..., 753, 754, 755],\n" |
644 | 1 | " ...,\n" |
645 | 1 | " [ 783, 784, 785, ..., 789, 790, 791],\n" |
646 | 1 | " [ 792, 793, 794, ..., 798, 799, 800],\n" |
647 | 1 | " [ 801, 802, 803, ..., 807, 808, 809]]]],\n" |
648 | 1 | " [[[[ 810, 811, 812, ..., 816, 817, 818],\n" |
649 | 1 | " [ 819, 820, 821, ..., 825, 826, 827],\n" |
650 | 1 | " [ 828, 829, 830, ..., 834, 835, 836],\n" |
651 | 1 | " ...,\n" |
652 | 1 | " [ 864, 865, 866, ..., 870, 871, 872],\n" |
653 | 1 | " [ 873, 874, 875, ..., 879, 880, 881],\n" |
654 | 1 | " [ 882, 883, 884, ..., 888, 889, 890]],\n" |
655 | 1 | " [[ 891, 892, 893, ..., 897, 898, 899],\n" |
656 | 1 | " [ 900, 901, 902, ..., 906, 907, 908],\n" |
657 | 1 | " [ 909, 910, 911, ..., 915, 916, 917],\n" |
658 | 1 | " ...,\n" |
659 | 1 | " [ 945, 946, 947, ..., 951, 952, 953],\n" |
660 | 1 | " [ 954, 955, 956, ..., 960, 961, 962],\n" |
661 | 1 | " [ 963, 964, 965, ..., 969, 970, 971]]],\n" |
662 | 1 | " [[[ 972, 973, 974, ..., 978, 979, 980],\n" |
663 | 1 | " [ 981, 982, 983, ..., 987, 988, 989],\n" |
664 | 1 | " [ 990, 991, 992, ..., 996, 997, 998],\n" |
665 | 1 | " ...,\n" |
666 | 1 | " [ 1026, 1027, 1028, ..., 1032, 1033, 1034],\n" |
667 | 1 | " [ 1035, 1036, 1037, ..., 1041, 1042, 1043],\n" |
668 | 1 | " [ 1044, 1045, 1046, ..., 1050, 1051, 1052]],\n" |
669 | 1 | " [[ 1053, 1054, 1055, ..., 1059, 1060, 1061],\n" |
670 | 1 | " [ 1062, 1063, 1064, ..., 1068, 1069, 1070],\n" |
671 | 1 | " [ 1071, 1072, 1073, ..., 1077, 1078, 1079],\n" |
672 | 1 | " ...,\n" |
673 | 1 | " [ 1107, 1108, 1109, ..., 1113, 1114, 1115],\n" |
674 | 1 | " [ 1116, 1117, 1118, ..., 1122, 1123, 1124],\n" |
675 | 1 | " [ 1125, 1126, 1127, ..., 1131, 1132, 1133]]],\n" |
676 | 1 | " ...,\n" |
677 | 1 | " [[[ 1296, 1297, 1298, ..., 1302, 1303, 1304],\n" |
678 | 1 | " [ 1305, 1306, 1307, ..., 1311, 1312, 1313],\n" |
679 | 1 | " [ 1314, 1315, 1316, ..., 1320, 1321, 1322],\n" |
680 | 1 | " ...,\n" |
681 | 1 | " [ 1350, 1351, 1352, ..., 1356, 1357, 1358],\n" |
682 | 1 | " [ 1359, 1360, 1361, ..., 1365, 1366, 1367],\n" |
683 | 1 | " [ 1368, 1369, 1370, ..., 1374, 1375, 1376]],\n" |
684 | 1 | " [[ 1377, 1378, 1379, ..., 1383, 1384, 1385],\n" |
685 | 1 | " [ 1386, 1387, 1388, ..., 1392, 1393, 1394],\n" |
686 | 1 | " [ 1395, 1396, 1397, ..., 1401, 1402, 1403],\n" |
687 | 1 | " ...,\n" |
688 | 1 | " [ 1431, 1432, 1433, ..., 1437, 1438, 1439],\n" |
689 | 1 | " [ 1440, 1441, 1442, ..., 1446, 1447, 1448],\n" |
690 | 1 | " [ 1449, 1450, 1451, ..., 1455, 1456, 1457]]],\n" |
691 | 1 | " [[[ 1458, 1459, 1460, ..., 1464, 1465, 1466],\n" |
692 | 1 | " [ 1467, 1468, 1469, ..., 1473, 1474, 1475],\n" |
693 | 1 | " [ 1476, 1477, 1478, ..., 1482, 1483, 1484],\n" |
694 | 1 | " ...,\n" |
695 | 1 | " [ 1512, 1513, 1514, ..., 1518, 1519, 1520],\n" |
696 | 1 | " [ 1521, 1522, 1523, ..., 1527, 1528, 1529],\n" |
697 | 1 | " [ 1530, 1531, 1532, ..., 1536, 1537, 1538]],\n" |
698 | 1 | " [[ 1539, 1540, 1541, ..., 1545, 1546, 1547],\n" |
699 | 1 | " [ 1548, 1549, 1550, ..., 1554, 1555, 1556],\n" |
700 | 1 | " [ 1557, 1558, 1559, ..., 1563, 1564, 1565],\n" |
701 | 1 | " ...,\n" |
702 | 1 | " [ 1593, 1594, 1595, ..., 1599, 1600, 1601],\n" |
703 | 1 | " [ 1602, 1603, 1604, ..., 1608, 1609, 1610],\n" |
704 | 1 | " [ 1611, 1612, 1613, ..., 1617, 1618, 1619]]]]\n" |
705 | 1 | "]"; |
706 | 1 | REQUIRE(memcmp(str, t, strlen(t) + 1) == 0, "output should be equal"); |
707 | 1 | ccfree(str); |
708 | 1 | ccv_nnc_tensor_free(tensor); |
709 | 1 | } |
710 | | |
711 | | TEST_CASE("format small 2-d tensor into string") |
712 | 1 | { |
713 | 1 | ccv_nnc_tensor_t* tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32S, 4, 4), 0); |
714 | 1 | int i; |
715 | 17 | for (i = 0; i < 4 * 4; i++16 ) |
716 | 16 | tensor->data.i32[i] = i; |
717 | 1 | char* str = ccv_nnc_tensor_format_new(tensor); |
718 | 1 | const char t[] = "[\n" |
719 | 1 | " [ 0, 1, 2, 3],\n" |
720 | 1 | " [ 4, 5, 6, 7],\n" |
721 | 1 | " [ 8, 9, 10, 11],\n" |
722 | 1 | " [ 12, 13, 14, 15]\n" |
723 | 1 | "]"; |
724 | 1 | REQUIRE(memcmp(str, t, strlen(t) + 1) == 0, "output should be equal"); |
725 | 1 | ccfree(str); |
726 | 1 | ccv_nnc_tensor_free(tensor); |
727 | 1 | } |
728 | | |
729 | | TEST_CASE("format small 1-d tensor into string") |
730 | 1 | { |
731 | 1 | ccv_nnc_tensor_t* tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32S, 12), 0); |
732 | 1 | int i; |
733 | 13 | for (i = 0; i < 12; i++12 ) |
734 | 12 | tensor->data.i32[i] = i; |
735 | 1 | char* str = ccv_nnc_tensor_format_new(tensor); |
736 | 1 | const char t[] = "[\n" |
737 | 1 | " 0, 1, 2, 3, 4, 5, 6, 7,\n" |
738 | 1 | " 8, 9, 10, 11\n" |
739 | 1 | "]"; |
740 | 1 | REQUIRE(memcmp(str, t, strlen(t) + 1) == 0, "output should be equal"); |
741 | 1 | ccfree(str); |
742 | 1 | ccv_nnc_tensor_free(tensor); |
743 | 1 | } |
744 | | |
745 | | TEST_CASE("format large 1-d tensor into string") |
746 | 1 | { |
747 | 1 | ccv_nnc_tensor_t* tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32S, 68), 0); |
748 | 1 | int i; |
749 | 69 | for (i = 0; i < 68; i++68 ) |
750 | 68 | tensor->data.i32[i] = i; |
751 | 1 | char* str = ccv_nnc_tensor_format_new(tensor); |
752 | 1 | const char t[] = "[\n" |
753 | 1 | " 0, 1, 2, 3, 4, 5, 6, 7,\n" |
754 | 1 | " 8, 9, 10, 11, 12, 13, 14, 15,\n" |
755 | 1 | " 16, 17, 18, 19, 20, 21, 22, 23,\n" |
756 | 1 | " ...,\n" |
757 | 1 | " 48, 49, 50, 51, 52, 53, 54, 55,\n" |
758 | 1 | " 56, 57, 58, 59, 60, 61, 62, 63,\n" |
759 | 1 | " 64, 65, 66, 67\n" |
760 | 1 | "]"; |
761 | 1 | REQUIRE(memcmp(str, t, strlen(t) + 1) == 0, "output should be equal"); |
762 | 1 | ccfree(str); |
763 | 1 | ccv_nnc_tensor_free(tensor); |
764 | 1 | } |
765 | | |
766 | | TEST_CASE("allocate palettize tensor with quantization to 5-bit") |
767 | 1 | { |
768 | 1 | ccv_nnc_tensor_t* const tensor = ccv_nnc_tensor_new(0, ccv_nnc_tensor_palettize(CPU_TENSOR_NHWC(32F, 10, 20, 30), 5, 512), 0); |
769 | 1 | REQUIRE_EQ(5312, ccv_nnc_tensor_data_size(tensor->info), "should be this size"); |
770 | 1 | ccv_nnc_tensor_free(tensor); |
771 | 1 | } |
772 | | |
773 | | #include "case_main.h" |