Coverage Report

Created: 2024-08-18 16:21

/home/liu/actions-runner/_work/ccv/ccv/test/unit/util.tests.c
Line
Count
Source
1
#include "ccv.h"
2
#include "case.h"
3
#include "ccv_case.h"
4
#include "3rdparty/dsfmt/dSFMT.h"
5
#include "3rdparty/sfmt/SFMT.h"
6
7
TEST_CASE("type size macro")
8
1
{
9
1
  REQUIRE_EQ(CCV_GET_DATA_TYPE_SIZE(CCV_8U), 1, "CCV_8U should have size 1");
10
1
  REQUIRE_EQ(CCV_GET_DATA_TYPE_SIZE(CCV_32S), 4, "CCV_32S should have size 4");
11
1
  REQUIRE_EQ(CCV_GET_DATA_TYPE_SIZE(CCV_32F), 4, "CCV_32F should have size 4");
12
1
  REQUIRE_EQ(CCV_GET_DATA_TYPE_SIZE(CCV_64S), 8, "CCV_64S should have size 8");
13
1
  REQUIRE_EQ(CCV_GET_DATA_TYPE_SIZE(CCV_64F), 8, "CCV_64F should have size 8");
14
1
  REQUIRE_EQ(CCV_GET_DATA_TYPE_SIZE(CCV_16F), 2, "CCV_64F should have size 2");
15
1
  REQUIRE_EQ(sizeof(ccv_float16_t), 2, "sizeof float16 should be 2");
16
1
}
17
18
TEST_CASE("dynamic array")
19
1
{
20
1
  ccv_array_t* array = ccv_array_new(4, 2, 0);
21
1
  int i;
22
1
  i = 1;
23
1
  ccv_array_push(array, &i);
24
1
  i = 2;
25
1
  ccv_array_push(array, &i);
26
1
  i = 3;
27
1
  ccv_array_push(array, &i);
28
1
  i = 4;
29
1
  ccv_array_push(array, &i);
30
1
  i = 5;
31
1
  ccv_array_push(array, &i);
32
1
  REQUIRE_EQ(5, array->rnum, "should have 5 elements pushed to array");
33
6
  for (i = 0; i < array->rnum; 
i++5
)
34
5
    REQUIRE_EQ(i + 1, ((int*)ccv_array_get(array, i))[0], "check element values in array");
35
1
  ccv_array_clear(array);
36
1
  i = 3;
37
1
  ccv_array_push(array, &i);
38
1
  i = 4;
39
1
  ccv_array_push(array, &i);
40
1
  i = 5;
41
1
  ccv_array_push(array, &i);
42
1
  REQUIRE_EQ(3, array->rnum, "should have 3 elements after clear");
43
4
  for (i = 0; i < array->rnum; 
i++3
)
44
3
    REQUIRE_EQ(i + 3, ((int*)ccv_array_get(array, i))[0], "check element values in array after clear at index %d", i);
45
1
  ccv_array_free(array);
46
1
}
47
48
TEST_CASE("array resize")
49
1
{
50
1
  ccv_array_t* array = ccv_array_new(4, 2, 0);
51
1
  int i;
52
1
  i = 1;
53
1
  ccv_array_push(array, &i);
54
1
  ccv_array_resize(array, 4);
55
1
  REQUIRE_EQ(4, array->rnum, "should have 4 elements in array");
56
1
  REQUIRE_EQ(1, ((int*)ccv_array_get(array, 0))[0], "check element values in array");
57
4
  for (i = 1; i < array->rnum; 
i++3
)
58
3
    REQUIRE_EQ(0, ((int*)ccv_array_get(array, i))[0], "check element values in array");
59
1
  ccv_array_free(array);
60
1
}
61
62
int is_equal(const void* r1, const void* r2, void* data)
63
56
{
64
56
  int a = *(int*)r1;
65
56
  int b = *(int*)r2;
66
56
  return a == b;
67
56
}
68
69
TEST_CASE("group array with is_equal function")
70
1
{
71
1
  ccv_array_t* array = ccv_array_new(4, 2, 0);
72
1
  int i;
73
1
  i = 1;
74
1
  ccv_array_push(array, &i);
75
1
  i = 2;
76
1
  ccv_array_push(array, &i);
77
1
  i = 2;
78
1
  ccv_array_push(array, &i);
79
1
  i = 2;
80
1
  ccv_array_push(array, &i);
81
1
  i = 5;
82
1
  ccv_array_push(array, &i);
83
1
  i = 3;
84
1
  ccv_array_push(array, &i);
85
1
  i = 4;
86
1
  ccv_array_push(array, &i);
87
1
  i = 5;
88
1
  ccv_array_push(array, &i);
89
1
  ccv_array_t* idx = 0;
90
1
  ccv_array_group(array, &idx, is_equal, 0);
91
1
  REQUIRE_EQ(((int*)ccv_array_get(idx, 1))[0], ((int*)ccv_array_get(idx, 2))[0], "element 2, 3 should in the same group");
92
1
  REQUIRE_EQ(((int*)ccv_array_get(idx, 2))[0], ((int*)ccv_array_get(idx, 3))[0], "element 3, 4 should in the same group");
93
1
  REQUIRE_EQ(((int*)ccv_array_get(idx, 4))[0], ((int*)ccv_array_get(idx, 7))[0], "element 4, 8 should in the same group");
94
1
  REQUIRE_NOT_EQ(((int*)ccv_array_get(idx, 0))[0], ((int*)ccv_array_get(idx, 1))[0], "element 1, 2 should not in the same group");
95
1
  REQUIRE_NOT_EQ(((int*)ccv_array_get(idx, 0))[0], ((int*)ccv_array_get(idx, 4))[0], "element 1, 5 should not in the same group");
96
1
  REQUIRE_NOT_EQ(((int*)ccv_array_get(idx, 0))[0], ((int*)ccv_array_get(idx, 5))[0], "element 1, 6 should not in the same group");
97
1
  REQUIRE_NOT_EQ(((int*)ccv_array_get(idx, 0))[0], ((int*)ccv_array_get(idx, 6))[0], "element 1, 7 should not in the same group");
98
1
  REQUIRE_NOT_EQ(((int*)ccv_array_get(idx, 1))[0], ((int*)ccv_array_get(idx, 4))[0], "element 2, 5 should not in the same group");
99
1
  REQUIRE_NOT_EQ(((int*)ccv_array_get(idx, 1))[0], ((int*)ccv_array_get(idx, 5))[0], "element 2, 6 should not in the same group");
100
1
  REQUIRE_NOT_EQ(((int*)ccv_array_get(idx, 1))[0], ((int*)ccv_array_get(idx, 6))[0], "element 2, 7 should not in the same group");
101
1
  REQUIRE_NOT_EQ(((int*)ccv_array_get(idx, 4))[0], ((int*)ccv_array_get(idx, 5))[0], "element 5, 6 should not in the same group");
102
1
  REQUIRE_NOT_EQ(((int*)ccv_array_get(idx, 4))[0], ((int*)ccv_array_get(idx, 6))[0], "element 5, 7 should not in the same group");
103
1
  REQUIRE_NOT_EQ(((int*)ccv_array_get(idx, 5))[0], ((int*)ccv_array_get(idx, 6))[0], "element 6, 7 should not in the same group");
104
1
  ccv_array_free(array);
105
1
  ccv_array_free(idx);
106
1
}
107
108
TEST_CASE("specific sparse matrix insertion")
109
1
{
110
1
  ccv_sparse_matrix_t* mat = ccv_sparse_matrix_new(1, 70, CCV_32S | CCV_C1, CCV_SPARSE_ROW_MAJOR, 0);
111
1
  const int k = 1;
112
1
  int idx[] = {26, 29, 30, 34, 35, 38, 39, 42, 43, 47, 48, 51, 52, 55, 56, 60, 61, 65, 66, 68, 69};
113
1
  int i;
114
22
  for (i = 0; i < sizeof(idx) / sizeof(int); 
i++21
)
115
21
    ccv_set_sparse_matrix_cell(mat, 0, idx[i], &k);
116
22
  for (i = 0; i < sizeof(idx) / sizeof(int); 
i++21
)
117
21
  {
118
21
    ccv_numeric_data_t cell = ccv_get_sparse_matrix_cell(mat, 0, idx[i]);
119
21
    REQUIRE(cell.u8 != 0, "cell at (%d, %d) doesn't contain any valid value", 0, idx[i]);
120
21
    REQUIRE_EQ(1, cell.i32[0], "cell at (%d, %d) doesn't match inserted value", 0, idx[i]);
121
21
  }
122
1
  ccv_matrix_free(mat);
123
1
}
124
125
TEST_CASE("sparse matrix basic insertion")
126
1
{
127
1
  ccv_sparse_matrix_t* mat = ccv_sparse_matrix_new(1000, 1000, CCV_32S | CCV_C1, CCV_SPARSE_ROW_MAJOR, 0);
128
1
  int i, j, k, n;
129
1
  k = 0;
130
1.00k
  for (i = 0; i < 1000; 
i++1.00k
)
131
1.00M
    
for (j = 0; 1.00k
j < 1000;
j++1.00M
)
132
1.00M
    {
133
1.00M
      ccv_set_sparse_matrix_cell(mat, i, j, &k);
134
1.00M
      k++;
135
1.00M
    }
136
1
  REQUIRE_EQ(1597, mat->size, "sparse matrix column size should be the prime number 1597");
137
101
  for (n = 0; n < 100; 
n++100
)
138
100
  {
139
100
    k = 0;
140
100k
    for (i = 0; i < 1000; 
i++100k
)
141
100M
      
for (j = 0; 100k
j < 1000;
j++100M
)
142
100M
      {
143
100M
        ccv_numeric_data_t cell = ccv_get_sparse_matrix_cell(mat, i, j);
144
100M
        REQUIRE(cell.u8 != 0, "cell at (%d, %d) doesn't contain any valid value", i, j);
145
100M
        REQUIRE_EQ(k, cell.i32[0], "cell at (%d, %d) doesn't match inserted value", i, j);
146
100M
        k++;
147
100M
      }
148
100
  }
149
1
  ccv_matrix_free(mat);
150
1
}
151
152
TEST_CASE("compress sparse matrix")
153
1
{
154
1
  ccv_sparse_matrix_t* mat = ccv_sparse_matrix_new(3, 3, CCV_32F | CCV_C1, CCV_SPARSE_ROW_MAJOR, 0);
155
1
  float cell;
156
1
  cell = 1.0;
157
1
  ccv_set_sparse_matrix_cell(mat, 0, 0, &cell);
158
1
  cell = 2.0;
159
1
  ccv_set_sparse_matrix_cell(mat, 0, 2, &cell);
160
1
  cell = 3.0;
161
1
  ccv_set_sparse_matrix_cell(mat, 1, 2, &cell);
162
1
  cell = 4.0;
163
1
  ccv_set_sparse_matrix_cell(mat, 2, 0, &cell);
164
1
  cell = 5.0;
165
1
  ccv_set_sparse_matrix_cell(mat, 2, 1, &cell);
166
1
  cell = 6.0;
167
1
  ccv_set_sparse_matrix_cell(mat, 2, 2, &cell);
168
1
  ccv_compressed_sparse_matrix_t* csm = 0;
169
1
  ccv_compress_sparse_matrix(mat, &csm);
170
1
  float dm[6] = {1, 2, 3, 4, 5, 6};
171
1
  int di[6] = {0, 2, 2, 0, 1, 2};
172
1
  REQUIRE_EQ(6, csm->nnz, "compress to non-zero factor of 6");
173
1
  REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, dm, csm->data.f32, 6, 1e-6, "actual element value should be the same");
174
1
  REQUIRE_ARRAY_EQ(int, di, csm->index, 6, "element index of CSR");
175
1
  REQUIRE_EQ(3, csm->rows, "compress should have the same number of rows (CSR)");
176
1
  int df[4] = {0, 2, 3, 6};
177
1
  REQUIRE_ARRAY_EQ(int, df, csm->offset, 4, "offset of leading element in each row");
178
1
  ccv_sparse_matrix_t* smt = 0;
179
1
  ccv_decompress_sparse_matrix(csm, &smt);
180
1
  float m[3][3] = {{1, 0, 2}, {0, 0, 3}, {4, 5, 6}};
181
1
  int i, j;
182
4
  for (i = 0; i < 3; 
i++3
)
183
12
    
for (j = 0; 3
j < 3;
j++9
)
184
9
    {
185
9
      ccv_numeric_data_t cell = ccv_get_sparse_matrix_cell(smt, i, j);
186
9
      REQUIRE_EQ_WITH_TOLERANCE(m[i][j], (cell.u8 != 0) ? cell.f32[0] : 0, 1e-6, "should have the same matrix after decompressed at row %d, col %d", i, j);
187
9
    }
188
1
  ccv_matrix_free(smt);
189
1
  ccv_matrix_free(mat);
190
1
  ccv_matrix_free(csm);
191
1
}
192
193
TEST_CASE("loop over sparse matrix")
194
1
{
195
1
  ccv_sparse_matrix_t* mat = ccv_sparse_matrix_new(1000, 1000, CCV_32F | CCV_C1, CCV_SPARSE_ROW_MAJOR, 0);
196
1
  ccv_dense_matrix_t* a = ccv_dense_matrix_new(1000, 1000, CCV_32F | CCV_C1, 0, 0);
197
1
  ccv_zero(a);
198
1
  ccv_dense_matrix_t* b = ccv_dense_matrix_new(1000, 1000, CCV_32F | CCV_C1, 0, 0);
199
1
  ccv_zero(b);
200
1
  dsfmt_t dsfmt;
201
1
  dsfmt_init_gen_rand(&dsfmt, 0xdead);
202
1
  sfmt_t sfmt;
203
1
  sfmt_init_gen_rand(&sfmt, 0xbeef);
204
1
  int i;
205
51
  for (i = 0; i < 50; 
i++50
)
206
50
  {
207
50
    int x = sfmt_genrand_uint32(&sfmt) % 1000;
208
50
    int y = sfmt_genrand_uint32(&sfmt) % 1000;
209
50
    float v = dsfmt_genrand_close_open(&dsfmt);
210
50
    a->data.f32[y * 1000 + x] = v;
211
50
    ccv_set_sparse_matrix_cell(mat, y, x, &v);
212
50
  }
213
50
#define block(y, x, v) { b->data.f32[y * 1000 + x] = ((float*)v)[0]; }
214
50
  
CCV_SPARSE_FOREACH1
(mat, block);
215
1
#undef block
216
1
  REQUIRE_MATRIX_EQ(a, b, "matrix should be exactly equal when looped over the sparse one");
217
1
  ccv_matrix_free(mat);
218
1
  ccv_matrix_free(a);
219
1
  ccv_matrix_free(b);
220
1
}
221
222
TEST_CASE("loop over column major sparse matrix")
223
1
{
224
1
  ccv_sparse_matrix_t* mat = ccv_sparse_matrix_new(1000, 1000, CCV_32F | CCV_C1, CCV_SPARSE_COL_MAJOR, 0);
225
1
  ccv_dense_matrix_t* a = ccv_dense_matrix_new(1000, 1000, CCV_32F | CCV_C1, 0, 0);
226
1
  ccv_zero(a);
227
1
  ccv_dense_matrix_t* b = ccv_dense_matrix_new(1000, 1000, CCV_32F | CCV_C1, 0, 0);
228
1
  ccv_zero(b);
229
1
  dsfmt_t dsfmt;
230
1
  dsfmt_init_gen_rand(&dsfmt, 0xdead);
231
1
  sfmt_t sfmt;
232
1
  sfmt_init_gen_rand(&sfmt, 0xbeef);
233
1
  int i;
234
201
  for (i = 0; i < 200; 
i++200
)
235
200
  {
236
200
    int x = sfmt_genrand_uint32(&sfmt) % 1000;
237
200
    int y = sfmt_genrand_uint32(&sfmt) % 1000;
238
200
    float v = dsfmt_genrand_close_open(&dsfmt);
239
200
    a->data.f32[y * 1000 + x] = v;
240
200
    ccv_set_sparse_matrix_cell(mat, y, x, &v);
241
200
  }
242
200
#define block(y, x, v) { b->data.f32[y * 1000 + x] = ((float*)v)[0]; }
243
200
  
CCV_SPARSE_FOREACH1
(mat, block);
244
1
#undef block
245
1
  REQUIRE_MATRIX_EQ(a, b, "matrix should be exactly equal when looped over the sparse one");
246
1
  ccv_matrix_free(mat);
247
1
  ccv_matrix_free(a);
248
1
  ccv_matrix_free(b);
249
1
}
250
251
TEST_CASE("loop over sparse matrix with dense vector")
252
1
{
253
1
  ccv_sparse_matrix_t* mat = ccv_sparse_matrix_new(1000, 1000, CCV_32F | CCV_C1 | CCV_DENSE_VECTOR, CCV_SPARSE_ROW_MAJOR, 0);
254
1
  ccv_dense_matrix_t* a = ccv_dense_matrix_new(1000, 1000, CCV_32F | CCV_C1, 0, 0);
255
1
  ccv_zero(a);
256
1
  ccv_dense_matrix_t* b = ccv_dense_matrix_new(1000, 1000, CCV_32F | CCV_C1, 0, 0);
257
1
  ccv_zero(b);
258
1
  dsfmt_t dsfmt;
259
1
  dsfmt_init_gen_rand(&dsfmt, 0xdead);
260
1
  sfmt_t sfmt;
261
1
  sfmt_init_gen_rand(&sfmt, 0xbeef);
262
1
  int i;
263
201
  for (i = 0; i < 200; 
i++200
)
264
200
  {
265
200
    int x = sfmt_genrand_uint32(&sfmt) % 1000;
266
200
    int y = sfmt_genrand_uint32(&sfmt) % 1000;
267
200
    float v = dsfmt_genrand_close_open(&dsfmt);
268
200
    a->data.f32[y * 1000 + x] = v;
269
200
    ccv_set_sparse_matrix_cell(mat, y, x, &v);
270
200
  }
271
182k
#define block(y, x, v) { b->data.f32[y * 1000 + x] = ((float*)v)[0]; }
272
182k
  
CCV_SPARSE_FOREACH1
(mat, block);
273
1
#undef block
274
1
  REQUIRE_MATRIX_EQ(a, b, "matrix should be exactly equal when looped over the sparse one");
275
1
  ccv_matrix_free(mat);
276
1
  ccv_matrix_free(a);
277
1
  ccv_matrix_free(b);
278
1
}
279
280
TEST_CASE("loop over sparse matrix vector")
281
1
{
282
1
  ccv_sparse_matrix_t* mat = ccv_sparse_matrix_new(1000, 1000, CCV_32F | CCV_C1, CCV_SPARSE_ROW_MAJOR, 0);
283
1
  ccv_dense_matrix_t* a = ccv_dense_matrix_new(1, 1000, CCV_32F | CCV_C1, 0, 0);
284
1
  ccv_zero(a);
285
1
  ccv_dense_matrix_t* b = ccv_dense_matrix_new(1, 1000, CCV_32F | CCV_C1, 0, 0);
286
1
  ccv_zero(b);
287
1
  dsfmt_t dsfmt;
288
1
  dsfmt_init_gen_rand(&dsfmt, 0xdead);
289
1
  sfmt_t sfmt;
290
1
  sfmt_init_gen_rand(&sfmt, 0xbeef);
291
1
  int i;
292
51
  for (i = 0; i < 50; 
i++50
)
293
50
  {
294
50
    int x = sfmt_genrand_uint32(&sfmt) % 1000;
295
50
    float v = dsfmt_genrand_close_open(&dsfmt);
296
50
    a->data.f32[x] = v;
297
50
    ccv_set_sparse_matrix_cell(mat, 38, x, &v);
298
50
  }
299
1
  ccv_sparse_matrix_vector_t* vector = ccv_get_sparse_matrix_vector(mat, 38);
300
48
#define block(x, v) { b->data.f32[x] = ((float*)v)[0]; }
301
48
  
CCV_SPARSE_VECTOR_FOREACH1
(mat, vector, block);
302
1
#undef block
303
1
  REQUIRE_MATRIX_EQ(a, b, "matrix should be exactly equal when looped over the sparse one");
304
1
  ccv_matrix_free(mat);
305
1
  ccv_matrix_free(a);
306
1
  ccv_matrix_free(b);
307
1
}
308
309
TEST_CASE("loop over sparse matrix dense vector")
310
1
{
311
1
  ccv_sparse_matrix_t* mat = ccv_sparse_matrix_new(1000, 1000, CCV_32F | CCV_C1 | CCV_DENSE_VECTOR, CCV_SPARSE_ROW_MAJOR, 0);
312
1
  ccv_dense_matrix_t* a = ccv_dense_matrix_new(1, 1000, CCV_32F | CCV_C1, 0, 0);
313
1
  ccv_zero(a);
314
1
  ccv_dense_matrix_t* b = ccv_dense_matrix_new(1, 1000, CCV_32F | CCV_C1, 0, 0);
315
1
  ccv_zero(b);
316
1
  dsfmt_t dsfmt;
317
1
  dsfmt_init_gen_rand(&dsfmt, 0xdead);
318
1
  sfmt_t sfmt;
319
1
  sfmt_init_gen_rand(&sfmt, 0xbeef);
320
1
  int i;
321
201
  for (i = 0; i < 200; 
i++200
)
322
200
  {
323
200
    int x = sfmt_genrand_uint32(&sfmt) % 1000;
324
200
    float v = dsfmt_genrand_close_open(&dsfmt);
325
200
    a->data.f32[x] = v;
326
200
    ccv_set_sparse_matrix_cell(mat, 38, x, &v);
327
200
  }
328
1
  ccv_sparse_matrix_vector_t* vector = ccv_get_sparse_matrix_vector(mat, 38);
329
1.00k
#define block(x, v) { b->data.f32[x] = ((float*)v)[0]; }
330
1.00k
  
CCV_SPARSE_VECTOR_FOREACH1
(mat, vector, block);
331
1
#undef block
332
1
  REQUIRE_MATRIX_EQ(a, b, "matrix should be exactly equal when looped over the sparse one");
333
1
  ccv_matrix_free(mat);
334
1
  ccv_matrix_free(a);
335
1
  ccv_matrix_free(b);
336
1
}
337
338
#ifdef HAVE_LIBPNG
339
TEST_CASE("matrix slice")
340
1
{
341
1
  ccv_dense_matrix_t* image = 0;
342
1
  ccv_read("../../samples/chessbox.png", &image, CCV_IO_ANY_FILE);
343
1
  ccv_dense_matrix_t* b = 0;
344
1
  ccv_slice(image, (ccv_matrix_t**)&b, 0, 33, 41, 111, 91);
345
1
  REQUIRE_MATRIX_FILE_EQ(b, "data/chessbox.slice.bin", "should have data/chessbox.png sliced at (33, 41) with 111 x 91");
346
1
  ccv_matrix_free(image);
347
1
  ccv_matrix_free(b);
348
1
}
349
#endif
350
351
TEST_CASE("matrix flatten")
352
1
{
353
1
  ccv_dense_matrix_t* dmt = ccv_dense_matrix_new(2, 2, CCV_8U | CCV_C2, 0, 0);
354
1
  dmt->data.u8[0] = 200;
355
1
  dmt->data.u8[1] = 100;
356
1
  dmt->data.u8[2] = 150;
357
1
  dmt->data.u8[3] = 50;
358
1
  dmt->data.u8[4] = 25;
359
1
  dmt->data.u8[5] = 20;
360
1
  dmt->data.u8[6] = 200;
361
1
  dmt->data.u8[7] = 250;
362
1
  ccv_dense_matrix_t* result = 0;
363
1
  ccv_flatten(dmt, (ccv_matrix_t**)&result, 0, 0);
364
1
  ccv_matrix_free(dmt);
365
1
  int rf[4] = {300, 200, 45, 450};
366
1
  REQUIRE_EQ(CCV_GET_CHANNEL(result->type), CCV_C1, "flatten matrix should have only one channel");
367
1
  REQUIRE_ARRAY_EQ(int, result->data.i32, rf, 4, "matrix flatten should have same value as reference array");
368
1
  ccv_matrix_free(result);
369
1
}
370
371
TEST_CASE("matrix reshape")
372
1
{
373
1
  ccv_dense_matrix_t* dmt = ccv_dense_matrix_new(2, 4, CCV_32S | CCV_C1, 0, 0);
374
1
  dmt->data.i32[0] = 200;
375
1
  dmt->data.i32[1] = 100;
376
1
  dmt->data.i32[2] = 150;
377
1
  dmt->data.i32[3] = 50;
378
1
  dmt->data.i32[4] = 25;
379
1
  dmt->data.i32[5] = 20;
380
1
  dmt->data.i32[6] = 200;
381
1
  dmt->data.i32[7] = 250;
382
1
  ccv_dense_matrix_t sub = ccv_reshape(dmt, 0, 2, 2, 2);
383
1
  ccv_dense_matrix_t* a = ccv_dense_matrix_new(2, 2, CCV_32S | CCV_C1, 0, 0);
384
1
  a->data.i32[0] = 100;
385
1
  a->data.i32[1] = 100;
386
1
  a->data.i32[2] = 100;
387
1
  a->data.i32[3] = 100;
388
1
  ccv_subtract(a, &sub, (ccv_matrix_t**)&a, 0);
389
1
  int rf[4] = {-50, 50, -100, -150};
390
1
  REQUIRE_ARRAY_EQ(int, a->data.i32, rf, 4, "matrix subtract a reshaped matrix should have same value as reference array");
391
1
  ccv_matrix_free(a);
392
1
  ccv_matrix_free(dmt);
393
1
}
394
395
TEST_CASE("matrix border")
396
1
{
397
1
  ccv_dense_matrix_t* dmt = ccv_dense_matrix_new(1, 1, CCV_32F | CCV_C1, 0, 0);
398
1
  dmt->data.f32[0] = 2.0;
399
1
  ccv_dense_matrix_t* result = 0;
400
1
  ccv_margin_t margin = ccv_margin(2, 3, 1, 2);
401
1
  ccv_border(dmt, (ccv_matrix_t**)&result, 0, margin);
402
1
  ccv_matrix_free(dmt);
403
1
  float rf[24] = {
404
1
    0, 0, 0, 0,
405
1
    0, 0, 0, 0,
406
1
    0, 0, 0, 0,
407
1
    0, 0, 2, 0,
408
1
    0, 0, 0, 0,
409
1
    0, 0, 0, 0,
410
1
  };
411
1
  REQUIRE_EQ(margin.top + margin.bottom + 1, result->rows, "bordered matrix should have margin.top + margin.bottom + 1 rows");
412
1
  REQUIRE_EQ(margin.left + margin.right + 1, result->cols, "bordered matrix should have margin.left + margin.right + 1 cols");
413
1
  REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, result->data.f32, rf, 24, 1e-5, "matrix border should have same value as reference array");
414
1
  ccv_matrix_free(result);
415
1
}
416
417
TEST_CASE("half precision and float-point conversion")
418
1
{
419
1
  uint16_t* h = (uint16_t*)ccmalloc(sizeof(uint16_t) * 0x10000);
420
1
  float* f = (float*)ccmalloc(sizeof(float) * 0x10000);
421
1
  uint16_t* b = (uint16_t*)ccmalloc(sizeof(uint16_t) * 0x10000);
422
1
  float* c = (float*)ccmalloc(sizeof(float) * 0x10000);
423
1
  int i;
424
65.5k
  for (i = 0; i < 0x10000; 
i++65.5k
)
425
65.5k
    h[i] = i;
426
1
  ccv_half_precision_to_float(h, f, 0x10000);
427
1
  ccv_float_to_half_precision(f, b, 0x10000);
428
1
  REQUIRE_ARRAY_EQ(uint16_t, h, b, 0x10000, "half precision convert to float and then convert back should match exactly");
429
2.05k
  for (i = 0; i <= 2048; 
i++2.04k
)
430
2.04k
    f[i] = i;
431
1
  ccv_float_to_half_precision(f, h, 2049);
432
1
  ccv_half_precision_to_float(h, c, 2049);
433
1
  REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, f, c, 2049, 1e-5, "0-2048 integer to half precision and convert back should match exactly");
434
4.09k
  for (i = 4097; i <= 8192; 
i++4.09k
)
435
4.09k
    f[i - 4097] = i;
436
1
  ccv_float_to_half_precision(f, h, 8192 - 4097 + 1);
437
1
  ccv_half_precision_to_float(h, c, 8192 - 4097 + 1);
438
1
  REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, f, c, 8192 - 4097 + 1, 4 + 1e-5, "4097-8192 integer to half precision and convert back should round to multiple of 4");
439
1
  ccfree(h);
440
1
  ccfree(f);
441
1
  ccfree(b);
442
1
  ccfree(c);
443
1
}
444
445
#include "case_main.h"