/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 | 1 | { |
17 | 1 | const ccv_nnc_tensor_param_t params = { |
18 | 1 | .type = CCV_TENSOR_CPU_MEMORY, |
19 | 1 | .format = CCV_TENSOR_FORMAT_NHWC, |
20 | 1 | .datatype = CCV_32F, |
21 | 1 | .dim = { |
22 | 1 | 10, 20, 30, 4, 5, 6, |
23 | 1 | }, |
24 | 1 | }; |
25 | 1 | ccv_nnc_tensor_t* tensor = ccv_nnc_tensor_new(0, params, 0); |
26 | 1 | int i; |
27 | 720k | for (i = 0; i < 10 * 20 * 30 * 4 * 5 * 6; i++720k ) |
28 | 720k | tensor->data.f32[i] = 1; |
29 | 1 | ccv_nnc_tensor_zero(tensor); |
30 | 720k | for (i = 0; i < 10 * 20 * 30 * 4 * 5 * 6; i++720k ) |
31 | 720k | REQUIRE_EQ(0, tensor->data.f32[i], "should be zero'ed at %d", i); |
32 | 1 | ccv_nnc_tensor_free(tensor); |
33 | 1 | } |
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_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) |
174 | 6 | { |
175 | 6 | unsigned char* const u8 = (unsigned char*)data; |
176 | 6 | unsigned char* const u8enc = (unsigned char*)encoded; |
177 | 6 | int i; |
178 | 120k | for (i = 0; i < data_size; i++120k ) |
179 | 120k | u8enc[i] = u8[i] ^ 0x13; |
180 | 6 | *encoded_size = data_size; |
181 | 6 | *identifier = 1; |
182 | 6 | return 1; |
183 | 6 | } |
184 | | |
185 | | 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) |
186 | 8 | { |
187 | 8 | if (identifier != 1) |
188 | 0 | return 0; |
189 | 8 | if (!tensor_out[0]) |
190 | 2 | { |
191 | 2 | tensor_out[0] = ccv_nnc_tensor_new(0, tensor_params, 0); |
192 | 2 | if (!decoded) |
193 | 1 | decoded = tensor_out[0]->data.u8; |
194 | 2 | } |
195 | 8 | unsigned char* const u8 = (unsigned char*)data; |
196 | 8 | unsigned char* const u8dec = (unsigned char*)decoded; |
197 | 8 | const size_t expected_size = *decoded_size; |
198 | 8 | int i; |
199 | 48.5k | for (i = 0; i < ccv_min(expected_size, data_size); i++48.5k ) |
200 | 48.5k | u8dec[i] = u8[i] ^ 0x13; |
201 | 8 | *decoded_size = ccv_min(expected_size, data_size); |
202 | 8 | return 1; |
203 | 8 | } |
204 | | |
205 | | 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) |
206 | 6 | { |
207 | 6 | return 0; |
208 | 6 | } |
209 | | |
210 | | 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) |
211 | 8 | { |
212 | 8 | return 0; |
213 | 8 | } |
214 | | |
215 | | TEST_CASE("tensor persistence with encoder / decoder") |
216 | 1 | { |
217 | 1 | sqlite3* handle; |
218 | 1 | sqlite3_open("tensors_de.sqlite3", &handle); |
219 | 1 | ccv_nnc_tensor_t* const tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
220 | 1 | int i; |
221 | 1 | dsfmt_t dsfmt; |
222 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
223 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
224 | 6.00k | tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
225 | 1 | ccv_nnc_tensor_io_option_t options = { |
226 | 1 | .encode = _tensor_xor_encode, |
227 | 1 | .decode = _tensor_xor_decode |
228 | 1 | }; |
229 | 1 | ccv_nnc_tensor_write(tensor, handle, "y", &options); |
230 | 1 | sqlite3_close(handle); |
231 | 1 | handle = 0; |
232 | 1 | sqlite3_open("tensors_de.sqlite3", &handle); |
233 | 1 | ccv_nnc_tensor_t* tensor1 = 0; |
234 | 1 | ccv_nnc_tensor_read(handle, "y", &options, 0, 0, &tensor1); |
235 | 1 | ccv_nnc_tensor_t* tensor2 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
236 | 1 | ccv_nnc_tensor_read(handle, "y", &options, 0, 0, &tensor2); |
237 | 1 | sqlite3_close(handle); |
238 | 1 | REQUIRE_TENSOR_EQ(tensor1, tensor, "the first tensor should equal to the second"); |
239 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor2->data.f32, tensor->data.f32, 10, 1e-5, "the first 10 element should be equal"); |
240 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor2->info.dim) == 1, "should be 1-d tensor"); |
241 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
242 | 1 | ccv_nnc_tensor_free(tensor1); |
243 | 1 | ccv_nnc_tensor_free(tensor2); |
244 | 1 | ccv_nnc_tensor_free(tensor); |
245 | 1 | } |
246 | | |
247 | | TEST_CASE("tensor persistence with noop encoder / decoder") |
248 | 1 | { |
249 | 1 | sqlite3* handle; |
250 | 1 | sqlite3_open("tensors_noop_de.sqlite3", &handle); |
251 | 1 | ccv_nnc_tensor_t* const tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
252 | 1 | int i; |
253 | 1 | dsfmt_t dsfmt; |
254 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
255 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
256 | 6.00k | tensor->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
257 | 1 | ccv_nnc_tensor_io_option_t options = { |
258 | 1 | .encode = _tensor_noop_encode, |
259 | 1 | .decode = _tensor_noop_decode |
260 | 1 | }; |
261 | 1 | ccv_nnc_tensor_write(tensor, handle, "y", &options); |
262 | 1 | sqlite3_close(handle); |
263 | 1 | handle = 0; |
264 | 1 | sqlite3_open("tensors_noop_de.sqlite3", &handle); |
265 | 1 | ccv_nnc_tensor_t* tensor1 = 0; |
266 | 1 | ccv_nnc_tensor_read(handle, "y", &options, 0, 0, &tensor1); |
267 | 1 | ccv_nnc_tensor_t* tensor2 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
268 | 1 | ccv_nnc_tensor_read(handle, "y", &options, 0, 0, &tensor2); |
269 | 1 | sqlite3_close(handle); |
270 | 1 | REQUIRE_TENSOR_EQ(tensor1, tensor, "the first tensor should equal to the second"); |
271 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor2->data.f32, tensor->data.f32, 10, 1e-5, "the first 10 element should be equal"); |
272 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor2->info.dim) == 1, "should be 1-d tensor"); |
273 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
274 | 1 | ccv_nnc_tensor_free(tensor1); |
275 | 1 | ccv_nnc_tensor_free(tensor2); |
276 | 1 | ccv_nnc_tensor_free(tensor); |
277 | 1 | } |
278 | | |
279 | | TEST_CASE("tensor persistence and read metadata only") |
280 | 1 | { |
281 | 1 | sqlite3* handle; |
282 | 1 | sqlite3_open("tensors_md.sqlite3", &handle); |
283 | 1 | ccv_nnc_tensor_t* const tensorf32 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
284 | 1 | int i; |
285 | 1 | dsfmt_t dsfmt; |
286 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
287 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
288 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
289 | 1 | ccv_nnc_tensor_t* const tensorf16 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10, 20, 30), 0); |
290 | 1 | ccv_float_to_half_precision(tensorf32->data.f32, (uint16_t*)tensorf16->data.f16, 10 * 20 * 30); |
291 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
292 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
293 | 1 | ccv_nnc_tensor_write(tensorf16, handle, "x", 0); |
294 | 1 | ccv_nnc_tensor_write(tensorf32, handle, "y", 0); |
295 | 1 | sqlite3_close(handle); |
296 | 1 | handle = 0; |
297 | 1 | sqlite3_open("tensors_md.sqlite3", &handle); |
298 | 1 | ccv_nnc_tensor_t* tensor1 = 0; |
299 | 1 | ccv_nnc_tensor_read(handle, "x", 0, CCV_NNC_TENSOR_READ_METADATA_ONLY, 0, &tensor1); |
300 | 1 | ccv_nnc_tensor_t* tensor2 = 0; |
301 | 1 | ccv_nnc_tensor_read(handle, "y", 0, CCV_NNC_TENSOR_READ_METADATA_ONLY, 0, &tensor2); |
302 | 1 | sqlite3_close(handle); |
303 | 1 | REQUIRE(tensor1->data.u8 == 0, "should have no data"); |
304 | 1 | REQUIRE(tensor2->data.u8 == 0, "should have no data"); |
305 | 1 | REQUIRE_EQ(tensor1->info.dim[0], 10, "should be 3-d tensor with 10, 20, 30"); |
306 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 3-d tensor with 10, 20, 30"); |
307 | 1 | REQUIRE_EQ(tensor1->info.dim[1], 20, "should be 3-d tensor with 10, 20, 30"); |
308 | 1 | REQUIRE_EQ(tensor2->info.dim[1], 20, "should be 3-d tensor with 10, 20, 30"); |
309 | 1 | REQUIRE_EQ(tensor1->info.dim[2], 30, "should be 3-d tensor with 10, 20, 30"); |
310 | 1 | REQUIRE_EQ(tensor2->info.dim[2], 30, "should be 3-d tensor with 10, 20, 30"); |
311 | 1 | REQUIRE_EQ(tensor1->info.dim[3], 0, "should be 3-d tensor with 10, 20, 30"); |
312 | 1 | REQUIRE_EQ(tensor2->info.dim[3], 0, "should be 3-d tensor with 10, 20, 30"); |
313 | 1 | ccv_nnc_tensor_free(tensor1); |
314 | 1 | ccv_nnc_tensor_free(tensor2); |
315 | 1 | ccv_nnc_tensor_free(tensorf16); |
316 | 1 | ccv_nnc_tensor_free(tensorf32); |
317 | 1 | } |
318 | | |
319 | | TEST_CASE("tensor persistence with type coercion") |
320 | 1 | { |
321 | 1 | sqlite3* handle; |
322 | 1 | sqlite3_open("tensors_tc.sqlite3", &handle); |
323 | 1 | ccv_nnc_tensor_t* const tensorf32 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
324 | 1 | int i; |
325 | 1 | dsfmt_t dsfmt; |
326 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
327 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
328 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
329 | 1 | ccv_nnc_tensor_t* const tensorf16 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10, 20, 30), 0); |
330 | 1 | ccv_float_to_half_precision(tensorf32->data.f32, (uint16_t*)tensorf16->data.f16, 10 * 20 * 30); |
331 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
332 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
333 | 1 | ccv_nnc_tensor_write(tensorf16, handle, "x", 0); |
334 | 1 | ccv_nnc_tensor_write(tensorf32, handle, "y", 0); |
335 | 1 | sqlite3_close(handle); |
336 | 1 | handle = 0; |
337 | 1 | sqlite3_open("tensors_tc.sqlite3", &handle); |
338 | 1 | ccv_nnc_tensor_t* tensor1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
339 | 1 | ccv_nnc_tensor_read(handle, "x", 0, 0, 0, &tensor1); |
340 | 1 | ccv_nnc_tensor_t* tensor2 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10), 0); |
341 | 1 | ccv_nnc_tensor_read(handle, "y", 0, 0, 0, &tensor2); |
342 | 1 | sqlite3_close(handle); |
343 | 1 | float* tensor1_ref = (float*)ccmalloc(sizeof(float) * 10); |
344 | 1 | ccv_half_precision_to_float((uint16_t*)tensorf16->data.f16, tensor1_ref, 10); |
345 | 1 | float* tensor2_ret = (float*)ccmalloc(sizeof(float) * 10); |
346 | 1 | ccv_half_precision_to_float((uint16_t*)tensor2->data.f16, tensor2_ret, 10); |
347 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor1->data.f32, tensor1_ref, 10, 1e-3, "the first 10 element should be equal"); |
348 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor2_ret, tensorf32->data.f32, 10, 1e-3, "the first 10 element should be equal"); |
349 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor1->info.dim) == 1, "should be 1-d tensor"); |
350 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor2->info.dim) == 1, "should be 1-d tensor"); |
351 | 1 | REQUIRE_EQ(tensor1->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
352 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
353 | 1 | ccv_nnc_tensor_free(tensor1); |
354 | 1 | ccv_nnc_tensor_free(tensor2); |
355 | 1 | ccv_nnc_tensor_free(tensorf16); |
356 | 1 | ccv_nnc_tensor_free(tensorf32); |
357 | 1 | ccfree(tensor1_ref); |
358 | 1 | ccfree(tensor2_ret); |
359 | 1 | } |
360 | | |
361 | | TEST_CASE("tensor persistence with type coercion and encoder / decoder") |
362 | 1 | { |
363 | 1 | sqlite3* handle; |
364 | 1 | sqlite3_open("tensors_tc_de.sqlite3", &handle); |
365 | 1 | ccv_nnc_tensor_t* const tensorf32 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
366 | 1 | int i; |
367 | 1 | dsfmt_t dsfmt; |
368 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
369 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
370 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
371 | 1 | ccv_nnc_tensor_t* const tensorf16 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10, 20, 30), 0); |
372 | 1 | ccv_float_to_half_precision(tensorf32->data.f32, (uint16_t*)tensorf16->data.f16, 10 * 20 * 30); |
373 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
374 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
375 | 1 | ccv_nnc_tensor_io_option_t options = { |
376 | 1 | .encode = _tensor_xor_encode, |
377 | 1 | .decode = _tensor_xor_decode |
378 | 1 | }; |
379 | 1 | ccv_nnc_tensor_write(tensorf16, handle, "x", &options); |
380 | 1 | ccv_nnc_tensor_write(tensorf32, handle, "y", &options); |
381 | 1 | sqlite3_close(handle); |
382 | 1 | handle = 0; |
383 | 1 | sqlite3_open("tensors_tc_de.sqlite3", &handle); |
384 | 1 | ccv_nnc_tensor_t* tensor1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
385 | 1 | ccv_nnc_tensor_read(handle, "x", &options, 0, 0, &tensor1); |
386 | 1 | ccv_nnc_tensor_t* tensor2 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10), 0); |
387 | 1 | ccv_nnc_tensor_read(handle, "y", &options, 0, 0, &tensor2); |
388 | 1 | sqlite3_close(handle); |
389 | 1 | float* tensor1_ref = (float*)ccmalloc(sizeof(float) * 10); |
390 | 1 | ccv_half_precision_to_float((uint16_t*)tensorf16->data.f16, tensor1_ref, 10); |
391 | 1 | float* tensor2_ret = (float*)ccmalloc(sizeof(float) * 10); |
392 | 1 | ccv_half_precision_to_float((uint16_t*)tensor2->data.f16, tensor2_ret, 10); |
393 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor1->data.f32, tensor1_ref, 10, 1e-3, "the first 10 element should be equal"); |
394 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor2_ret, tensorf32->data.f32, 10, 1e-3, "the first 10 element should be equal"); |
395 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor1->info.dim) == 1, "should be 1-d tensor"); |
396 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor2->info.dim) == 1, "should be 1-d tensor"); |
397 | 1 | REQUIRE_EQ(tensor1->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
398 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
399 | 1 | ccv_nnc_tensor_free(tensor1); |
400 | 1 | ccv_nnc_tensor_free(tensor2); |
401 | 1 | ccv_nnc_tensor_free(tensorf16); |
402 | 1 | ccv_nnc_tensor_free(tensorf32); |
403 | 1 | ccfree(tensor1_ref); |
404 | 1 | ccfree(tensor2_ret); |
405 | 1 | } |
406 | | |
407 | | TEST_CASE("tensor persistence with type coercion and noop encoder / decoder") |
408 | 1 | { |
409 | 1 | sqlite3* handle; |
410 | 1 | sqlite3_open("tensors_tc_noop_de.sqlite3", &handle); |
411 | 1 | ccv_nnc_tensor_t* const tensorf32 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10, 20, 30), 0); |
412 | 1 | int i; |
413 | 1 | dsfmt_t dsfmt; |
414 | 1 | dsfmt_init_gen_rand(&dsfmt, 1); |
415 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
416 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
417 | 1 | ccv_nnc_tensor_t* const tensorf16 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10, 20, 30), 0); |
418 | 1 | ccv_float_to_half_precision(tensorf32->data.f32, (uint16_t*)tensorf16->data.f16, 10 * 20 * 30); |
419 | 6.00k | for (i = 0; i < 10 * 20 * 30; i++6.00k ) |
420 | 6.00k | tensorf32->data.f32[i] = dsfmt_genrand_open_close(&dsfmt) * 2 - 1; |
421 | 1 | ccv_nnc_tensor_io_option_t options = { |
422 | 1 | .encode = _tensor_noop_encode, |
423 | 1 | .decode = _tensor_noop_decode |
424 | 1 | }; |
425 | 1 | ccv_nnc_tensor_write(tensorf16, handle, "x", &options); |
426 | 1 | ccv_nnc_tensor_write(tensorf32, handle, "y", &options); |
427 | 1 | sqlite3_close(handle); |
428 | 1 | handle = 0; |
429 | 1 | sqlite3_open("tensors_tc_noop_de.sqlite3", &handle); |
430 | 1 | ccv_nnc_tensor_t* tensor1 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 10), 0); |
431 | 1 | ccv_nnc_tensor_read(handle, "x", &options, 0, 0, &tensor1); |
432 | 1 | ccv_nnc_tensor_t* tensor2 = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(16F, 10), 0); |
433 | 1 | ccv_nnc_tensor_read(handle, "y", &options, 0, 0, &tensor2); |
434 | 1 | sqlite3_close(handle); |
435 | 1 | float* tensor1_ref = (float*)ccmalloc(sizeof(float) * 10); |
436 | 1 | ccv_half_precision_to_float((uint16_t*)tensorf16->data.f16, tensor1_ref, 10); |
437 | 1 | float* tensor2_ret = (float*)ccmalloc(sizeof(float) * 10); |
438 | 1 | ccv_half_precision_to_float((uint16_t*)tensor2->data.f16, tensor2_ret, 10); |
439 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor1->data.f32, tensor1_ref, 10, 1e-3, "the first 10 element should be equal"); |
440 | 1 | REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, tensor2_ret, tensorf32->data.f32, 10, 1e-3, "the first 10 element should be equal"); |
441 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor1->info.dim) == 1, "should be 1-d tensor"); |
442 | 1 | REQUIRE(ccv_nnc_tensor_nd(tensor2->info.dim) == 1, "should be 1-d tensor"); |
443 | 1 | REQUIRE_EQ(tensor1->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
444 | 1 | REQUIRE_EQ(tensor2->info.dim[0], 10, "should be 1-d tensor with 10-element"); |
445 | 1 | ccv_nnc_tensor_free(tensor1); |
446 | 1 | ccv_nnc_tensor_free(tensor2); |
447 | 1 | ccv_nnc_tensor_free(tensorf16); |
448 | 1 | ccv_nnc_tensor_free(tensorf32); |
449 | 1 | ccfree(tensor1_ref); |
450 | 1 | ccfree(tensor2_ret); |
451 | 1 | } |
452 | | |
453 | | TEST_CASE("resize tensor") |
454 | 1 | { |
455 | 1 | ccv_nnc_tensor_t* tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 12, 12, 3), 0); |
456 | 1 | int i; |
457 | 433 | for (i = 0; i < 12 * 12 * 3; i++432 ) |
458 | 432 | tensor->data.f32[i] = i; |
459 | 1 | tensor = ccv_nnc_tensor_resize(tensor, CPU_TENSOR_NHWC(32F, 23, 23, 3)); |
460 | 1.15k | for (i = 12 * 12 * 3; i < 23 * 23 * 3; i++1.15k ) |
461 | 1.15k | tensor->data.f32[i] = i; |
462 | 1 | ccv_nnc_tensor_t* b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 23, 23, 3), 0); |
463 | 1.58k | for (i = 0; i < 23 * 23 * 3; i++1.58k ) |
464 | 1.58k | b->data.f32[i] = i; |
465 | 1 | REQUIRE_TENSOR_EQ(tensor, b, "should retain the content when resize a tensor"); |
466 | 1 | ccv_nnc_tensor_free(tensor); |
467 | 1 | ccv_nnc_tensor_free(b); |
468 | 1 | } |
469 | | |
470 | | TEST_CASE("format 5-d tensor into string") |
471 | 1 | { |
472 | 1 | ccv_nnc_tensor_t* tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32S, 2, 5, 2, 9, 9), 0); |
473 | 1 | int i; |
474 | 1.62k | for (i = 0; i < 81 * 2 * 5 * 2; i++1.62k ) |
475 | 1.62k | tensor->data.i32[i] = i; |
476 | 1 | char* str = ccv_nnc_tensor_format_new(tensor); |
477 | 1 | const char t[] = "[\n" |
478 | 1 | " [[[[ 0, 1, 2, ..., 6, 7, 8],\n" |
479 | 1 | " [ 9, 10, 11, ..., 15, 16, 17],\n" |
480 | 1 | " [ 18, 19, 20, ..., 24, 25, 26],\n" |
481 | 1 | " ...,\n" |
482 | 1 | " [ 54, 55, 56, ..., 60, 61, 62],\n" |
483 | 1 | " [ 63, 64, 65, ..., 69, 70, 71],\n" |
484 | 1 | " [ 72, 73, 74, ..., 78, 79, 80]],\n" |
485 | 1 | " [[ 81, 82, 83, ..., 87, 88, 89],\n" |
486 | 1 | " [ 90, 91, 92, ..., 96, 97, 98],\n" |
487 | 1 | " [ 99, 100, 101, ..., 105, 106, 107],\n" |
488 | 1 | " ...,\n" |
489 | 1 | " [ 135, 136, 137, ..., 141, 142, 143],\n" |
490 | 1 | " [ 144, 145, 146, ..., 150, 151, 152],\n" |
491 | 1 | " [ 153, 154, 155, ..., 159, 160, 161]]],\n" |
492 | 1 | " [[[ 162, 163, 164, ..., 168, 169, 170],\n" |
493 | 1 | " [ 171, 172, 173, ..., 177, 178, 179],\n" |
494 | 1 | " [ 180, 181, 182, ..., 186, 187, 188],\n" |
495 | 1 | " ...,\n" |
496 | 1 | " [ 216, 217, 218, ..., 222, 223, 224],\n" |
497 | 1 | " [ 225, 226, 227, ..., 231, 232, 233],\n" |
498 | 1 | " [ 234, 235, 236, ..., 240, 241, 242]],\n" |
499 | 1 | " [[ 243, 244, 245, ..., 249, 250, 251],\n" |
500 | 1 | " [ 252, 253, 254, ..., 258, 259, 260],\n" |
501 | 1 | " [ 261, 262, 263, ..., 267, 268, 269],\n" |
502 | 1 | " ...,\n" |
503 | 1 | " [ 297, 298, 299, ..., 303, 304, 305],\n" |
504 | 1 | " [ 306, 307, 308, ..., 312, 313, 314],\n" |
505 | 1 | " [ 315, 316, 317, ..., 321, 322, 323]]],\n" |
506 | 1 | " ...,\n" |
507 | 1 | " [[[ 486, 487, 488, ..., 492, 493, 494],\n" |
508 | 1 | " [ 495, 496, 497, ..., 501, 502, 503],\n" |
509 | 1 | " [ 504, 505, 506, ..., 510, 511, 512],\n" |
510 | 1 | " ...,\n" |
511 | 1 | " [ 540, 541, 542, ..., 546, 547, 548],\n" |
512 | 1 | " [ 549, 550, 551, ..., 555, 556, 557],\n" |
513 | 1 | " [ 558, 559, 560, ..., 564, 565, 566]],\n" |
514 | 1 | " [[ 567, 568, 569, ..., 573, 574, 575],\n" |
515 | 1 | " [ 576, 577, 578, ..., 582, 583, 584],\n" |
516 | 1 | " [ 585, 586, 587, ..., 591, 592, 593],\n" |
517 | 1 | " ...,\n" |
518 | 1 | " [ 621, 622, 623, ..., 627, 628, 629],\n" |
519 | 1 | " [ 630, 631, 632, ..., 636, 637, 638],\n" |
520 | 1 | " [ 639, 640, 641, ..., 645, 646, 647]]],\n" |
521 | 1 | " [[[ 648, 649, 650, ..., 654, 655, 656],\n" |
522 | 1 | " [ 657, 658, 659, ..., 663, 664, 665],\n" |
523 | 1 | " [ 666, 667, 668, ..., 672, 673, 674],\n" |
524 | 1 | " ...,\n" |
525 | 1 | " [ 702, 703, 704, ..., 708, 709, 710],\n" |
526 | 1 | " [ 711, 712, 713, ..., 717, 718, 719],\n" |
527 | 1 | " [ 720, 721, 722, ..., 726, 727, 728]],\n" |
528 | 1 | " [[ 729, 730, 731, ..., 735, 736, 737],\n" |
529 | 1 | " [ 738, 739, 740, ..., 744, 745, 746],\n" |
530 | 1 | " [ 747, 748, 749, ..., 753, 754, 755],\n" |
531 | 1 | " ...,\n" |
532 | 1 | " [ 783, 784, 785, ..., 789, 790, 791],\n" |
533 | 1 | " [ 792, 793, 794, ..., 798, 799, 800],\n" |
534 | 1 | " [ 801, 802, 803, ..., 807, 808, 809]]]],\n" |
535 | 1 | " [[[[ 810, 811, 812, ..., 816, 817, 818],\n" |
536 | 1 | " [ 819, 820, 821, ..., 825, 826, 827],\n" |
537 | 1 | " [ 828, 829, 830, ..., 834, 835, 836],\n" |
538 | 1 | " ...,\n" |
539 | 1 | " [ 864, 865, 866, ..., 870, 871, 872],\n" |
540 | 1 | " [ 873, 874, 875, ..., 879, 880, 881],\n" |
541 | 1 | " [ 882, 883, 884, ..., 888, 889, 890]],\n" |
542 | 1 | " [[ 891, 892, 893, ..., 897, 898, 899],\n" |
543 | 1 | " [ 900, 901, 902, ..., 906, 907, 908],\n" |
544 | 1 | " [ 909, 910, 911, ..., 915, 916, 917],\n" |
545 | 1 | " ...,\n" |
546 | 1 | " [ 945, 946, 947, ..., 951, 952, 953],\n" |
547 | 1 | " [ 954, 955, 956, ..., 960, 961, 962],\n" |
548 | 1 | " [ 963, 964, 965, ..., 969, 970, 971]]],\n" |
549 | 1 | " [[[ 972, 973, 974, ..., 978, 979, 980],\n" |
550 | 1 | " [ 981, 982, 983, ..., 987, 988, 989],\n" |
551 | 1 | " [ 990, 991, 992, ..., 996, 997, 998],\n" |
552 | 1 | " ...,\n" |
553 | 1 | " [ 1026, 1027, 1028, ..., 1032, 1033, 1034],\n" |
554 | 1 | " [ 1035, 1036, 1037, ..., 1041, 1042, 1043],\n" |
555 | 1 | " [ 1044, 1045, 1046, ..., 1050, 1051, 1052]],\n" |
556 | 1 | " [[ 1053, 1054, 1055, ..., 1059, 1060, 1061],\n" |
557 | 1 | " [ 1062, 1063, 1064, ..., 1068, 1069, 1070],\n" |
558 | 1 | " [ 1071, 1072, 1073, ..., 1077, 1078, 1079],\n" |
559 | 1 | " ...,\n" |
560 | 1 | " [ 1107, 1108, 1109, ..., 1113, 1114, 1115],\n" |
561 | 1 | " [ 1116, 1117, 1118, ..., 1122, 1123, 1124],\n" |
562 | 1 | " [ 1125, 1126, 1127, ..., 1131, 1132, 1133]]],\n" |
563 | 1 | " ...,\n" |
564 | 1 | " [[[ 1296, 1297, 1298, ..., 1302, 1303, 1304],\n" |
565 | 1 | " [ 1305, 1306, 1307, ..., 1311, 1312, 1313],\n" |
566 | 1 | " [ 1314, 1315, 1316, ..., 1320, 1321, 1322],\n" |
567 | 1 | " ...,\n" |
568 | 1 | " [ 1350, 1351, 1352, ..., 1356, 1357, 1358],\n" |
569 | 1 | " [ 1359, 1360, 1361, ..., 1365, 1366, 1367],\n" |
570 | 1 | " [ 1368, 1369, 1370, ..., 1374, 1375, 1376]],\n" |
571 | 1 | " [[ 1377, 1378, 1379, ..., 1383, 1384, 1385],\n" |
572 | 1 | " [ 1386, 1387, 1388, ..., 1392, 1393, 1394],\n" |
573 | 1 | " [ 1395, 1396, 1397, ..., 1401, 1402, 1403],\n" |
574 | 1 | " ...,\n" |
575 | 1 | " [ 1431, 1432, 1433, ..., 1437, 1438, 1439],\n" |
576 | 1 | " [ 1440, 1441, 1442, ..., 1446, 1447, 1448],\n" |
577 | 1 | " [ 1449, 1450, 1451, ..., 1455, 1456, 1457]]],\n" |
578 | 1 | " [[[ 1458, 1459, 1460, ..., 1464, 1465, 1466],\n" |
579 | 1 | " [ 1467, 1468, 1469, ..., 1473, 1474, 1475],\n" |
580 | 1 | " [ 1476, 1477, 1478, ..., 1482, 1483, 1484],\n" |
581 | 1 | " ...,\n" |
582 | 1 | " [ 1512, 1513, 1514, ..., 1518, 1519, 1520],\n" |
583 | 1 | " [ 1521, 1522, 1523, ..., 1527, 1528, 1529],\n" |
584 | 1 | " [ 1530, 1531, 1532, ..., 1536, 1537, 1538]],\n" |
585 | 1 | " [[ 1539, 1540, 1541, ..., 1545, 1546, 1547],\n" |
586 | 1 | " [ 1548, 1549, 1550, ..., 1554, 1555, 1556],\n" |
587 | 1 | " [ 1557, 1558, 1559, ..., 1563, 1564, 1565],\n" |
588 | 1 | " ...,\n" |
589 | 1 | " [ 1593, 1594, 1595, ..., 1599, 1600, 1601],\n" |
590 | 1 | " [ 1602, 1603, 1604, ..., 1608, 1609, 1610],\n" |
591 | 1 | " [ 1611, 1612, 1613, ..., 1617, 1618, 1619]]]]\n" |
592 | 1 | "]"; |
593 | 1 | REQUIRE(memcmp(str, t, strlen(t) + 1) == 0, "output should be equal"); |
594 | 1 | ccfree(str); |
595 | 1 | ccv_nnc_tensor_free(tensor); |
596 | 1 | } |
597 | | |
598 | | TEST_CASE("format small 2-d tensor into string") |
599 | 1 | { |
600 | 1 | ccv_nnc_tensor_t* tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32S, 4, 4), 0); |
601 | 1 | int i; |
602 | 17 | for (i = 0; i < 4 * 4; i++16 ) |
603 | 16 | tensor->data.i32[i] = i; |
604 | 1 | char* str = ccv_nnc_tensor_format_new(tensor); |
605 | 1 | const char t[] = "[\n" |
606 | 1 | " [ 0, 1, 2, 3],\n" |
607 | 1 | " [ 4, 5, 6, 7],\n" |
608 | 1 | " [ 8, 9, 10, 11],\n" |
609 | 1 | " [ 12, 13, 14, 15]\n" |
610 | 1 | "]"; |
611 | 1 | REQUIRE(memcmp(str, t, strlen(t) + 1) == 0, "output should be equal"); |
612 | 1 | ccfree(str); |
613 | 1 | ccv_nnc_tensor_free(tensor); |
614 | 1 | } |
615 | | |
616 | | TEST_CASE("format small 1-d tensor into string") |
617 | 1 | { |
618 | 1 | ccv_nnc_tensor_t* tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32S, 12), 0); |
619 | 1 | int i; |
620 | 13 | for (i = 0; i < 12; i++12 ) |
621 | 12 | tensor->data.i32[i] = i; |
622 | 1 | char* str = ccv_nnc_tensor_format_new(tensor); |
623 | 1 | const char t[] = "[\n" |
624 | 1 | " 0, 1, 2, 3, 4, 5, 6, 7,\n" |
625 | 1 | " 8, 9, 10, 11\n" |
626 | 1 | "]"; |
627 | 1 | REQUIRE(memcmp(str, t, strlen(t) + 1) == 0, "output should be equal"); |
628 | 1 | ccfree(str); |
629 | 1 | ccv_nnc_tensor_free(tensor); |
630 | 1 | } |
631 | | |
632 | | TEST_CASE("format large 1-d tensor into string") |
633 | 1 | { |
634 | 1 | ccv_nnc_tensor_t* tensor = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32S, 68), 0); |
635 | 1 | int i; |
636 | 69 | for (i = 0; i < 68; i++68 ) |
637 | 68 | tensor->data.i32[i] = i; |
638 | 1 | char* str = ccv_nnc_tensor_format_new(tensor); |
639 | 1 | const char t[] = "[\n" |
640 | 1 | " 0, 1, 2, 3, 4, 5, 6, 7,\n" |
641 | 1 | " 8, 9, 10, 11, 12, 13, 14, 15,\n" |
642 | 1 | " 16, 17, 18, 19, 20, 21, 22, 23,\n" |
643 | 1 | " ...,\n" |
644 | 1 | " 48, 49, 50, 51, 52, 53, 54, 55,\n" |
645 | 1 | " 56, 57, 58, 59, 60, 61, 62, 63,\n" |
646 | 1 | " 64, 65, 66, 67\n" |
647 | 1 | "]"; |
648 | 1 | REQUIRE(memcmp(str, t, strlen(t) + 1) == 0, "output should be equal"); |
649 | 1 | ccfree(str); |
650 | 1 | ccv_nnc_tensor_free(tensor); |
651 | 1 | } |
652 | | |
653 | | TEST_CASE("allocate palettize tensor with quantization to 5-bit") |
654 | 1 | { |
655 | 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); |
656 | 1 | REQUIRE_EQ(5312, ccv_nnc_tensor_data_size(tensor->info), "should be this size"); |
657 | 1 | ccv_nnc_tensor_free(tensor); |
658 | 1 | } |
659 | | |
660 | | #include "case_main.h" |