## Coverage Report

#### Created: 2026-05-04 15:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /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.00kj < 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; 100kj < 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; 3j < 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"