Coverage Report

Created: 2024-12-02 18:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/liu/actions-runner/_work/ccv/ccv/lib/ccv_util.c
Line
Count
Source
1
#include "ccv.h"
2
#include "ccv_internal.h"
3
4
ccv_dense_matrix_t* ccv_get_dense_matrix(ccv_matrix_t* mat)
5
309k
{
6
309k
  int type = *(int*)mat;
7
309k
  if (type & CCV_MATRIX_DENSE)
8
309k
    return (ccv_dense_matrix_t*)mat;
9
0
  return 0;
10
309k
}
11
12
ccv_sparse_matrix_t* ccv_get_sparse_matrix(ccv_matrix_t* mat)
13
0
{
14
0
  int type = *(int*)mat;
15
0
  if (type & CCV_MATRIX_SPARSE)
16
0
    return (ccv_sparse_matrix_t*)mat;
17
0
  return 0;
18
0
}
19
20
void ccv_visualize(ccv_matrix_t* a, ccv_matrix_t** b, int type)
21
0
{
22
0
  ccv_dense_matrix_t* da = ccv_get_dense_matrix(a);
23
0
  ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_literal("ccv_visualize"), da->sig, CCV_EOF_SIGN);
24
0
  ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows, da->cols, CCV_8U | CCV_C1, CCV_8U | CCV_C1, sig);
25
0
  ccv_object_return_if_cached(, db);
26
0
  ccv_dense_matrix_t* dc = 0;
27
0
  if (CCV_GET_CHANNEL(da->type) > CCV_C1)
28
0
  {
29
0
    ccv_flatten(da, (ccv_matrix_t**)&dc, 0, 0);
30
0
    da = dc;
31
0
  }
32
0
  int i, j;
33
0
  double minval = DBL_MAX, maxval = -DBL_MAX;
34
0
  unsigned char* aptr = da->data.u8;
35
0
  unsigned char* bptr = db->data.u8;
36
0
#define for_block(_, _for_get) \
37
0
  for (i = 0; i < da->rows; i++) \
38
0
  { \
39
0
    for (j = 0; j < da->cols; j++) \
40
0
    { \
41
0
      minval = ccv_min(minval, _for_get(aptr, j)); \
42
0
      maxval = ccv_max(maxval, _for_get(aptr, j)); \
43
0
    } \
44
0
    aptr += da->step; \
45
0
  } \
46
0
  aptr = da->data.u8; \
47
0
  for (i = 0; i < da->rows; i++) \
48
0
  { \
49
0
    for (j = 0; j < da->cols; j++) \
50
0
      bptr[j] = ccv_clamp((_for_get(aptr, j) - minval) * 255.0 / (maxval - minval), 0, 255); \
51
0
    aptr += da->step; \
52
0
    bptr += db->step; \
53
0
  }
54
0
  ccv_matrix_getter(da->type, for_block);
55
0
#undef for_block
56
0
  if (dc != 0)
57
0
    ccv_matrix_free(dc);
58
0
}
59
60
void ccv_zero(ccv_matrix_t* mat)
61
209
{
62
209
  ccv_dense_matrix_t* dmt = ccv_get_dense_matrix(mat);
63
209
  memset(dmt->data.u8, 0, dmt->step * dmt->rows);
64
209
}
65
66
int ccv_any_nan(ccv_matrix_t *a)
67
150k
{
68
150k
  ccv_dense_matrix_t* da = ccv_get_dense_matrix(a);
69
150k
  assert((da->type & CCV_32F) || (da->type & CCV_64F));
70
150k
  int ch = CCV_GET_CHANNEL(da->type);
71
150k
  int i;
72
150k
  if (da->type & CCV_32F)
73
150k
  {
74
461M
    for (i = 0; i < da->rows * da->cols * ch; 
i++460M
)
75
#ifdef isnanf
76
      if (isnanf(da->data.f32[i]))
77
#else
78
460M
      if (isnan(da->data.f32[i]))
79
0
#endif
80
0
        return i + 1;
81
150k
  } else {
82
0
    for (i = 0; i < da->rows * da->cols * ch; i++)
83
0
      if (isnan(da->data.f64[i]))
84
0
        return i + 1;
85
0
  }
86
150k
  return 0;
87
150k
}
88
89
void ccv_flatten(ccv_matrix_t* a, ccv_matrix_t** b, int type, int flag)
90
1
{
91
1
  ccv_dense_matrix_t* da = ccv_get_dense_matrix(a);
92
1
  ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_format(64, "ccv_flatten(%d)", flag), da->sig, CCV_EOF_SIGN);
93
1
  int no_8u_type = (da->type & CCV_8U) ? CCV_32S : 
da->type0
;
94
1
  type = (type == 0) ? CCV_GET_DATA_TYPE(no_8u_type) | CCV_C1 : 
CCV_GET_DATA_TYPE0
(type) | CCV_C10
;
95
1
  ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_C1, type, sig);
96
1
  ccv_object_return_if_cached(, db);
97
1
  int i, j, k, ch = CCV_GET_CHANNEL(da->type);
98
1
  unsigned char* aptr = da->data.u8;
99
1
  unsigned char* bptr = db->data.u8;
100
1
#define for_block(_for_get, _for_type, _for_set) \
101
3
  
for (i = 0; 1
i < da->rows;
i++2
) \
102
2
  { \
103
6
    for (j = 0; j < da->cols; 
j++4
) \
104
4
    { \
105
4
      _for_type sum = 0; \
106
12
      for (k = 0; k < ch; 
k++8
) \
107
8
        sum += 
_for_get4
(aptr, j * ch + k); \
108
4
      _for_set(bptr, j, sum); \
109
4
    } \
110
2
    aptr += da->step; \
111
2
    bptr += db->step; \
112
2
  }
113
1
  ccv_matrix_getter(da->type, ccv_matrix_typeof_setter, db->type, for_block);
114
1
#undef for_block
115
1
}
116
117
void ccv_border(ccv_matrix_t* a, ccv_matrix_t** b, int type, ccv_margin_t margin)
118
1
{
119
1
  ccv_dense_matrix_t* da = ccv_get_dense_matrix(a);
120
1
  ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_format(64, "ccv_border(%d,%d,%d,%d)", margin.left, margin.top, margin.right, margin.bottom), da->sig, CCV_EOF_SIGN);
121
1
  int ch = CCV_GET_CHANNEL(da->type);
122
1
  type = (type == 0) ? CCV_GET_DATA_TYPE(da->type) | ch : 
CCV_GET_DATA_TYPE0
(type) | ch0
;
123
1
  ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows + margin.top + margin.bottom, da->cols + margin.left + margin.right, CCV_ALL_DATA_TYPE | ch, type, sig);
124
1
  ccv_object_return_if_cached(, db);
125
1
  ccv_zero(db);
126
1
  int i, j;
127
1
  unsigned char* aptr = da->data.u8;
128
1
  unsigned char* bptr = db->data.u8 + margin.top * db->step + margin.left * ch * CCV_GET_DATA_TYPE_SIZE(db->type);
129
1
  if (CCV_GET_DATA_TYPE(da->type) == CCV_GET_DATA_TYPE(db->type))
130
1
  {
131
    // use memcpy to speedup
132
1
    size_t scan = da->cols * ch * CCV_GET_DATA_TYPE_SIZE(da->type);
133
2
    for (i = 0; i < da->rows; 
i++1
)
134
1
    {
135
1
      memcpy(bptr, aptr, scan);
136
1
      aptr += da->step;
137
1
      bptr += db->step;
138
1
    }
139
1
  } else {
140
0
#define for_block(_for_get, _for_type, _for_set) \
141
0
    for (i = 0; i < da->rows; i++) \
142
0
    { \
143
0
      for (j = 0; j < da->cols * ch; j++) \
144
0
      { \
145
0
        _for_set(bptr, j, _for_get(aptr, j)); \
146
0
      } \
147
0
      aptr += da->step; \
148
0
      bptr += db->step; \
149
0
    }
150
0
    ccv_matrix_getter(da->type, ccv_matrix_typeof_setter, db->type, for_block);
151
0
#undef for_block
152
0
  }
153
1
}
154
155
void ccv_shift(ccv_matrix_t* a, ccv_matrix_t** b, int type, int lr, int rr)
156
10
{
157
10
  ccv_dense_matrix_t* da = ccv_get_dense_matrix(a);
158
10
  ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_format(64, "ccv_shift(%d,%d)", lr, rr), da->sig, CCV_EOF_SIGN);
159
10
  type = (type == 0) ? 
CCV_GET_DATA_TYPE0
(da->type) | 0
CCV_GET_CHANNEL0
(da->type) : CCV_GET_DATA_TYPE(type) | CCV_GET_CHANNEL(da->type);
160
10
  ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(da->type), type, sig); 
161
10
  ccv_object_return_if_cached(, db);
162
10
  int i, j, ch = CCV_GET_CHANNEL(da->type);
163
10
  unsigned char* aptr = da->data.u8;
164
10
  unsigned char* bptr = db->data.u8;
165
10
#define for_block(_for_get, _for_set) \
166
5.21k
  
for (i = 0; 10
i < da->rows;
i++5.20k
) \
167
5.20k
  { \
168
8.88M
    for (j = 0; j < da->cols * ch; 
j++8.88M
) \
169
8.88M
    { \
170
8.88M
      _for_set(bptr, j, _for_get(aptr, j, lr), rr); \
171
8.88M
    } \
172
5.20k
    aptr += da->step; \
173
5.20k
    bptr += db->step; \
174
5.20k
  }
175
10
  ccv_matrix_getter(da->type, ccv_matrix_setter, db->type, for_block);
176
10
#undef for_block
177
10
}
178
179
// From https://github.com/skarupke/flat_hash_map with anything overflows 32bit removed.
180
static uint32_t _ccv_sparse_matrix_index_for_hash(const uint32_t hash, const int prime_index)
181
209M
{
182
209M
  switch(prime_index)
183
209M
  {
184
0
  case 0:
185
0
    return 0u;
186
344k
  case 1:
187
344k
    return hash % 2u;
188
0
  case 2:
189
0
    return hash % 3u;
190
718k
  case 3:
191
718k
    return hash % 5u;
192
0
  case 4:
193
0
    return hash % 7u;
194
535k
  case 5:
195
535k
    return hash % 11u;
196
0
  case 6:
197
0
    return hash % 13u;
198
0
  case 7:
199
0
    return hash % 17u;
200
357k
  case 8:
201
357k
    return hash % 23u;
202
0
  case 9:
203
0
    return hash % 29u;
204
0
  case 10:
205
0
    return hash % 37u;
206
604k
  case 11:
207
604k
    return hash % 47u;
208
0
  case 12:
209
0
    return hash % 59u;
210
0
  case 13:
211
0
    return hash % 73u;
212
886k
  case 14:
213
886k
    return hash % 97u;
214
0
  case 15:
215
0
    return hash % 127u;
216
0
  case 16:
217
0
    return hash % 151u;
218
920k
  case 17:
219
920k
    return hash % 197u;
220
0
  case 18:
221
0
    return hash % 251u;
222
0
  case 19:
223
0
    return hash % 313u;
224
948k
  case 20:
225
948k
    return hash % 397u;
226
0
  case 21:
227
0
    return hash % 499u;
228
0
  case 22:
229
0
    return hash % 631u;
230
2.41M
  case 23:
231
2.41M
    return hash % 797u;
232
0
  case 24:
233
0
    return hash % 1009u;
234
0
  case 25:
235
0
    return hash % 1259u;
236
201M
  case 26:
237
201M
    return hash % 1597u;
238
0
  case 27:
239
0
    return hash % 2011u;
240
0
  case 28:
241
0
    return hash % 2539u;
242
0
  case 29:
243
0
    return hash % 3203u;
244
0
  case 30:
245
0
    return hash % 4027u;
246
0
  case 31:
247
0
    return hash % 5087u;
248
0
  case 32:
249
0
    return hash % 6421u;
250
0
  case 33:
251
0
    return hash % 8089u;
252
0
  case 34:
253
0
    return hash % 10193u;
254
0
  case 35:
255
0
    return hash % 12853u;
256
0
  case 36:
257
0
    return hash % 16193u;
258
0
  case 37:
259
0
    return hash % 20399u;
260
0
  case 38:
261
0
    return hash % 25717u;
262
0
  case 39:
263
0
    return hash % 32401u;
264
0
  case 40:
265
0
    return hash % 40823u;
266
0
  case 41:
267
0
    return hash % 51437u;
268
0
  case 42:
269
0
    return hash % 64811u;
270
0
  case 43:
271
0
    return hash % 81649u;
272
0
  case 44:
273
0
    return hash % 102877u;
274
0
  case 45:
275
0
    return hash % 129607u;
276
0
  case 46:
277
0
    return hash % 163307u;
278
0
  case 47:
279
0
    return hash % 205759u;
280
0
  case 48:
281
0
    return hash % 259229u;
282
0
  case 49:
283
0
    return hash % 326617u;
284
0
  case 50:
285
0
    return hash % 411527u;
286
0
  case 51:
287
0
    return hash % 518509u;
288
0
  case 52:
289
0
    return hash % 653267u;
290
0
  case 53:
291
0
    return hash % 823117u;
292
0
  case 54:
293
0
    return hash % 1037059u;
294
0
  case 55:
295
0
    return hash % 1306601u;
296
0
  case 56:
297
0
    return hash % 1646237u;
298
0
  case 57:
299
0
    return hash % 2074129u;
300
0
  case 58:
301
0
    return hash % 2613229u;
302
0
  case 59:
303
0
    return hash % 3292489u;
304
0
  case 60:
305
0
    return hash % 4148279u;
306
0
  case 61:
307
0
    return hash % 5226491u;
308
0
  case 62:
309
0
    return hash % 6584983u;
310
0
  case 63:
311
0
    return hash % 8296553u;
312
0
  case 64:
313
0
    return hash % 10453007u;
314
0
  case 65:
315
0
    return hash % 13169977u;
316
0
  case 66:
317
0
    return hash % 16593127u;
318
0
  case 67:
319
0
    return hash % 20906033u;
320
0
  case 68:
321
0
    return hash % 26339969u;
322
0
  case 69:
323
0
    return hash % 33186281u;
324
0
  case 70:
325
0
    return hash % 41812097u;
326
0
  case 71:
327
0
    return hash % 52679969u;
328
0
  case 72:
329
0
    return hash % 66372617u;
330
0
  case 73:
331
0
    return hash % 83624237u;
332
0
  case 74:
333
0
    return hash % 105359939u;
334
0
  case 75:
335
0
    return hash % 132745199u;
336
0
  case 76:
337
0
    return hash % 167248483u;
338
0
  case 77:
339
0
    return hash % 210719881u;
340
0
  case 78:
341
0
    return hash % 265490441u;
342
0
  case 79:
343
0
    return hash % 334496971u;
344
0
  case 80:
345
0
    return hash % 421439783u;
346
0
  case 81:
347
0
    return hash % 530980861u;
348
0
  case 82:
349
0
    return hash % 668993977u;
350
0
  case 83:
351
0
    return hash % 842879579u;
352
0
  case 84:
353
0
    return hash % 1061961721u;
354
0
  case 85:
355
0
    return hash % 1337987929u;
356
0
  case 86:
357
0
    return hash % 1685759167u;
358
0
  case 87:
359
0
    return hash % 2123923447u;
360
0
  case 88:
361
0
    return hash % 2675975881u;
362
0
  case 89:
363
0
    return hash % 3371518343u;
364
0
  case 90:
365
0
    return hash % 4247846927u;
366
0
  case 91:
367
0
    return hash % 4294967291u;
368
0
  default:
369
0
    return hash;
370
209M
  }
371
209M
}
372
373
// prime numbers generated by the following method:
374
// 1. start with a prime p = 2
375
// 2. go to wolfram alpha and get p = NextPrime(2 * p)
376
// 3. repeat 2. until you overflow 32 bits
377
// you now have large gaps which you would hit if somebody called reserve() with an unlucky number.
378
// 4. to fill the gaps for every prime p go to wolfram alpha and get ClosestPrime(p * 2^(1/3)) and ClosestPrime(p * 2^(2/3)) and put those in the gaps
379
// 5. get PrevPrime(2^32) and put it at the end
380
const static uint32_t _ccv_sparse_prime[] =
381
{
382
  2u, 3u, 5u, 7u, 11u, 13u, 17u, 23u, 29u, 37u, 47u,
383
  59u, 73u, 97u, 127u, 151u, 197u, 251u, 313u, 397u,
384
  499u, 631u, 797u, 1009u, 1259u, 1597u, 2011u, 2539u,
385
  3203u, 4027u, 5087u, 6421u, 8089u, 10193u, 12853u, 16193u,
386
  20399u, 25717u, 32401u, 40823u, 51437u, 64811u, 81649u,
387
  102877u, 129607u, 163307u, 205759u, 259229u, 326617u,
388
  411527u, 518509u, 653267u, 823117u, 1037059u, 1306601u,
389
  1646237u, 2074129u, 2613229u, 3292489u, 4148279u, 5226491u,
390
  6584983u, 8296553u, 10453007u, 13169977u, 16593127u, 20906033u,
391
  26339969u, 33186281u, 41812097u, 52679969u, 66372617u,
392
  83624237u, 105359939u, 132745199u, 167248483u, 210719881u,
393
  265490441u, 334496971u, 421439783u, 530980861u, 668993977u,
394
  842879579u, 1061961721u, 1337987929u, 1685759167u, 2123923447u,
395
  2675975881u, 3371518343u, 4247846927u, 4294967291u
396
};
397
398
static uint8_t _ccv_sparse_matrix_index_next_size_over(const uint32_t size)
399
126k
{
400
126k
  int i;
401
126k
  assert(sizeof(_ccv_sparse_prime) / sizeof(uint32_t) == 91);
402
694k
  
for (i = 0; 126k
i < sizeof(_ccv_sparse_prime) / sizeof(uint32_t);
i++567k
)
403
694k
    if (_ccv_sparse_prime[i] > size)
404
126k
      return i + 1;
405
0
  return sizeof(_ccv_sparse_prime) / sizeof(uint32_t) + 1;
406
126k
}
407
408
static uint32_t _ccv_sparse_matrix_size_for_index(const int prime_index)
409
126k
{
410
126k
  return _ccv_sparse_prime[prime_index - 1];
411
126k
}
412
413
static void _ccv_init_sparse_matrix_vector(ccv_sparse_matrix_vector_t* vector, const ccv_sparse_matrix_t* const mat)
414
93.4k
{
415
93.4k
  if (mat->type & CCV_DENSE_VECTOR)
416
183
  {
417
183
    const int vlen = (mat->major == CCV_SPARSE_COL_MAJOR) ? 
mat->rows0
: mat->cols;
418
183
    const size_t cell_size = CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type);
419
183
    vector->size = vlen;
420
183
    vector->data.u8 = (uint8_t*)cccalloc(1, (cell_size * vlen + 15) & -16);
421
183
    return;
422
183
  }
423
93.2k
  vector->prime_index = 1; // See ccv_util.c to know why this is 1 and why size is 2.
424
93.2k
  vector->size = 2;
425
93.2k
  vector->rnum = 0;
426
93.2k
  const size_t cell_size_aligned = (CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type) + 3) & -4;
427
93.2k
  vector->index = (ccv_sparse_matrix_index_t*)cccalloc(sizeof(ccv_sparse_matrix_index_t) + cell_size_aligned, vector->size);
428
93.2k
}
429
430
static inline void _ccv_move_sparse_matrix_vector(ccv_sparse_matrix_index_t* const index, ccv_sparse_matrix_vector_t* const vector, const ccv_sparse_matrix_t* const mat, uint32_t k, uint32_t idx, int i, const uint32_t size, const int prime_index)
431
3.95k
{
432
3.95k
  uint32_t old_i = index[idx].i;
433
3.95k
  index[idx].i = i;
434
3.95k
  i = old_i;
435
3.95k
  ccv_sparse_matrix_vector_t val = vector[idx];
436
3.95k
  _ccv_init_sparse_matrix_vector(vector + idx, mat);
437
  // Move to next idx, this is already occupied.
438
3.95k
  ++k;
439
3.95k
  ++idx;
440
49.8k
  for (; k < 255; 
++idx, ++k45.8k
)
441
49.8k
  {
442
49.8k
    if (idx >= size)
443
56
      idx = 0;
444
49.8k
    if (!index[idx].ifbit)
445
3.95k
    {
446
3.95k
      index[idx].ifbit = k;
447
3.95k
      index[idx].i = i;
448
3.95k
      vector[idx] = val;
449
3.95k
      return;
450
3.95k
    }
451
45.8k
    uint32_t j = index[idx].ifbit;
452
45.8k
    if (k > j)
453
38.7k
    {
454
38.7k
      index[idx].ifbit = k;
455
38.7k
      k = j;
456
38.7k
      uint32_t old_i = index[idx].i;
457
38.7k
      index[idx].i = i;
458
38.7k
      i = old_i;
459
38.7k
      ccv_sparse_matrix_vector_t old_val = vector[idx];
460
38.7k
      vector[idx] = val;
461
38.7k
      val = old_val;
462
38.7k
    }
463
45.8k
  }
464
0
  for (;; ++idx, ++k)
465
0
  {
466
0
    if (idx >= size)
467
0
      idx = 0;
468
0
    if (!index[idx].ifbit)
469
0
    {
470
0
      index[idx].ifbit = k > 0xff ? 0xff : k;
471
0
      index[idx].i = i;
472
0
      vector[idx] = val;
473
0
      return;
474
0
    }
475
0
    uint32_t j = index[idx].ifbit;
476
0
    if (j == 0xff)
477
0
      j = (size - _ccv_sparse_matrix_index_for_hash(index[idx].i + size - idx, prime_index)) + 2;
478
0
    if (k > j)
479
0
    {
480
0
      index[idx].ifbit = k > 0xff ? 0xff : k;
481
0
      k = j;
482
0
      uint32_t old_i = index[idx].i;
483
0
      index[idx].i = i;
484
0
      i = old_i;
485
0
      ccv_sparse_matrix_vector_t old_val = vector[idx];
486
0
      vector[idx] = val;
487
0
      val = old_val;
488
0
    }
489
0
  }
490
0
}
491
492
static ccv_sparse_matrix_vector_t* _ccv_get_or_add_sparse_matrix_vector(ccv_sparse_matrix_t* mat, int i)
493
1.55M
{
494
1.55M
  const uint32_t size = mat->size;
495
1.55M
  ccv_sparse_matrix_index_t* const index = mat->index;
496
1.55M
  ccv_sparse_matrix_vector_t* const vector = mat->vector;
497
1.55M
  const int prime_index = mat->prime_index;
498
1.55M
  uint32_t idx = _ccv_sparse_matrix_index_for_hash(i, prime_index);
499
1.55M
  uint32_t k = 2;
500
2.26M
  for (; k < 255; 
++idx, ++k714k
)
501
2.26M
  {
502
2.26M
    if (idx >= size)
503
125
      idx = 0;
504
2.26M
    uint32_t j = index[idx].ifbit;
505
2.26M
    if (k > j)
506
93.4k
    {
507
93.4k
      ++mat->rnum;
508
93.4k
      index[idx].ifbit = k;
509
93.4k
      if (!j)
510
89.4k
      {
511
89.4k
        index[idx].i = i;
512
89.4k
        _ccv_init_sparse_matrix_vector(vector + idx, mat);
513
89.4k
      } else
514
3.95k
        _ccv_move_sparse_matrix_vector(index, vector, mat, j /* This is j not k because we are replacing it. */, idx, i, size, prime_index);
515
93.4k
      return vector + idx;
516
93.4k
    }
517
2.17M
    if (index[idx].i == i)
518
1.45M
      return vector + idx;
519
2.17M
  }
520
  // Above or equal to 255, we need to fetch the key to recompute the distance every time now.
521
0
  for (;; ++idx, ++k)
522
0
  {
523
0
    if (idx >= size)
524
0
      idx = 0;
525
0
    uint32_t j = index[idx].ifbit;
526
0
    if (j == 0xff)
527
0
      j = (size - _ccv_sparse_matrix_index_for_hash(index[idx].i + size - idx, prime_index)) + 2;
528
0
    if (k > j)
529
0
    {
530
0
      ++mat->rnum;
531
0
      index[idx].ifbit = k > 0xff ? 0xff : k;
532
0
      if (!j)
533
0
      {
534
0
        index[idx].i = i;
535
0
        _ccv_init_sparse_matrix_vector(vector + idx, mat);
536
0
      } else
537
0
        _ccv_move_sparse_matrix_vector(index, vector, mat, j /* This is j not k because we are replacing it. */, idx, i, size, prime_index);
538
0
      return vector + idx;
539
0
    }
540
0
    if (index[idx].i == i)
541
0
      return vector + idx;
542
0
  }
543
0
  return 0;
544
0
}
545
546
ccv_sparse_matrix_vector_t* ccv_get_sparse_matrix_vector(const ccv_sparse_matrix_t* mat, int i)
547
102M
{
548
102M
  const uint32_t size = mat->size;
549
102M
  ccv_sparse_matrix_index_t* index = mat->index;
550
102M
  ccv_sparse_matrix_vector_t* vector = mat->vector;
551
102M
  const int prime_index = mat->prime_index;
552
102M
  uint32_t idx = _ccv_sparse_matrix_index_for_hash(i, prime_index);
553
102M
  uint32_t k = 2;
554
105M
  for (; k < 255; 
++idx, ++k3.68M
)
555
105M
  {
556
105M
    if (idx >= size)
557
375
      idx = 0;
558
105M
    if (k > index[idx].ifbit)
559
548k
      return 0;
560
105M
    if (index[idx].i == i)
561
101M
      return vector + idx;
562
105M
  }
563
  // Above or equal to 255, we need to fetch the key to recompute the distance every time now.
564
0
  for (;; ++idx, ++k)
565
0
  {
566
0
    if (idx >= size)
567
0
      idx = 0;
568
0
    uint32_t j = index[idx].ifbit;
569
0
    if (j == 0xff)
570
0
      j = (size - _ccv_sparse_matrix_index_for_hash(index[idx].i + size - idx, prime_index)) + 2;
571
0
    if (k > j)
572
0
      return 0;
573
0
    if (index[idx].i == i)
574
0
      return vector + idx;
575
0
  }
576
0
  return 0;
577
0
}
578
579
ccv_numeric_data_t ccv_get_sparse_matrix_cell_from_vector(const ccv_sparse_matrix_t* mat, ccv_sparse_matrix_vector_t* vector, int vidx)
580
101M
{
581
101M
  ccv_numeric_data_t cell = {}; // zero-init.
582
101M
  const size_t cell_size = CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type);
583
101M
  if (mat->type & CCV_DENSE_VECTOR)
584
0
  {
585
0
    cell.u8 = vector->data.u8 + cell_size * vidx;
586
0
    return cell;
587
0
  }
588
101M
  const size_t cell_size_aligned = (CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type) + 3) & -4;
589
101M
  const size_t index_size = sizeof(ccv_sparse_matrix_index_t) + cell_size_aligned;
590
101M
  const uint32_t size = vector->size;
591
101M
  uint8_t* const index = (uint8_t*)vector->index;
592
101M
  const int prime_index = vector->prime_index;
593
101M
  uint32_t idx = _ccv_sparse_matrix_index_for_hash(vidx, prime_index);
594
101M
  uint32_t k = 2;
595
102M
  for (; k < 255; 
++idx, ++k976k
)
596
102M
  {
597
102M
    if (idx >= size)
598
42.2k
      idx = 0;
599
102M
    ccv_sparse_matrix_index_t* const index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx);
600
102M
    if (k > index_idx->ifbit)
601
1.31M
      return cell;
602
101M
    if (index_idx->i == vidx)
603
100M
    {
604
100M
      cell.u8 = (uint8_t*)(index_idx + 1);
605
100M
      return cell;
606
100M
    }
607
101M
  }
608
  // Above or equal to 255, we need to fetch the key to recompute the distance every time now.
609
0
  for (;; ++idx, ++k)
610
0
  {
611
0
    if (idx >= size)
612
0
      idx = 0;
613
0
    ccv_sparse_matrix_index_t* const index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx);
614
0
    uint32_t j = index_idx->ifbit;
615
0
    if (j == 0xff)
616
0
      j = (size - _ccv_sparse_matrix_index_for_hash(index_idx->i + size - idx, prime_index)) + 2;
617
0
    if (k > j)
618
0
      return cell;
619
0
    if (index_idx->i == vidx)
620
0
    {
621
0
      cell.u8 = (uint8_t*)(index_idx + 1);
622
0
      return cell;
623
0
    }
624
0
  }
625
0
}
626
627
ccv_numeric_data_t ccv_get_sparse_matrix_cell(const ccv_sparse_matrix_t* mat, int row, int col)
628
101M
{
629
101M
  ccv_sparse_matrix_vector_t* vector = ccv_get_sparse_matrix_vector(mat, (mat->major == CCV_SPARSE_COL_MAJOR) ? 
col0
: row);
630
101M
  if (!vector || 
!vector->rnum101M
)
631
498k
    return (ccv_numeric_data_t){};
632
101M
  const int vidx = (mat->major == CCV_SPARSE_COL_MAJOR) ? 
row0
: col;
633
101M
  return ccv_get_sparse_matrix_cell_from_vector(mat, vector, vidx);
634
101M
}
635
636
static void _ccv_sparse_matrix_vector_inc_size(const ccv_sparse_matrix_t* const mat, ccv_sparse_matrix_vector_t* const vector)
637
100k
{
638
100k
  assert(vector->prime_index >= 0 && vector->prime_index < sizeof(_ccv_sparse_prime) / sizeof(int));
639
100k
  const uint32_t size = vector->size;
640
100k
  const int prime_index = vector->prime_index = _ccv_sparse_matrix_index_next_size_over(size * 2);
641
100k
  const uint32_t new_size = vector->size = _ccv_sparse_matrix_size_for_index(vector->prime_index);
642
100k
  assert(vector->prime_index >= 0 && vector->prime_index < sizeof(_ccv_sparse_prime) / sizeof(int));
643
100k
  const size_t cell_size_aligned = (CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type) + 3) & -4;
644
100k
  const size_t index_size = sizeof(ccv_sparse_matrix_index_t) + cell_size_aligned;
645
100k
  const size_t cell_rnum = cell_size_aligned / sizeof(uint32_t);
646
100k
  vector->index = (ccv_sparse_matrix_index_t*)ccrealloc(vector->index, index_size * new_size);
647
100k
  uint8_t* const index = (uint8_t*)vector->index;
648
100k
  memset(index + index_size * size, 0, index_size * (new_size - size));
649
100k
  uint32_t i, h;
650
2.55M
  for (i = 0; i < size; 
i++2.45M
)
651
2.45M
  {
652
2.45M
    ccv_sparse_matrix_index_t* index_i = (ccv_sparse_matrix_index_t*)(index + index_size * i);
653
2.45M
    index_i->ifbit = !!index_i->ifbit; // Mark this as need to be moved around.
654
2.45M
  }
655
2.55M
  for (i = 0; i < size; 
i++2.45M
)
656
2.45M
  {
657
2.45M
    ccv_sparse_matrix_index_t* index_i = (ccv_sparse_matrix_index_t*)(index + index_size * i);
658
2.45M
    if (index_i->ifbit == 1) // Encountered one need to be moved.
659
1.86M
    {
660
1.86M
      index_i->ifbit = 0;
661
      // This item is from old hash table, need to find a new location for it.
662
1.86M
      uint32_t key = index_i->i;
663
1.86M
      uint32_t* val = (uint32_t*)(index_i + 1);
664
1.86M
      uint32_t k = 2;
665
1.86M
      uint32_t idx = _ccv_sparse_matrix_index_for_hash(key, prime_index);
666
2.07M
      for (; k < 255; 
++idx, ++k204k
)
667
2.07M
      {
668
2.07M
        if (idx >= new_size)
669
541
          idx = 0;
670
2.07M
        ccv_sparse_matrix_index_t* index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx);
671
2.07M
        uint32_t j = index_idx->ifbit;
672
2.07M
        if (!j)
673
1.86M
        {
674
1.86M
          index_idx->ifbit = k;
675
1.86M
          index_idx->i = key;
676
1.86M
          memcpy(index_idx + 1, val, cell_size_aligned);
677
1.86M
          break;
678
1.86M
        }
679
204k
        if (k <= j) // j could be either a valid one or 1, in any case, this will pass.
680
136k
          continue;
681
67.7k
        index_idx->ifbit = k;
682
67.7k
        uint32_t old_key = index_idx->i;
683
67.7k
        index_idx->i = key;
684
67.7k
        key = old_key;
685
67.7k
        uint32_t* old_val = (uint32_t*)(index_idx + 1);
686
136k
        for (h = 0; h < cell_rnum; 
h++68.7k
)
687
68.7k
        {
688
68.7k
          uint32_t v = old_val[h];
689
68.7k
          old_val[h] = val[h];
690
68.7k
          val[h] = v;
691
68.7k
        }
692
67.7k
        if (j != 1)
693
25.7k
          k = j;
694
42.0k
        else { // In this case, I cannot keep going with the idx, need to recompute idx as well restart k.
695
42.0k
          idx = _ccv_sparse_matrix_index_for_hash(key, prime_index) - 1;
696
42.0k
          k = 1; // Restart.
697
42.0k
        }
698
67.7k
      }
699
1.86M
      if (k < 255)
700
1.86M
        continue;
701
0
      for (;; ++idx, ++k)
702
0
      {
703
0
        if (idx >= new_size)
704
0
          idx = 0;
705
0
        ccv_sparse_matrix_index_t* index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx);
706
0
        uint32_t j = index_idx->ifbit;
707
0
        if (!j)
708
0
        {
709
0
          index_idx->ifbit = k > 0xff ? 0xff : k;
710
0
          index_idx->i = key;
711
0
          memcpy(index_idx + 1, val, cell_size_aligned);
712
0
          break;
713
0
        }
714
0
        if (j == 0xff)
715
0
          j = (new_size - _ccv_sparse_matrix_index_for_hash((index_idx->i + new_size - idx), prime_index)) + 2; // This is valid because on overflow, unsigned is well defined.
716
0
        if (k <= j) // j could be either a valid one or 1, in any case, this will pass.
717
0
          continue;
718
0
        index_idx->ifbit = k > 0xff ? 0xff : k;
719
0
        uint32_t old_key = index_idx->i;
720
0
        index_idx->i = key;
721
0
        key = old_key;
722
0
        uint32_t* old_val = (uint32_t*)(index_idx + 1);
723
0
        for (h = 0; h < cell_rnum; h++)
724
0
        {
725
0
          uint32_t v = old_val[h];
726
0
          old_val[h] = val[h];
727
0
          val[h] = v;
728
0
        }
729
0
        if (j != 1)
730
0
          k = j;
731
0
        else { // In this case, I cannot keep going with the idx, need to recompute idx as well restart k.
732
0
          idx = _ccv_sparse_matrix_index_for_hash(key, prime_index) - 1;
733
0
          k = 1; // Restart.
734
0
        }
735
0
      }
736
0
    }
737
2.45M
  }
738
100k
}
739
740
static void _ccv_sparse_matrix_inc_size(ccv_sparse_matrix_t* mat)
741
26.6k
{
742
26.6k
  assert(mat->prime_index >= 0 && mat->prime_index < sizeof(_ccv_sparse_prime) / sizeof(int));
743
26.6k
  const uint32_t size = mat->size;
744
26.6k
  const int prime_index = mat->prime_index = _ccv_sparse_matrix_index_next_size_over(size * 2);
745
26.6k
  const uint32_t new_size = mat->size = _ccv_sparse_matrix_size_for_index(mat->prime_index);
746
26.6k
  assert(mat->prime_index >= 0 && mat->prime_index < sizeof(_ccv_sparse_prime) / sizeof(int));
747
26.6k
  ccv_sparse_matrix_index_t* const index = mat->index = (ccv_sparse_matrix_index_t*)ccrealloc(mat->index, sizeof(ccv_sparse_matrix_index_t) * new_size);
748
26.6k
  memset(index + size, 0, sizeof(ccv_sparse_matrix_index_t) * (new_size - size));
749
26.6k
  ccv_sparse_matrix_vector_t* const vector = mat->vector = (ccv_sparse_matrix_vector_t*)ccrealloc(mat->vector, sizeof(ccv_sparse_matrix_vector_t) * new_size);
750
26.6k
  uint32_t i;
751
130k
  for (i = 0; i < size; 
i++104k
)
752
104k
    index[i].ifbit = !!index[i].ifbit; // Mark this as need to be moved around.
753
130k
  for (i = 0; i < size; 
i++104k
)
754
104k
    if (index[i].ifbit == 1) // Encountered one need to be moved.
755
71.5k
    {
756
71.5k
      index[i].ifbit = 0;
757
      // This item is from old hash table, need to find a new location for it.
758
71.5k
      uint32_t key = index[i].i;
759
71.5k
      ccv_sparse_matrix_vector_t val = vector[i];
760
71.5k
      uint32_t k = 2;
761
71.5k
      uint32_t idx = _ccv_sparse_matrix_index_for_hash(key, prime_index);
762
90.8k
      for (; k < 255; 
++idx, ++k19.3k
)
763
90.8k
      {
764
90.8k
        if (idx >= new_size)
765
2
          idx = 0;
766
90.8k
        uint32_t j = index[idx].ifbit;
767
90.8k
        if (!j)
768
71.5k
        {
769
71.5k
          index[idx].ifbit = k;
770
71.5k
          index[idx].i = key;
771
71.5k
          vector[idx] = val;
772
71.5k
          break;
773
71.5k
        }
774
19.3k
        if (k <= j) // j could be either a valid one or 1, in any case, this will pass.
775
16.7k
          continue;
776
2.62k
        index[idx].ifbit = k;
777
2.62k
        uint32_t old_key = index[idx].i;
778
2.62k
        index[idx].i = key;
779
2.62k
        key = old_key;
780
2.62k
        ccv_sparse_matrix_vector_t old_val = vector[idx];
781
2.62k
        vector[idx] = val;
782
2.62k
        val = old_val;
783
2.62k
        if (j != 1)
784
2.19k
          k = j;
785
429
        else { // In this case, I cannot keep going with the idx, need to recompute idx as well restart k.
786
429
          idx = _ccv_sparse_matrix_index_for_hash(key, prime_index) - 1;
787
429
          k = 1; // Restart.
788
429
        }
789
2.62k
      }
790
71.5k
      if (k < 255)
791
71.5k
        continue;
792
0
      for (;; ++idx, ++k)
793
0
      {
794
0
        if (idx >= new_size)
795
0
          idx = 0;
796
0
        uint32_t j = index[idx].ifbit;
797
0
        if (!j)
798
0
        {
799
0
          index[idx].ifbit = k > 0xff ? 0xff : k;
800
0
          index[idx].i = key;
801
0
          vector[idx] = val;
802
0
          break;
803
0
        }
804
0
        if (j == 0xff)
805
0
          j = (new_size - _ccv_sparse_matrix_index_for_hash((index[idx].i + new_size - idx), prime_index)) + 2; // This is valid because on overflow, unsigned is well defined.
806
0
        if (k <= j) // j could be either a valid one or 1, in any case, this will pass.
807
0
          continue;
808
0
        index[idx].ifbit = k > 0xff ? 0xff : k;
809
0
        uint32_t old_key = index[idx].i;
810
0
        index[idx].i = key;
811
0
        key = old_key;
812
0
        ccv_sparse_matrix_vector_t old_val = vector[idx];
813
0
        vector[idx] = val;
814
0
        val = old_val;
815
0
        if (j != 1)
816
0
          k = j;
817
0
        else { // In this case, I cannot keep going with the idx, need to recompute idx as well restart k.
818
0
          idx = _ccv_sparse_matrix_index_for_hash(key, prime_index) - 1;
819
0
          k = 1; // Restart.
820
0
        }
821
0
      }
822
0
    }
823
26.6k
}
824
825
static inline void _ccv_move_sparse_matrix_cell(uint8_t* const index, uint32_t k, uint32_t idx, int i, const uint32_t size, const int prime_index, const size_t index_size, const size_t cell_size_aligned)
826
62.1k
{
827
62.1k
  ccv_sparse_matrix_index_t* const index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx);
828
62.1k
  const size_t cell_rnum = cell_size_aligned / sizeof(uint32_t);
829
62.1k
  uint32_t* val = (uint32_t*)(index_idx + 1);
830
62.1k
  uint32_t old_i = index_idx->i;
831
62.1k
  index_idx->i = i;
832
62.1k
  i = old_i;
833
  // Move to next idx, this is already occupied.
834
62.1k
  ++k;
835
62.1k
  ++idx;
836
62.1k
  uint32_t h;
837
592k
  for (; k < 255; 
++idx, ++k530k
)
838
592k
  {
839
592k
    if (idx >= size)
840
2.39k
      idx = 0;
841
592k
    ccv_sparse_matrix_index_t* const index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx);
842
592k
    if (!index_idx->ifbit)
843
62.1k
    {
844
62.1k
      index_idx->ifbit = k;
845
62.1k
      index_idx->i = i;
846
62.1k
      memcpy(index_idx + 1, val, cell_size_aligned);
847
62.1k
      return;
848
62.1k
    }
849
530k
    uint32_t j = index_idx->ifbit;
850
530k
    if (k > j)
851
484k
    {
852
484k
      index_idx->ifbit = k;
853
484k
      k = j;
854
484k
      uint32_t old_i = index_idx->i;
855
484k
      index_idx->i = i;
856
484k
      i = old_i;
857
484k
      uint32_t* old_val = (uint32_t*)(index_idx + 1);
858
978k
      for (h = 0; h < cell_rnum; 
h++494k
)
859
494k
      {
860
494k
        uint32_t v = old_val[h];
861
494k
        old_val[h] = val[h];
862
494k
        val[h] = v;
863
494k
      }
864
484k
    }
865
530k
  }
866
0
  for (;; ++idx, ++k)
867
0
  {
868
0
    if (idx >= size)
869
0
      idx = 0;
870
0
    ccv_sparse_matrix_index_t* const index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx);
871
0
    if (!index_idx->ifbit)
872
0
    {
873
0
      index_idx->ifbit = k > 0xff ? 0xff : k;
874
0
      index_idx->i = i;
875
0
      memcpy(index_idx + 1, val, cell_size_aligned);
876
0
      return;
877
0
    }
878
0
    uint32_t j = index_idx->ifbit;
879
0
    if (j == 0xff)
880
0
      j = (size - _ccv_sparse_matrix_index_for_hash(index_idx->i + size - idx, prime_index)) + 2;
881
0
    if (k > j)
882
0
    {
883
0
      index_idx->ifbit = k > 0xff ? 0xff : k;
884
0
      k = j;
885
0
      uint32_t old_i = index_idx->i;
886
0
      index_idx->i = i;
887
0
      i = old_i;
888
0
      uint32_t* old_val = (uint32_t*)(index_idx + 1);
889
0
      for (h = 0; h < cell_rnum; h++)
890
0
      {
891
0
        uint32_t v = old_val[h];
892
0
        old_val[h] = val[h];
893
0
        val[h] = v;
894
0
      }
895
0
    }
896
0
  }
897
0
}
898
899
void ccv_set_sparse_matrix_cell_from_vector(ccv_sparse_matrix_t* mat, ccv_sparse_matrix_vector_t* const vector, int vidx, const void* data)
900
234k
{
901
234k
  const size_t cell_size = CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type);
902
234k
  if (mat->type & CCV_DENSE_VECTOR)
903
0
  {
904
0
    memcpy(vector->data.u8 + vidx * cell_size, data, cell_size);
905
0
    return;
906
0
  }
907
234k
  if ((vector->rnum + 1) * 10llu > vector->size * 8llu) // expand when reached 90%.
908
34.0k
    _ccv_sparse_matrix_vector_inc_size(mat, vector);
909
  // Align to 4 bytes.
910
234k
  const size_t cell_size_aligned = (CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type) + 3) & -4;
911
234k
  const size_t index_size = sizeof(ccv_sparse_matrix_index_t) + cell_size_aligned;
912
234k
  uint8_t* const index = (uint8_t*)vector->index;
913
234k
  const int prime_index = vector->prime_index;
914
234k
  const uint32_t size = vector->size;
915
234k
  uint32_t idx = _ccv_sparse_matrix_index_for_hash(vidx, prime_index);
916
234k
  uint32_t k = 2;
917
483k
  for (; k < 255; 
++idx, ++k249k
)
918
483k
  {
919
483k
    if (idx >= size)
920
383
      idx = 0;
921
483k
    ccv_sparse_matrix_index_t* const index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx);
922
483k
    uint32_t j = index_idx->ifbit;
923
483k
    if (k > j)
924
203k
    {
925
203k
      ++vector->rnum;
926
203k
      index_idx->ifbit = k;
927
203k
      if (!j)
928
183k
      {
929
183k
        index_idx->i = vidx;
930
        // Assign it out.
931
183k
        memcpy(index_idx + 1, data, cell_size);
932
183k
      } else {
933
19.7k
        _ccv_move_sparse_matrix_cell(index, j /* This is j not k because we are replacing it. */, idx, vidx, size, prime_index, index_size, cell_size_aligned);
934
19.7k
        memcpy(index_idx + 1, data, cell_size);
935
19.7k
      }
936
203k
      return;
937
203k
    }
938
280k
    if (index_idx->i == vidx)
939
30.8k
    {
940
30.8k
      memcpy(index_idx + 1, data, cell_size);
941
30.8k
      return;
942
30.8k
    }
943
280k
  }
944
  // Above or equal to 255, we need to fetch the key to recompute the distance every time now.
945
0
  for (;; ++idx, ++k)
946
0
  {
947
0
    if (idx >= size)
948
0
      idx = 0;
949
0
    ccv_sparse_matrix_index_t* const index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx);
950
0
    uint32_t j = index_idx->ifbit;
951
0
    if (j == 0xff)
952
0
      j = (size - _ccv_sparse_matrix_index_for_hash(index_idx->i + size - idx, prime_index)) + 2;
953
0
    if (k > j)
954
0
    {
955
0
      ++vector->rnum;
956
0
      index_idx->ifbit = k > 0xff ? 0xff : k;
957
0
      if (!j)
958
0
      {
959
0
        index_idx->i = vidx;
960
0
        memcpy(index_idx + 1, data, cell_size);
961
0
      } else {
962
0
        _ccv_move_sparse_matrix_cell(index, j /* This is j not k because we are replacing it. */, idx, vidx, size, prime_index, index_size, cell_size_aligned);
963
0
        memcpy(index_idx + 1, data, cell_size);
964
0
      }
965
0
      return;
966
0
    }
967
0
    if (index_idx->i == vidx)
968
0
    {
969
0
      memcpy(index_idx + 1, data, cell_size);
970
0
      return;
971
0
    }
972
0
  }
973
0
}
974
975
void ccv_set_sparse_matrix_cell(ccv_sparse_matrix_t* mat, int row, int col, const void* data)
976
1.55M
{
977
1.55M
  assert(data);
978
1.55M
  const int hidx = (mat->major == CCV_SPARSE_COL_MAJOR) ? 
col200
:
row1.55M
;
979
1.55M
  const int vidx = (mat->major == CCV_SPARSE_COL_MAJOR) ? 
row200
:
col1.55M
;
980
  // This will handle initialize a vector if it doesn't already exist.
981
1.55M
  if ((mat->rnum + 1) * 10llu > mat->size * 8llu) // expand when reached 90%.
982
26.6k
    _ccv_sparse_matrix_inc_size(mat);
983
1.55M
  ccv_sparse_matrix_vector_t* const vector = _ccv_get_or_add_sparse_matrix_vector(mat, hidx);
984
1.55M
  const size_t cell_size = CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type);
985
1.55M
  if (mat->type & CCV_DENSE_VECTOR)
986
400
  {
987
400
    memcpy(vector->data.u8 + vidx * cell_size, data, cell_size);
988
400
    return;
989
400
  }
990
1.55M
  if ((vector->rnum + 1) * 10llu > vector->size * 8llu) // expand when reached 90%.
991
66.2k
    _ccv_sparse_matrix_vector_inc_size(mat, vector);
992
  // Align to 4 bytes.
993
1.55M
  const size_t cell_size_aligned = (CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type) + 3) & -4;
994
1.55M
  const size_t index_size = sizeof(ccv_sparse_matrix_index_t) + cell_size_aligned;
995
1.55M
  uint8_t* const index = (uint8_t*)vector->index;
996
1.55M
  const int prime_index = vector->prime_index;
997
1.55M
  const uint32_t size = vector->size;
998
1.55M
  uint32_t idx = _ccv_sparse_matrix_index_for_hash(vidx, prime_index);
999
1.55M
  uint32_t k = 2;
1000
1.74M
  for (; k < 255; 
++idx, ++k193k
)
1001
1.74M
  {
1002
1.74M
    if (idx >= size)
1003
5.40k
      idx = 0;
1004
1.74M
    ccv_sparse_matrix_index_t* const index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx);
1005
1.74M
    uint32_t j = index_idx->ifbit;
1006
1.74M
    if (k > j)
1007
1.42M
    {
1008
1.42M
      ++vector->rnum;
1009
1.42M
      index_idx->ifbit = k;
1010
1.42M
      if (!j)
1011
1.37M
      {
1012
1.37M
        index_idx->i = vidx;
1013
        // Assign it out.
1014
1.37M
        memcpy(index_idx + 1, data, cell_size);
1015
1.37M
      } else {
1016
42.3k
        _ccv_move_sparse_matrix_cell(index, j /* This is j not k because we are replacing it. */, idx, vidx, size, prime_index, index_size, cell_size_aligned);
1017
42.3k
        memcpy(index_idx + 1, data, cell_size);
1018
42.3k
      }
1019
1.42M
      return;
1020
1.42M
    }
1021
322k
    if (index_idx->i == vidx)
1022
128k
    {
1023
128k
      memcpy(index_idx + 1, data, cell_size);
1024
128k
      return;
1025
128k
    }
1026
322k
  }
1027
  // Above or equal to 255, we need to fetch the key to recompute the distance every time now.
1028
0
  for (;; ++idx, ++k)
1029
0
  {
1030
0
    if (idx >= size)
1031
0
      idx = 0;
1032
0
    ccv_sparse_matrix_index_t* const index_idx = (ccv_sparse_matrix_index_t*)(index + index_size * idx);
1033
0
    uint32_t j = index_idx->ifbit;
1034
0
    if (j == 0xff)
1035
0
      j = (size - _ccv_sparse_matrix_index_for_hash(index_idx->i + size - idx, prime_index)) + 2;
1036
0
    if (k > j)
1037
0
    {
1038
0
      ++vector->rnum;
1039
0
      index_idx->ifbit = k > 0xff ? 0xff : k;
1040
0
      if (!j)
1041
0
      {
1042
0
        index_idx->i = vidx;
1043
0
        memcpy(index_idx + 1, data, cell_size);
1044
0
      } else {
1045
0
        _ccv_move_sparse_matrix_cell(index, j /* This is j not k because we are replacing it. */, idx, vidx, size, prime_index, index_size, cell_size_aligned);
1046
0
        memcpy(index_idx + 1, data, cell_size);
1047
0
      }
1048
0
      return;
1049
0
    }
1050
0
    if (index_idx->i == vidx)
1051
0
    {
1052
0
      memcpy(index_idx + 1, data, cell_size);
1053
0
      return;
1054
0
    }
1055
0
  }
1056
0
}
1057
1058
3
#define _ccv_indice_less_than(i1, i2, aux) ((i1) < (i2))
1059
0
#define _ccv_swap_indice_and_uchar_data(i1, i2, array, aux, t) {  \
1060
0
  unsigned char td = (aux)[(int)(&(i1) - (array))];       \
1061
0
  (aux)[(int)(&(i1) - (array))] = (aux)[(int)(&(i2) - (array))]; \
1062
0
  (aux)[(int)(&(i2) - (array))] = td;             \
1063
0
  CCV_SWAP(i1, i2, t); }
1064
0
#define _ccv_swap_indice_and_int_data(i1, i2, array, aux, t) { \
1065
0
  int td = (aux)[(int)(&(i1) - (array))];           \
1066
0
  (aux)[(int)(&(i1) - (array))] = (aux)[(int)(&(i2) - (array))]; \
1067
0
  (aux)[(int)(&(i2) - (array))] = td;             \
1068
0
  CCV_SWAP(i1, i2, t); }
1069
0
#define _ccv_swap_indice_and_float_data(i1, i2, array, aux, t) {  \
1070
0
  float td = (aux)[(int)(&(i1) - (array))];           \
1071
0
  (aux)[(int)(&(i1) - (array))] = (aux)[(int)(&(i2) - (array))]; \
1072
0
  (aux)[(int)(&(i2) - (array))] = td;             \
1073
0
  CCV_SWAP(i1, i2, t); }
1074
0
#define _ccv_swap_indice_and_double_data(i1, i2, array, aux, t) { \
1075
0
  double td = (aux)[(int)(&(i1) - (array))];           \
1076
0
  (aux)[(int)(&(i1) - (array))] = (aux)[(int)(&(i2) - (array))]; \
1077
0
  (aux)[(int)(&(i2) - (array))] = td;             \
1078
0
  CCV_SWAP(i1, i2, t); }
1079
1080
0
static CCV_IMPLEMENT_QSORT_EX(_ccv_indice_uchar_sort, int, _ccv_indice_less_than, _ccv_swap_indice_and_uchar_data, unsigned char*);
1081
0
static CCV_IMPLEMENT_QSORT_EX(_ccv_indice_int_sort, int, _ccv_indice_less_than, _ccv_swap_indice_and_int_data, int*);
1082
3
static CCV_IMPLEMENT_QSORT_EX(_ccv_indice_float_sort, int, _ccv_indice_less_than, 
_ccv_swap_indice_and_float_data0
, float*);
1083
0
static CCV_IMPLEMENT_QSORT_EX(_ccv_indice_double_sort, int, _ccv_indice_less_than, _ccv_swap_indice_and_double_data, double*);
1084
1085
void ccv_compress_sparse_matrix(const ccv_sparse_matrix_t* mat, ccv_compressed_sparse_matrix_t** csm)
1086
1
{
1087
1
  uint32_t i, j;
1088
1
  int nnz = 0;
1089
1
  const uint32_t size = mat->size;
1090
6
  for (i = 0; i < size; 
i++5
)
1091
5
  {
1092
5
    ccv_sparse_matrix_index_t* index = mat->index + i;
1093
5
    ccv_sparse_matrix_vector_t* vector = mat->vector + i;
1094
5
    if (index->ifbit <= 1 || 
!vector->rnum3
)
1095
2
      continue;
1096
3
    if (mat->type & CCV_DENSE_VECTOR)
1097
0
    {
1098
0
#define while_block(_, _while_get) \
1099
0
      for (j = 0; j < vector->rnum; j++) \
1100
0
        if (_while_get(vector->data.u8, j, 0) != 0) \
1101
0
          nnz++; \
1102
0
      ccv_matrix_getter(mat->type, while_block);
1103
0
#undef while_block
1104
0
    } else
1105
3
      nnz += vector->rnum;
1106
3
  }
1107
1
  ccv_compressed_sparse_matrix_t* cm = *csm = (ccv_compressed_sparse_matrix_t*)ccmalloc(sizeof(ccv_compressed_sparse_matrix_t) + nnz * sizeof(int) + nnz * CCV_GET_DATA_TYPE_SIZE(mat->type) + (((mat->major == CCV_SPARSE_COL_MAJOR) ? 
mat->cols0
: mat->rows) + 1) * sizeof(int));
1108
1
  cm->type = (mat->type & ~CCV_MATRIX_SPARSE & ~CCV_SPARSE_VECTOR & ~CCV_DENSE_VECTOR) | ((mat->major == CCV_SPARSE_COL_MAJOR) ? 
CCV_MATRIX_CSC0
: CCV_MATRIX_CSR);
1109
1
  cm->nnz = nnz;
1110
1
  cm->rows = mat->rows;
1111
1
  cm->cols = mat->cols;
1112
1
  cm->index = (int*)(cm + 1);
1113
1
  cm->offset = cm->index + nnz;
1114
1
  cm->data.i32 = cm->offset + ((mat->major == CCV_SPARSE_COL_MAJOR) ? 
mat->cols0
: mat->rows) + 1;
1115
1
  unsigned char* m_ptr = cm->data.u8;
1116
1
  int* idx = cm->index;
1117
1
  cm->offset[0] = 0;
1118
1
  const size_t cell_size_aligned = (CCV_GET_DATA_TYPE_SIZE(mat->type) * CCV_GET_CHANNEL(mat->type) + 3) & -4;
1119
1
  const size_t index_size = sizeof(ccv_sparse_matrix_index_t) + cell_size_aligned;
1120
4
  for (i = 0; i < ((mat->major == CCV_SPARSE_COL_MAJOR) ? 
mat->cols0
: mat->rows);
i++3
)
1121
3
  {
1122
3
    ccv_sparse_matrix_vector_t* vector = ccv_get_sparse_matrix_vector(mat, i);
1123
3
    if (!vector || !vector->rnum)
1124
0
      cm->offset[i + 1] = cm->offset[i];
1125
3
    else {
1126
3
      if (mat->type & CCV_DENSE_VECTOR)
1127
0
      {
1128
0
        int k = 0;
1129
0
#define for_block(_, _for_set, _for_get) \
1130
0
        for (j = 0; j < vector->rnum; j++) \
1131
0
          if (_for_get(vector->data.u8, j, 0) != 0) \
1132
0
          { \
1133
0
            _for_set(m_ptr, k, _for_get(vector->data.u8, j)); \
1134
0
            idx[k] = j; \
1135
0
            k++; \
1136
0
          }
1137
0
        ccv_matrix_setter_getter(mat->type, for_block);
1138
0
#undef for_block
1139
0
        cm->offset[i + 1] = cm->offset[i] + k;
1140
0
        idx += k;
1141
0
        m_ptr += k * CCV_GET_DATA_TYPE_SIZE(mat->type);
1142
3
      } else {
1143
3
        int k = 0;
1144
3
        uint8_t* const index = (uint8_t*)vector->index;
1145
3
#define for_block(_, _for_set, _for_get) \
1146
15
        
for (j = 0; 3
j < vector->size;
j++12
) \
1147
12
        { \
1148
12
          ccv_sparse_matrix_index_t* const index_j = (ccv_sparse_matrix_index_t*)(index + index_size * j); \
1149
12
          if (index_j->ifbit > 1) \
1150
12
          { \
1151
6
            _for_set(m_ptr, k, _for_get((uint8_t*)(index_j + 1), 0)); \
1152
6
            idx[k] = index_j->i; \
1153
6
            k++; \
1154
6
          } \
1155
12
        }
1156
3
        ccv_matrix_setter_getter(mat->type, for_block);
1157
3
#undef for_block
1158
3
        assert(k == vector->rnum);
1159
3
        switch (CCV_GET_DATA_TYPE(mat->type))
1160
3
        {
1161
0
          case CCV_8U:
1162
0
            _ccv_indice_uchar_sort(idx, vector->rnum, (unsigned char*)m_ptr);
1163
0
            break;
1164
0
          case CCV_32S:
1165
0
            _ccv_indice_int_sort(idx, vector->rnum, (int*)m_ptr);
1166
0
            break;
1167
3
          case CCV_32F:
1168
3
            _ccv_indice_float_sort(idx, vector->rnum, (float*)m_ptr);
1169
3
            break;
1170
0
          case CCV_64F:
1171
0
            _ccv_indice_double_sort(idx, vector->rnum, (double*)m_ptr);
1172
0
            break;
1173
3
        }
1174
3
        cm->offset[i + 1] = cm->offset[i] + vector->rnum;
1175
3
        idx += vector->rnum;
1176
3
        m_ptr += vector->rnum * CCV_GET_DATA_TYPE_SIZE(mat->type);
1177
3
      }
1178
3
    }
1179
3
  }
1180
1
}
1181
1182
void ccv_decompress_sparse_matrix(const ccv_compressed_sparse_matrix_t* csm, ccv_sparse_matrix_t** smt)
1183
1
{
1184
1
  ccv_sparse_matrix_t* mat = *smt = ccv_sparse_matrix_new(csm->rows, csm->cols, csm->type & ~CCV_MATRIX_CSR & ~CCV_MATRIX_CSC, (csm->type & CCV_MATRIX_CSR) ? CCV_SPARSE_ROW_MAJOR : 
CCV_SPARSE_COL_MAJOR0
, 0);
1185
1
  int i, j;
1186
4
  for (i = 0; i < ((mat->major == CCV_SPARSE_COL_MAJOR) ? 
mat->cols0
: mat->rows);
i++3
)
1187
9
    
for (j = csm->offset[i]; 3
j < csm->offset[i + 1];
j++6
)
1188
6
      if (mat->major == CCV_SPARSE_COL_MAJOR)
1189
0
        ccv_set_sparse_matrix_cell(mat, csm->index[j], i, csm->data.u8 + CCV_GET_DATA_TYPE_SIZE(csm->type) * j);
1190
6
      else
1191
6
        ccv_set_sparse_matrix_cell(mat, i, csm->index[j], csm->data.u8 + CCV_GET_DATA_TYPE_SIZE(csm->type) * j);
1192
1
}
1193
1194
int ccv_matrix_eq(ccv_matrix_t* a, ccv_matrix_t* b)
1195
201
{
1196
201
  int a_type = *(int*)a;
1197
201
  int b_type = *(int*)b;
1198
201
  if ((a_type & CCV_MATRIX_DENSE) && (b_type & CCV_MATRIX_DENSE))
1199
201
  {
1200
201
    ccv_dense_matrix_t* da = (ccv_dense_matrix_t*)a;
1201
201
    ccv_dense_matrix_t* db = (ccv_dense_matrix_t*)b;
1202
201
    if (CCV_GET_DATA_TYPE(da->type) != CCV_GET_DATA_TYPE(db->type))
1203
0
      return -1;
1204
201
    if (CCV_GET_CHANNEL(da->type) != CCV_GET_CHANNEL(db->type))
1205
0
      return -1;
1206
201
    if (da->rows != db->rows)
1207
0
      return -1;
1208
201
    if (da->cols != db->cols)
1209
0
      return -1;
1210
201
    int i, j, ch = CCV_GET_CHANNEL(da->type);
1211
201
    unsigned char* a_ptr = da->data.u8;
1212
201
    unsigned char* b_ptr = db->data.u8;
1213
    // Read: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1214
    // http://floating-point-gui.de/errors/comparison/
1215
201
    if (CCV_GET_DATA_TYPE(db->type) == CCV_32F)
1216
167
    {
1217
167
      static const float epsi = FLT_EPSILON;
1218
167
      static const int32_t ulps = 128; // So that for 1 and 1.000015 will be treated as the same.
1219
13.8k
      for (i = 0; i < da->rows; 
i++13.7k
)
1220
13.7k
      {
1221
13.7k
        int32_t* ia_ptr = (int32_t*)a_ptr;
1222
13.7k
        int32_t* ib_ptr = (int32_t*)b_ptr;
1223
32.0M
        for (j = 0; j < da->cols * ch; 
j++32.0M
)
1224
32.0M
        {
1225
32.0M
          int32_t i32a = ia_ptr[j];
1226
32.0M
          if (i32a < 0)
1227
25.1k
            i32a = 0x80000000 - i32a;
1228
32.0M
          int32_t i32b = ib_ptr[j];
1229
32.0M
          if (i32b < 0)
1230
25.1k
            i32b = 0x80000000 - i32b;
1231
32.0M
          if (abs(i32a - i32b) > ulps && 
fabsf(((float*)a_ptr)[j] - ((float*)b_ptr)[j]) > epsi0
)
1232
0
            return -1;
1233
32.0M
        }
1234
13.7k
        a_ptr += da->step;
1235
13.7k
        b_ptr += db->step;
1236
13.7k
      }
1237
167
    } else 
if (34
CCV_GET_DATA_TYPE34
(db->type) == CCV_64F34
) {
1238
1
      static const double epsi = FLT_EPSILON; // Using FLT_EPSILON because for most of ccv computations, we have 32-bit float point computation inside.
1239
1
      static const int64_t ulps = 0x100000l; // So that for 1 and 1.000000001 will be treated as the same.
1240
254
      for (i = 0; i < da->rows; 
i++253
)
1241
253
      {
1242
253
        int64_t* ia_ptr = (int64_t*)a_ptr;
1243
253
        int64_t* ib_ptr = (int64_t*)b_ptr;
1244
144k
        for (j = 0; j < da->cols * ch; 
j++144k
)
1245
144k
        {
1246
144k
          int64_t i64a = ia_ptr[j];
1247
144k
          if (i64a < 0)
1248
0
            i64a = 0x8000000000000000l - i64a;
1249
144k
          int64_t i64b = ib_ptr[j];
1250
144k
          if (i64b < 0)
1251
0
            i64b = 0x8000000000000000l - i64b;
1252
144k
          if (llabs(i64a - i64b) > ulps && 
fabsf(((float*)a_ptr)[j] - ((float*)b_ptr)[j]) > epsi1
)
1253
0
            return -1;
1254
144k
        }
1255
253
        a_ptr += da->step;
1256
253
        b_ptr += db->step;
1257
253
      }
1258
33
    } else {
1259
33
#define for_block(_, _for_get) \
1260
17.8k
      
for (i = 0; 33
i < da->rows;
i++17.8k
) \
1261
17.8k
      { \
1262
38.5M
        for (j = 0; j < da->cols * ch; 
j++38.4M
) \
1263
38.4M
        { \
1264
38.4M
          if (llabs(_for_get(b_ptr, j) - _for_get(a_ptr, j)) > 1) \
1265
38.4M
            
return -10
; \
1266
38.4M
        } \
1267
17.8k
        a_ptr += da->step; \
1268
17.8k
        b_ptr += db->step; \
1269
17.8k
      }
1270
33
      ccv_matrix_getter_integer_only(da->type, for_block);
1271
33
#undef for_block
1272
33
    }
1273
201
  }
1274
201
  return 0;
1275
201
}
1276
1277
void ccv_slice(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int y, int x, int rows, int cols)
1278
150k
{
1279
150k
  int type = *(int*)a;
1280
150k
  if (type & CCV_MATRIX_DENSE)
1281
150k
  {
1282
150k
    ccv_dense_matrix_t* da = ccv_get_dense_matrix(a);
1283
150k
    ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_format(128, "ccv_slice(%d,%d,%d,%d)", y, x, rows, cols), da->sig, CCV_EOF_SIGN);
1284
150k
    btype = (btype == 0) ? 
CCV_GET_DATA_TYPE150k
(da->type) | 150k
CCV_GET_CHANNEL150k
(da->type) :
CCV_GET_DATA_TYPE1
(btype) | 1
CCV_GET_CHANNEL1
(da->type);
1285
150k
    ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, rows, cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(da->type), btype, sig);
1286
150k
    ccv_object_return_if_cached(, db);
1287
150k
    int i, j, ch = CCV_GET_CHANNEL(da->type);
1288
150k
    int dx = 0, dy = 0;
1289
150k
    if (!(y >= 0 && 
y + rows <= da->rows150k
&&
x >= 0150k
&&
x + cols <= da->cols150k
))
1290
1
    {
1291
1
      ccv_zero(db);
1292
1
      if (y < 0) { rows += y; dy = -y; y = 0; }
1293
1
      if (y + rows > da->rows) rows = da->rows - y;
1294
1
      if (x < 0) 
{ cols += x; dx = -x; x = 0; }0
1295
1
      if (x + cols > da->cols) 
cols = da->cols - x0
;
1296
1
    }
1297
150k
    unsigned char* a_ptr = da->data.u8 + x * ch * CCV_GET_DATA_TYPE_SIZE(da->type) + y * da->step;
1298
150k
    unsigned char* b_ptr = db->data.u8 + dx * ch * CCV_GET_DATA_TYPE_SIZE(db->type) + dy * db->step;
1299
150k
#define for_block(_for_set, _for_get) \
1300
4.95M
    
for (i = 0; 150k
i < rows;
i++4.80M
) \
1301
4.80M
    { \
1302
466M
      for (j = 0; j < cols * ch; 
j++461M
) \
1303
461M
      { \
1304
461M
        _for_set(b_ptr, j, _for_get(a_ptr, j)); \
1305
461M
      } \
1306
4.80M
      a_ptr += da->step; \
1307
4.80M
      b_ptr += db->step; \
1308
4.80M
    }
1309
150k
    ccv_matrix_setter(db->type, ccv_matrix_getter, da->type, for_block);
1310
150k
#undef for_block
1311
150k
  } else 
if (0
type & CCV_MATRIX_SPARSE0
) {
1312
0
  }
1313
150k
}
1314
1315
ccv_dense_matrix_t ccv_reshape(ccv_dense_matrix_t* a, int y, int x, int rows, int cols)
1316
1
{
1317
1
  assert(y + rows <= a->rows);
1318
1
  assert(x + cols <= a->cols);
1319
1
  assert(x >= 0 && y >= 0);
1320
1
  ccv_dense_matrix_t b = {
1321
1
    .type = (CCV_UNMANAGED | CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) | CCV_NO_DATA_ALLOC | CCV_MATRIX_DENSE) & ~CCV_GARBAGE,
1322
1
    .rows = rows,
1323
1
    .cols = cols,
1324
1
    .step = a->step,
1325
1
    .refcount = 0,
1326
1
    .sig = 0,
1327
1
    .tb.u8 = 0,
1328
1
    .data.u8 = ccv_get_dense_matrix_cell(a, y, x, 0),
1329
1
  };
1330
1
  return b;
1331
1
}
1332
1333
void ccv_move(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int y, int x)
1334
0
{
1335
0
  int type = *(int*)a;
1336
0
  if (type & CCV_MATRIX_DENSE)
1337
0
  {
1338
0
    ccv_dense_matrix_t* da = ccv_get_dense_matrix(a);
1339
0
    ccv_declare_derived_signature(sig, da->sig != 0, ccv_sign_with_format(64, "ccv_move(%d,%d)", y, x), da->sig, CCV_EOF_SIGN);
1340
0
    btype = (btype == 0) ? CCV_GET_DATA_TYPE(da->type) | CCV_GET_CHANNEL(da->type) : CCV_GET_DATA_TYPE(btype) | CCV_GET_CHANNEL(da->type);
1341
0
    ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(da->type), btype, sig);
1342
0
    ccv_object_return_if_cached(, db);
1343
0
    int i, j, ch = CCV_GET_CHANNEL(da->type);
1344
0
    unsigned char* a_ptr = da->data.u8 + ccv_max(x, 0) * ch * CCV_GET_DATA_TYPE_SIZE(da->type) + ccv_max(y, 0) * da->step;
1345
0
    unsigned char* b_ptr = db->data.u8 + ccv_max(-x, 0) * ch * CCV_GET_DATA_TYPE_SIZE(db->type) + ccv_max(-y, 0) * db->step;
1346
0
#define for_block(_for_set, _for_get) \
1347
0
    for (i = abs(y); i < db->rows; i++) \
1348
0
    { \
1349
0
      for (j = abs(x) * ch; j < db->cols * ch; j++) \
1350
0
      { \
1351
0
        _for_set(b_ptr, j, _for_get(a_ptr, j)); \
1352
0
      } \
1353
0
      a_ptr += da->step; \
1354
0
      b_ptr += db->step; \
1355
0
    }
1356
0
    ccv_matrix_setter(db->type, ccv_matrix_getter, da->type, for_block);
1357
0
#undef for_block
1358
0
  } else if (type & CCV_MATRIX_SPARSE) {
1359
0
  }
1360
0
}
1361
1362
// the code are shamelessly copied from ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf, assuming in Public Domain
1363
1364
static uint16_t _ccv_base_table[512] = {
1365
  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1366
  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1367
  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1368
  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1369
  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1370
  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1371
  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100,
1372
  0x200, 0x400, 0x800, 0xc00, 0x1000, 0x1400, 0x1800, 0x1c00, 0x2000, 0x2400, 0x2800, 0x2c00, 0x3000, 0x3400, 0x3800, 0x3c00,
1373
  0x4000, 0x4400, 0x4800, 0x4c00, 0x5000, 0x5400, 0x5800, 0x5c00, 0x6000, 0x6400, 0x6800, 0x6c00, 0x7000, 0x7400, 0x7800, 0x7c00,
1374
  0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
1375
  0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
1376
  0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
1377
  0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
1378
  0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
1379
  0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
1380
  0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
1381
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1382
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1383
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1384
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1385
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1386
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1387
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, 0x8002, 0x8004, 0x8008, 0x8010, 0x8020, 0x8040, 0x8080, 0x8100,
1388
  0x8200, 0x8400, 0x8800, 0x8c00, 0x9000, 0x9400, 0x9800, 0x9c00, 0xa000, 0xa400, 0xa800, 0xac00, 0xb000, 0xb400, 0xb800, 0xbc00,
1389
  0xc000, 0xc400, 0xc800, 0xcc00, 0xd000, 0xd400, 0xd800, 0xdc00, 0xe000, 0xe400, 0xe800, 0xec00, 0xf000, 0xf400, 0xf800, 0xfc00,
1390
  0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
1391
  0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
1392
  0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
1393
  0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
1394
  0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
1395
  0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
1396
  0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
1397
};
1398
1399
static uint8_t _ccv_shift_table[512] = {
1400
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1401
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1402
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1403
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1404
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1405
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1406
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0xf,
1407
  0xe, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd,
1408
  0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0x18,
1409
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1410
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1411
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1412
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1413
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1414
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1415
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd,
1416
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1417
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1418
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1419
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1420
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1421
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1422
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0xf,
1423
  0xe, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd,
1424
  0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0x18,
1425
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1426
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1427
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1428
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1429
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1430
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
1431
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd,
1432
};
1433
1434
void ccv_float_to_half_precision(const float* f, uint16_t* h, size_t len)
1435
20.9M
{
1436
20.9M
  int i;
1437
20.9M
  const uint32_t* u = (const uint32_t*)f;
1438
1.04G
  for (i = 0; i < len; 
i++1.02G
)
1439
1.02G
    h[i] = _ccv_base_table[(u[i] >> 23) & 0x1ff] + ((u[i] & 0x007fffff) >> _ccv_shift_table[(u[i] >> 23) & 0x1ff]);
1440
20.9M
}
1441
1442
void ccv_double_to_half_precision(const double* f, uint16_t* h, size_t len)
1443
2
{
1444
2
  int i;
1445
258
  for (i = 0; i < len; 
i++256
)
1446
256
  {
1447
256
    union {
1448
256
      float v;
1449
256
      uint32_t p;
1450
256
    } u = { .v = (const float)f[i] };
1451
256
    h[i] = _ccv_base_table[(u.p >> 23) & 0x1ff] + ((u.p & 0x007fffff) >> _ccv_shift_table[(u.p >> 23) & 0x1ff]);
1452
256
  }
1453
2
}
1454
1455
static uint32_t _ccv_mantissa_table[2048] = {
1456
  0x0, 0x33800000, 0x34000000, 0x34400000, 0x34800000, 0x34a00000, 0x34c00000, 0x34e00000,
1457
  0x35000000, 0x35100000, 0x35200000, 0x35300000, 0x35400000, 0x35500000, 0x35600000, 0x35700000,
1458
  0x35800000, 0x35880000, 0x35900000, 0x35980000, 0x35a00000, 0x35a80000, 0x35b00000, 0x35b80000,
1459
  0x35c00000, 0x35c80000, 0x35d00000, 0x35d80000, 0x35e00000, 0x35e80000, 0x35f00000, 0x35f80000,
1460
  0x36000000, 0x36040000, 0x36080000, 0x360c0000, 0x36100000, 0x36140000, 0x36180000, 0x361c0000,
1461
  0x36200000, 0x36240000, 0x36280000, 0x362c0000, 0x36300000, 0x36340000, 0x36380000, 0x363c0000,
1462
  0x36400000, 0x36440000, 0x36480000, 0x364c0000, 0x36500000, 0x36540000, 0x36580000, 0x365c0000,
1463
  0x36600000, 0x36640000, 0x36680000, 0x366c0000, 0x36700000, 0x36740000, 0x36780000, 0x367c0000,
1464
  0x36800000, 0x36820000, 0x36840000, 0x36860000, 0x36880000, 0x368a0000, 0x368c0000, 0x368e0000,
1465
  0x36900000, 0x36920000, 0x36940000, 0x36960000, 0x36980000, 0x369a0000, 0x369c0000, 0x369e0000,
1466
  0x36a00000, 0x36a20000, 0x36a40000, 0x36a60000, 0x36a80000, 0x36aa0000, 0x36ac0000, 0x36ae0000,
1467
  0x36b00000, 0x36b20000, 0x36b40000, 0x36b60000, 0x36b80000, 0x36ba0000, 0x36bc0000, 0x36be0000,
1468
  0x36c00000, 0x36c20000, 0x36c40000, 0x36c60000, 0x36c80000, 0x36ca0000, 0x36cc0000, 0x36ce0000,
1469
  0x36d00000, 0x36d20000, 0x36d40000, 0x36d60000, 0x36d80000, 0x36da0000, 0x36dc0000, 0x36de0000,
1470
  0x36e00000, 0x36e20000, 0x36e40000, 0x36e60000, 0x36e80000, 0x36ea0000, 0x36ec0000, 0x36ee0000,
1471
  0x36f00000, 0x36f20000, 0x36f40000, 0x36f60000, 0x36f80000, 0x36fa0000, 0x36fc0000, 0x36fe0000,
1472
  0x37000000, 0x37010000, 0x37020000, 0x37030000, 0x37040000, 0x37050000, 0x37060000, 0x37070000,
1473
  0x37080000, 0x37090000, 0x370a0000, 0x370b0000, 0x370c0000, 0x370d0000, 0x370e0000, 0x370f0000,
1474
  0x37100000, 0x37110000, 0x37120000, 0x37130000, 0x37140000, 0x37150000, 0x37160000, 0x37170000,
1475
  0x37180000, 0x37190000, 0x371a0000, 0x371b0000, 0x371c0000, 0x371d0000, 0x371e0000, 0x371f0000,
1476
  0x37200000, 0x37210000, 0x37220000, 0x37230000, 0x37240000, 0x37250000, 0x37260000, 0x37270000,
1477
  0x37280000, 0x37290000, 0x372a0000, 0x372b0000, 0x372c0000, 0x372d0000, 0x372e0000, 0x372f0000,
1478
  0x37300000, 0x37310000, 0x37320000, 0x37330000, 0x37340000, 0x37350000, 0x37360000, 0x37370000,
1479
  0x37380000, 0x37390000, 0x373a0000, 0x373b0000, 0x373c0000, 0x373d0000, 0x373e0000, 0x373f0000,
1480
  0x37400000, 0x37410000, 0x37420000, 0x37430000, 0x37440000, 0x37450000, 0x37460000, 0x37470000,
1481
  0x37480000, 0x37490000, 0x374a0000, 0x374b0000, 0x374c0000, 0x374d0000, 0x374e0000, 0x374f0000,
1482
  0x37500000, 0x37510000, 0x37520000, 0x37530000, 0x37540000, 0x37550000, 0x37560000, 0x37570000,
1483
  0x37580000, 0x37590000, 0x375a0000, 0x375b0000, 0x375c0000, 0x375d0000, 0x375e0000, 0x375f0000,
1484
  0x37600000, 0x37610000, 0x37620000, 0x37630000, 0x37640000, 0x37650000, 0x37660000, 0x37670000,
1485
  0x37680000, 0x37690000, 0x376a0000, 0x376b0000, 0x376c0000, 0x376d0000, 0x376e0000, 0x376f0000,
1486
  0x37700000, 0x37710000, 0x37720000, 0x37730000, 0x37740000, 0x37750000, 0x37760000, 0x37770000,
1487
  0x37780000, 0x37790000, 0x377a0000, 0x377b0000, 0x377c0000, 0x377d0000, 0x377e0000, 0x377f0000,
1488
  0x37800000, 0x37808000, 0x37810000, 0x37818000, 0x37820000, 0x37828000, 0x37830000, 0x37838000,
1489
  0x37840000, 0x37848000, 0x37850000, 0x37858000, 0x37860000, 0x37868000, 0x37870000, 0x37878000,
1490
  0x37880000, 0x37888000, 0x37890000, 0x37898000, 0x378a0000, 0x378a8000, 0x378b0000, 0x378b8000,
1491
  0x378c0000, 0x378c8000, 0x378d0000, 0x378d8000, 0x378e0000, 0x378e8000, 0x378f0000, 0x378f8000,
1492
  0x37900000, 0x37908000, 0x37910000, 0x37918000, 0x37920000, 0x37928000, 0x37930000, 0x37938000,
1493
  0x37940000, 0x37948000, 0x37950000, 0x37958000, 0x37960000, 0x37968000, 0x37970000, 0x37978000,
1494
  0x37980000, 0x37988000, 0x37990000, 0x37998000, 0x379a0000, 0x379a8000, 0x379b0000, 0x379b8000,
1495
  0x379c0000, 0x379c8000, 0x379d0000, 0x379d8000, 0x379e0000, 0x379e8000, 0x379f0000, 0x379f8000,
1496
  0x37a00000, 0x37a08000, 0x37a10000, 0x37a18000, 0x37a20000, 0x37a28000, 0x37a30000, 0x37a38000,
1497
  0x37a40000, 0x37a48000, 0x37a50000, 0x37a58000, 0x37a60000, 0x37a68000, 0x37a70000, 0x37a78000,
1498
  0x37a80000, 0x37a88000, 0x37a90000, 0x37a98000, 0x37aa0000, 0x37aa8000, 0x37ab0000, 0x37ab8000,
1499
  0x37ac0000, 0x37ac8000, 0x37ad0000, 0x37ad8000, 0x37ae0000, 0x37ae8000, 0x37af0000, 0x37af8000,
1500
  0x37b00000, 0x37b08000, 0x37b10000, 0x37b18000, 0x37b20000, 0x37b28000, 0x37b30000, 0x37b38000,
1501
  0x37b40000, 0x37b48000, 0x37b50000, 0x37b58000, 0x37b60000, 0x37b68000, 0x37b70000, 0x37b78000,
1502
  0x37b80000, 0x37b88000, 0x37b90000, 0x37b98000, 0x37ba0000, 0x37ba8000, 0x37bb0000, 0x37bb8000,
1503
  0x37bc0000, 0x37bc8000, 0x37bd0000, 0x37bd8000, 0x37be0000, 0x37be8000, 0x37bf0000, 0x37bf8000,
1504
  0x37c00000, 0x37c08000, 0x37c10000, 0x37c18000, 0x37c20000, 0x37c28000, 0x37c30000, 0x37c38000,
1505
  0x37c40000, 0x37c48000, 0x37c50000, 0x37c58000, 0x37c60000, 0x37c68000, 0x37c70000, 0x37c78000,
1506
  0x37c80000, 0x37c88000, 0x37c90000, 0x37c98000, 0x37ca0000, 0x37ca8000, 0x37cb0000, 0x37cb8000,
1507
  0x37cc0000, 0x37cc8000, 0x37cd0000, 0x37cd8000, 0x37ce0000, 0x37ce8000, 0x37cf0000, 0x37cf8000,
1508
  0x37d00000, 0x37d08000, 0x37d10000, 0x37d18000, 0x37d20000, 0x37d28000, 0x37d30000, 0x37d38000,
1509
  0x37d40000, 0x37d48000, 0x37d50000, 0x37d58000, 0x37d60000, 0x37d68000, 0x37d70000, 0x37d78000,
1510
  0x37d80000, 0x37d88000, 0x37d90000, 0x37d98000, 0x37da0000, 0x37da8000, 0x37db0000, 0x37db8000,
1511
  0x37dc0000, 0x37dc8000, 0x37dd0000, 0x37dd8000, 0x37de0000, 0x37de8000, 0x37df0000, 0x37df8000,
1512
  0x37e00000, 0x37e08000, 0x37e10000, 0x37e18000, 0x37e20000, 0x37e28000, 0x37e30000, 0x37e38000,
1513
  0x37e40000, 0x37e48000, 0x37e50000, 0x37e58000, 0x37e60000, 0x37e68000, 0x37e70000, 0x37e78000,
1514
  0x37e80000, 0x37e88000, 0x37e90000, 0x37e98000, 0x37ea0000, 0x37ea8000, 0x37eb0000, 0x37eb8000,
1515
  0x37ec0000, 0x37ec8000, 0x37ed0000, 0x37ed8000, 0x37ee0000, 0x37ee8000, 0x37ef0000, 0x37ef8000,
1516
  0x37f00000, 0x37f08000, 0x37f10000, 0x37f18000, 0x37f20000, 0x37f28000, 0x37f30000, 0x37f38000,
1517
  0x37f40000, 0x37f48000, 0x37f50000, 0x37f58000, 0x37f60000, 0x37f68000, 0x37f70000, 0x37f78000,
1518
  0x37f80000, 0x37f88000, 0x37f90000, 0x37f98000, 0x37fa0000, 0x37fa8000, 0x37fb0000, 0x37fb8000,
1519
  0x37fc0000, 0x37fc8000, 0x37fd0000, 0x37fd8000, 0x37fe0000, 0x37fe8000, 0x37ff0000, 0x37ff8000,
1520
  0x38000000, 0x38004000, 0x38008000, 0x3800c000, 0x38010000, 0x38014000, 0x38018000, 0x3801c000,
1521
  0x38020000, 0x38024000, 0x38028000, 0x3802c000, 0x38030000, 0x38034000, 0x38038000, 0x3803c000,
1522
  0x38040000, 0x38044000, 0x38048000, 0x3804c000, 0x38050000, 0x38054000, 0x38058000, 0x3805c000,
1523
  0x38060000, 0x38064000, 0x38068000, 0x3806c000, 0x38070000, 0x38074000, 0x38078000, 0x3807c000,
1524
  0x38080000, 0x38084000, 0x38088000, 0x3808c000, 0x38090000, 0x38094000, 0x38098000, 0x3809c000,
1525
  0x380a0000, 0x380a4000, 0x380a8000, 0x380ac000, 0x380b0000, 0x380b4000, 0x380b8000, 0x380bc000,
1526
  0x380c0000, 0x380c4000, 0x380c8000, 0x380cc000, 0x380d0000, 0x380d4000, 0x380d8000, 0x380dc000,
1527
  0x380e0000, 0x380e4000, 0x380e8000, 0x380ec000, 0x380f0000, 0x380f4000, 0x380f8000, 0x380fc000,
1528
  0x38100000, 0x38104000, 0x38108000, 0x3810c000, 0x38110000, 0x38114000, 0x38118000, 0x3811c000,
1529
  0x38120000, 0x38124000, 0x38128000, 0x3812c000, 0x38130000, 0x38134000, 0x38138000, 0x3813c000,
1530
  0x38140000, 0x38144000, 0x38148000, 0x3814c000, 0x38150000, 0x38154000, 0x38158000, 0x3815c000,
1531
  0x38160000, 0x38164000, 0x38168000, 0x3816c000, 0x38170000, 0x38174000, 0x38178000, 0x3817c000,
1532
  0x38180000, 0x38184000, 0x38188000, 0x3818c000, 0x38190000, 0x38194000, 0x38198000, 0x3819c000,
1533
  0x381a0000, 0x381a4000, 0x381a8000, 0x381ac000, 0x381b0000, 0x381b4000, 0x381b8000, 0x381bc000,
1534
  0x381c0000, 0x381c4000, 0x381c8000, 0x381cc000, 0x381d0000, 0x381d4000, 0x381d8000, 0x381dc000,
1535
  0x381e0000, 0x381e4000, 0x381e8000, 0x381ec000, 0x381f0000, 0x381f4000, 0x381f8000, 0x381fc000,
1536
  0x38200000, 0x38204000, 0x38208000, 0x3820c000, 0x38210000, 0x38214000, 0x38218000, 0x3821c000,
1537
  0x38220000, 0x38224000, 0x38228000, 0x3822c000, 0x38230000, 0x38234000, 0x38238000, 0x3823c000,
1538
  0x38240000, 0x38244000, 0x38248000, 0x3824c000, 0x38250000, 0x38254000, 0x38258000, 0x3825c000,
1539
  0x38260000, 0x38264000, 0x38268000, 0x3826c000, 0x38270000, 0x38274000, 0x38278000, 0x3827c000,
1540
  0x38280000, 0x38284000, 0x38288000, 0x3828c000, 0x38290000, 0x38294000, 0x38298000, 0x3829c000,
1541
  0x382a0000, 0x382a4000, 0x382a8000, 0x382ac000, 0x382b0000, 0x382b4000, 0x382b8000, 0x382bc000,
1542
  0x382c0000, 0x382c4000, 0x382c8000, 0x382cc000, 0x382d0000, 0x382d4000, 0x382d8000, 0x382dc000,
1543
  0x382e0000, 0x382e4000, 0x382e8000, 0x382ec000, 0x382f0000, 0x382f4000, 0x382f8000, 0x382fc000,
1544
  0x38300000, 0x38304000, 0x38308000, 0x3830c000, 0x38310000, 0x38314000, 0x38318000, 0x3831c000,
1545
  0x38320000, 0x38324000, 0x38328000, 0x3832c000, 0x38330000, 0x38334000, 0x38338000, 0x3833c000,
1546
  0x38340000, 0x38344000, 0x38348000, 0x3834c000, 0x38350000, 0x38354000, 0x38358000, 0x3835c000,
1547
  0x38360000, 0x38364000, 0x38368000, 0x3836c000, 0x38370000, 0x38374000, 0x38378000, 0x3837c000,
1548
  0x38380000, 0x38384000, 0x38388000, 0x3838c000, 0x38390000, 0x38394000, 0x38398000, 0x3839c000,
1549
  0x383a0000, 0x383a4000, 0x383a8000, 0x383ac000, 0x383b0000, 0x383b4000, 0x383b8000, 0x383bc000,
1550
  0x383c0000, 0x383c4000, 0x383c8000, 0x383cc000, 0x383d0000, 0x383d4000, 0x383d8000, 0x383dc000,
1551
  0x383e0000, 0x383e4000, 0x383e8000, 0x383ec000, 0x383f0000, 0x383f4000, 0x383f8000, 0x383fc000,
1552
  0x38400000, 0x38404000, 0x38408000, 0x3840c000, 0x38410000, 0x38414000, 0x38418000, 0x3841c000,
1553
  0x38420000, 0x38424000, 0x38428000, 0x3842c000, 0x38430000, 0x38434000, 0x38438000, 0x3843c000,
1554
  0x38440000, 0x38444000, 0x38448000, 0x3844c000, 0x38450000, 0x38454000, 0x38458000, 0x3845c000,
1555
  0x38460000, 0x38464000, 0x38468000, 0x3846c000, 0x38470000, 0x38474000, 0x38478000, 0x3847c000,
1556
  0x38480000, 0x38484000, 0x38488000, 0x3848c000, 0x38490000, 0x38494000, 0x38498000, 0x3849c000,
1557
  0x384a0000, 0x384a4000, 0x384a8000, 0x384ac000, 0x384b0000, 0x384b4000, 0x384b8000, 0x384bc000,
1558
  0x384c0000, 0x384c4000, 0x384c8000, 0x384cc000, 0x384d0000, 0x384d4000, 0x384d8000, 0x384dc000,
1559
  0x384e0000, 0x384e4000, 0x384e8000, 0x384ec000, 0x384f0000, 0x384f4000, 0x384f8000, 0x384fc000,
1560
  0x38500000, 0x38504000, 0x38508000, 0x3850c000, 0x38510000, 0x38514000, 0x38518000, 0x3851c000,
1561
  0x38520000, 0x38524000, 0x38528000, 0x3852c000, 0x38530000, 0x38534000, 0x38538000, 0x3853c000,
1562
  0x38540000, 0x38544000, 0x38548000, 0x3854c000, 0x38550000, 0x38554000, 0x38558000, 0x3855c000,
1563
  0x38560000, 0x38564000, 0x38568000, 0x3856c000, 0x38570000, 0x38574000, 0x38578000, 0x3857c000,
1564
  0x38580000, 0x38584000, 0x38588000, 0x3858c000, 0x38590000, 0x38594000, 0x38598000, 0x3859c000,
1565
  0x385a0000, 0x385a4000, 0x385a8000, 0x385ac000, 0x385b0000, 0x385b4000, 0x385b8000, 0x385bc000,
1566
  0x385c0000, 0x385c4000, 0x385c8000, 0x385cc000, 0x385d0000, 0x385d4000, 0x385d8000, 0x385dc000,
1567
  0x385e0000, 0x385e4000, 0x385e8000, 0x385ec000, 0x385f0000, 0x385f4000, 0x385f8000, 0x385fc000,
1568
  0x38600000, 0x38604000, 0x38608000, 0x3860c000, 0x38610000, 0x38614000, 0x38618000, 0x3861c000,
1569
  0x38620000, 0x38624000, 0x38628000, 0x3862c000, 0x38630000, 0x38634000, 0x38638000, 0x3863c000,
1570
  0x38640000, 0x38644000, 0x38648000, 0x3864c000, 0x38650000, 0x38654000, 0x38658000, 0x3865c000,
1571
  0x38660000, 0x38664000, 0x38668000, 0x3866c000, 0x38670000, 0x38674000, 0x38678000, 0x3867c000,
1572
  0x38680000, 0x38684000, 0x38688000, 0x3868c000, 0x38690000, 0x38694000, 0x38698000, 0x3869c000,
1573
  0x386a0000, 0x386a4000, 0x386a8000, 0x386ac000, 0x386b0000, 0x386b4000, 0x386b8000, 0x386bc000,
1574
  0x386c0000, 0x386c4000, 0x386c8000, 0x386cc000, 0x386d0000, 0x386d4000, 0x386d8000, 0x386dc000,
1575
  0x386e0000, 0x386e4000, 0x386e8000, 0x386ec000, 0x386f0000, 0x386f4000, 0x386f8000, 0x386fc000,
1576
  0x38700000, 0x38704000, 0x38708000, 0x3870c000, 0x38710000, 0x38714000, 0x38718000, 0x3871c000,
1577
  0x38720000, 0x38724000, 0x38728000, 0x3872c000, 0x38730000, 0x38734000, 0x38738000, 0x3873c000,
1578
  0x38740000, 0x38744000, 0x38748000, 0x3874c000, 0x38750000, 0x38754000, 0x38758000, 0x3875c000,
1579
  0x38760000, 0x38764000, 0x38768000, 0x3876c000, 0x38770000, 0x38774000, 0x38778000, 0x3877c000,
1580
  0x38780000, 0x38784000, 0x38788000, 0x3878c000, 0x38790000, 0x38794000, 0x38798000, 0x3879c000,
1581
  0x387a0000, 0x387a4000, 0x387a8000, 0x387ac000, 0x387b0000, 0x387b4000, 0x387b8000, 0x387bc000,
1582
  0x387c0000, 0x387c4000, 0x387c8000, 0x387cc000, 0x387d0000, 0x387d4000, 0x387d8000, 0x387dc000,
1583
  0x387e0000, 0x387e4000, 0x387e8000, 0x387ec000, 0x387f0000, 0x387f4000, 0x387f8000, 0x387fc000,
1584
  0x38000000, 0x38002000, 0x38004000, 0x38006000, 0x38008000, 0x3800a000, 0x3800c000, 0x3800e000,
1585
  0x38010000, 0x38012000, 0x38014000, 0x38016000, 0x38018000, 0x3801a000, 0x3801c000, 0x3801e000,
1586
  0x38020000, 0x38022000, 0x38024000, 0x38026000, 0x38028000, 0x3802a000, 0x3802c000, 0x3802e000,
1587
  0x38030000, 0x38032000, 0x38034000, 0x38036000, 0x38038000, 0x3803a000, 0x3803c000, 0x3803e000,
1588
  0x38040000, 0x38042000, 0x38044000, 0x38046000, 0x38048000, 0x3804a000, 0x3804c000, 0x3804e000,
1589
  0x38050000, 0x38052000, 0x38054000, 0x38056000, 0x38058000, 0x3805a000, 0x3805c000, 0x3805e000,
1590
  0x38060000, 0x38062000, 0x38064000, 0x38066000, 0x38068000, 0x3806a000, 0x3806c000, 0x3806e000,
1591
  0x38070000, 0x38072000, 0x38074000, 0x38076000, 0x38078000, 0x3807a000, 0x3807c000, 0x3807e000,
1592
  0x38080000, 0x38082000, 0x38084000, 0x38086000, 0x38088000, 0x3808a000, 0x3808c000, 0x3808e000,
1593
  0x38090000, 0x38092000, 0x38094000, 0x38096000, 0x38098000, 0x3809a000, 0x3809c000, 0x3809e000,
1594
  0x380a0000, 0x380a2000, 0x380a4000, 0x380a6000, 0x380a8000, 0x380aa000, 0x380ac000, 0x380ae000,
1595
  0x380b0000, 0x380b2000, 0x380b4000, 0x380b6000, 0x380b8000, 0x380ba000, 0x380bc000, 0x380be000,
1596
  0x380c0000, 0x380c2000, 0x380c4000, 0x380c6000, 0x380c8000, 0x380ca000, 0x380cc000, 0x380ce000,
1597
  0x380d0000, 0x380d2000, 0x380d4000, 0x380d6000, 0x380d8000, 0x380da000, 0x380dc000, 0x380de000,
1598
  0x380e0000, 0x380e2000, 0x380e4000, 0x380e6000, 0x380e8000, 0x380ea000, 0x380ec000, 0x380ee000,
1599
  0x380f0000, 0x380f2000, 0x380f4000, 0x380f6000, 0x380f8000, 0x380fa000, 0x380fc000, 0x380fe000,
1600
  0x38100000, 0x38102000, 0x38104000, 0x38106000, 0x38108000, 0x3810a000, 0x3810c000, 0x3810e000,
1601
  0x38110000, 0x38112000, 0x38114000, 0x38116000, 0x38118000, 0x3811a000, 0x3811c000, 0x3811e000,
1602
  0x38120000, 0x38122000, 0x38124000, 0x38126000, 0x38128000, 0x3812a000, 0x3812c000, 0x3812e000,
1603
  0x38130000, 0x38132000, 0x38134000, 0x38136000, 0x38138000, 0x3813a000, 0x3813c000, 0x3813e000,
1604
  0x38140000, 0x38142000, 0x38144000, 0x38146000, 0x38148000, 0x3814a000, 0x3814c000, 0x3814e000,
1605
  0x38150000, 0x38152000, 0x38154000, 0x38156000, 0x38158000, 0x3815a000, 0x3815c000, 0x3815e000,
1606
  0x38160000, 0x38162000, 0x38164000, 0x38166000, 0x38168000, 0x3816a000, 0x3816c000, 0x3816e000,
1607
  0x38170000, 0x38172000, 0x38174000, 0x38176000, 0x38178000, 0x3817a000, 0x3817c000, 0x3817e000,
1608
  0x38180000, 0x38182000, 0x38184000, 0x38186000, 0x38188000, 0x3818a000, 0x3818c000, 0x3818e000,
1609
  0x38190000, 0x38192000, 0x38194000, 0x38196000, 0x38198000, 0x3819a000, 0x3819c000, 0x3819e000,
1610
  0x381a0000, 0x381a2000, 0x381a4000, 0x381a6000, 0x381a8000, 0x381aa000, 0x381ac000, 0x381ae000,
1611
  0x381b0000, 0x381b2000, 0x381b4000, 0x381b6000, 0x381b8000, 0x381ba000, 0x381bc000, 0x381be000,
1612
  0x381c0000, 0x381c2000, 0x381c4000, 0x381c6000, 0x381c8000, 0x381ca000, 0x381cc000, 0x381ce000,
1613
  0x381d0000, 0x381d2000, 0x381d4000, 0x381d6000, 0x381d8000, 0x381da000, 0x381dc000, 0x381de000,
1614
  0x381e0000, 0x381e2000, 0x381e4000, 0x381e6000, 0x381e8000, 0x381ea000, 0x381ec000, 0x381ee000,
1615
  0x381f0000, 0x381f2000, 0x381f4000, 0x381f6000, 0x381f8000, 0x381fa000, 0x381fc000, 0x381fe000,
1616
  0x38200000, 0x38202000, 0x38204000, 0x38206000, 0x38208000, 0x3820a000, 0x3820c000, 0x3820e000,
1617
  0x38210000, 0x38212000, 0x38214000, 0x38216000, 0x38218000, 0x3821a000, 0x3821c000, 0x3821e000,
1618
  0x38220000, 0x38222000, 0x38224000, 0x38226000, 0x38228000, 0x3822a000, 0x3822c000, 0x3822e000,
1619
  0x38230000, 0x38232000, 0x38234000, 0x38236000, 0x38238000, 0x3823a000, 0x3823c000, 0x3823e000,
1620
  0x38240000, 0x38242000, 0x38244000, 0x38246000, 0x38248000, 0x3824a000, 0x3824c000, 0x3824e000,
1621
  0x38250000, 0x38252000, 0x38254000, 0x38256000, 0x38258000, 0x3825a000, 0x3825c000, 0x3825e000,
1622
  0x38260000, 0x38262000, 0x38264000, 0x38266000, 0x38268000, 0x3826a000, 0x3826c000, 0x3826e000,
1623
  0x38270000, 0x38272000, 0x38274000, 0x38276000, 0x38278000, 0x3827a000, 0x3827c000, 0x3827e000,
1624
  0x38280000, 0x38282000, 0x38284000, 0x38286000, 0x38288000, 0x3828a000, 0x3828c000, 0x3828e000,
1625
  0x38290000, 0x38292000, 0x38294000, 0x38296000, 0x38298000, 0x3829a000, 0x3829c000, 0x3829e000,
1626
  0x382a0000, 0x382a2000, 0x382a4000, 0x382a6000, 0x382a8000, 0x382aa000, 0x382ac000, 0x382ae000,
1627
  0x382b0000, 0x382b2000, 0x382b4000, 0x382b6000, 0x382b8000, 0x382ba000, 0x382bc000, 0x382be000,
1628
  0x382c0000, 0x382c2000, 0x382c4000, 0x382c6000, 0x382c8000, 0x382ca000, 0x382cc000, 0x382ce000,
1629
  0x382d0000, 0x382d2000, 0x382d4000, 0x382d6000, 0x382d8000, 0x382da000, 0x382dc000, 0x382de000,
1630
  0x382e0000, 0x382e2000, 0x382e4000, 0x382e6000, 0x382e8000, 0x382ea000, 0x382ec000, 0x382ee000,
1631
  0x382f0000, 0x382f2000, 0x382f4000, 0x382f6000, 0x382f8000, 0x382fa000, 0x382fc000, 0x382fe000,
1632
  0x38300000, 0x38302000, 0x38304000, 0x38306000, 0x38308000, 0x3830a000, 0x3830c000, 0x3830e000,
1633
  0x38310000, 0x38312000, 0x38314000, 0x38316000, 0x38318000, 0x3831a000, 0x3831c000, 0x3831e000,
1634
  0x38320000, 0x38322000, 0x38324000, 0x38326000, 0x38328000, 0x3832a000, 0x3832c000, 0x3832e000,
1635
  0x38330000, 0x38332000, 0x38334000, 0x38336000, 0x38338000, 0x3833a000, 0x3833c000, 0x3833e000,
1636
  0x38340000, 0x38342000, 0x38344000, 0x38346000, 0x38348000, 0x3834a000, 0x3834c000, 0x3834e000,
1637
  0x38350000, 0x38352000, 0x38354000, 0x38356000, 0x38358000, 0x3835a000, 0x3835c000, 0x3835e000,
1638
  0x38360000, 0x38362000, 0x38364000, 0x38366000, 0x38368000, 0x3836a000, 0x3836c000, 0x3836e000,
1639
  0x38370000, 0x38372000, 0x38374000, 0x38376000, 0x38378000, 0x3837a000, 0x3837c000, 0x3837e000,
1640
  0x38380000, 0x38382000, 0x38384000, 0x38386000, 0x38388000, 0x3838a000, 0x3838c000, 0x3838e000,
1641
  0x38390000, 0x38392000, 0x38394000, 0x38396000, 0x38398000, 0x3839a000, 0x3839c000, 0x3839e000,
1642
  0x383a0000, 0x383a2000, 0x383a4000, 0x383a6000, 0x383a8000, 0x383aa000, 0x383ac000, 0x383ae000,
1643
  0x383b0000, 0x383b2000, 0x383b4000, 0x383b6000, 0x383b8000, 0x383ba000, 0x383bc000, 0x383be000,
1644
  0x383c0000, 0x383c2000, 0x383c4000, 0x383c6000, 0x383c8000, 0x383ca000, 0x383cc000, 0x383ce000,
1645
  0x383d0000, 0x383d2000, 0x383d4000, 0x383d6000, 0x383d8000, 0x383da000, 0x383dc000, 0x383de000,
1646
  0x383e0000, 0x383e2000, 0x383e4000, 0x383e6000, 0x383e8000, 0x383ea000, 0x383ec000, 0x383ee000,
1647
  0x383f0000, 0x383f2000, 0x383f4000, 0x383f6000, 0x383f8000, 0x383fa000, 0x383fc000, 0x383fe000,
1648
  0x38400000, 0x38402000, 0x38404000, 0x38406000, 0x38408000, 0x3840a000, 0x3840c000, 0x3840e000,
1649
  0x38410000, 0x38412000, 0x38414000, 0x38416000, 0x38418000, 0x3841a000, 0x3841c000, 0x3841e000,
1650
  0x38420000, 0x38422000, 0x38424000, 0x38426000, 0x38428000, 0x3842a000, 0x3842c000, 0x3842e000,
1651
  0x38430000, 0x38432000, 0x38434000, 0x38436000, 0x38438000, 0x3843a000, 0x3843c000, 0x3843e000,
1652
  0x38440000, 0x38442000, 0x38444000, 0x38446000, 0x38448000, 0x3844a000, 0x3844c000, 0x3844e000,
1653
  0x38450000, 0x38452000, 0x38454000, 0x38456000, 0x38458000, 0x3845a000, 0x3845c000, 0x3845e000,
1654
  0x38460000, 0x38462000, 0x38464000, 0x38466000, 0x38468000, 0x3846a000, 0x3846c000, 0x3846e000,
1655
  0x38470000, 0x38472000, 0x38474000, 0x38476000, 0x38478000, 0x3847a000, 0x3847c000, 0x3847e000,
1656
  0x38480000, 0x38482000, 0x38484000, 0x38486000, 0x38488000, 0x3848a000, 0x3848c000, 0x3848e000,
1657
  0x38490000, 0x38492000, 0x38494000, 0x38496000, 0x38498000, 0x3849a000, 0x3849c000, 0x3849e000,
1658
  0x384a0000, 0x384a2000, 0x384a4000, 0x384a6000, 0x384a8000, 0x384aa000, 0x384ac000, 0x384ae000,
1659
  0x384b0000, 0x384b2000, 0x384b4000, 0x384b6000, 0x384b8000, 0x384ba000, 0x384bc000, 0x384be000,
1660
  0x384c0000, 0x384c2000, 0x384c4000, 0x384c6000, 0x384c8000, 0x384ca000, 0x384cc000, 0x384ce000,
1661
  0x384d0000, 0x384d2000, 0x384d4000, 0x384d6000, 0x384d8000, 0x384da000, 0x384dc000, 0x384de000,
1662
  0x384e0000, 0x384e2000, 0x384e4000, 0x384e6000, 0x384e8000, 0x384ea000, 0x384ec000, 0x384ee000,
1663
  0x384f0000, 0x384f2000, 0x384f4000, 0x384f6000, 0x384f8000, 0x384fa000, 0x384fc000, 0x384fe000,
1664
  0x38500000, 0x38502000, 0x38504000, 0x38506000, 0x38508000, 0x3850a000, 0x3850c000, 0x3850e000,
1665
  0x38510000, 0x38512000, 0x38514000, 0x38516000, 0x38518000, 0x3851a000, 0x3851c000, 0x3851e000,
1666
  0x38520000, 0x38522000, 0x38524000, 0x38526000, 0x38528000, 0x3852a000, 0x3852c000, 0x3852e000,
1667
  0x38530000, 0x38532000, 0x38534000, 0x38536000, 0x38538000, 0x3853a000, 0x3853c000, 0x3853e000,
1668
  0x38540000, 0x38542000, 0x38544000, 0x38546000, 0x38548000, 0x3854a000, 0x3854c000, 0x3854e000,
1669
  0x38550000, 0x38552000, 0x38554000, 0x38556000, 0x38558000, 0x3855a000, 0x3855c000, 0x3855e000,
1670
  0x38560000, 0x38562000, 0x38564000, 0x38566000, 0x38568000, 0x3856a000, 0x3856c000, 0x3856e000,
1671
  0x38570000, 0x38572000, 0x38574000, 0x38576000, 0x38578000, 0x3857a000, 0x3857c000, 0x3857e000,
1672
  0x38580000, 0x38582000, 0x38584000, 0x38586000, 0x38588000, 0x3858a000, 0x3858c000, 0x3858e000,
1673
  0x38590000, 0x38592000, 0x38594000, 0x38596000, 0x38598000, 0x3859a000, 0x3859c000, 0x3859e000,
1674
  0x385a0000, 0x385a2000, 0x385a4000, 0x385a6000, 0x385a8000, 0x385aa000, 0x385ac000, 0x385ae000,
1675
  0x385b0000, 0x385b2000, 0x385b4000, 0x385b6000, 0x385b8000, 0x385ba000, 0x385bc000, 0x385be000,
1676
  0x385c0000, 0x385c2000, 0x385c4000, 0x385c6000, 0x385c8000, 0x385ca000, 0x385cc000, 0x385ce000,
1677
  0x385d0000, 0x385d2000, 0x385d4000, 0x385d6000, 0x385d8000, 0x385da000, 0x385dc000, 0x385de000,
1678
  0x385e0000, 0x385e2000, 0x385e4000, 0x385e6000, 0x385e8000, 0x385ea000, 0x385ec000, 0x385ee000,
1679
  0x385f0000, 0x385f2000, 0x385f4000, 0x385f6000, 0x385f8000, 0x385fa000, 0x385fc000, 0x385fe000,
1680
  0x38600000, 0x38602000, 0x38604000, 0x38606000, 0x38608000, 0x3860a000, 0x3860c000, 0x3860e000,
1681
  0x38610000, 0x38612000, 0x38614000, 0x38616000, 0x38618000, 0x3861a000, 0x3861c000, 0x3861e000,
1682
  0x38620000, 0x38622000, 0x38624000, 0x38626000, 0x38628000, 0x3862a000, 0x3862c000, 0x3862e000,
1683
  0x38630000, 0x38632000, 0x38634000, 0x38636000, 0x38638000, 0x3863a000, 0x3863c000, 0x3863e000,
1684
  0x38640000, 0x38642000, 0x38644000, 0x38646000, 0x38648000, 0x3864a000, 0x3864c000, 0x3864e000,
1685
  0x38650000, 0x38652000, 0x38654000, 0x38656000, 0x38658000, 0x3865a000, 0x3865c000, 0x3865e000,
1686
  0x38660000, 0x38662000, 0x38664000, 0x38666000, 0x38668000, 0x3866a000, 0x3866c000, 0x3866e000,
1687
  0x38670000, 0x38672000, 0x38674000, 0x38676000, 0x38678000, 0x3867a000, 0x3867c000, 0x3867e000,
1688
  0x38680000, 0x38682000, 0x38684000, 0x38686000, 0x38688000, 0x3868a000, 0x3868c000, 0x3868e000,
1689
  0x38690000, 0x38692000, 0x38694000, 0x38696000, 0x38698000, 0x3869a000, 0x3869c000, 0x3869e000,
1690
  0x386a0000, 0x386a2000, 0x386a4000, 0x386a6000, 0x386a8000, 0x386aa000, 0x386ac000, 0x386ae000,
1691
  0x386b0000, 0x386b2000, 0x386b4000, 0x386b6000, 0x386b8000, 0x386ba000, 0x386bc000, 0x386be000,
1692
  0x386c0000, 0x386c2000, 0x386c4000, 0x386c6000, 0x386c8000, 0x386ca000, 0x386cc000, 0x386ce000,
1693
  0x386d0000, 0x386d2000, 0x386d4000, 0x386d6000, 0x386d8000, 0x386da000, 0x386dc000, 0x386de000,
1694
  0x386e0000, 0x386e2000, 0x386e4000, 0x386e6000, 0x386e8000, 0x386ea000, 0x386ec000, 0x386ee000,
1695
  0x386f0000, 0x386f2000, 0x386f4000, 0x386f6000, 0x386f8000, 0x386fa000, 0x386fc000, 0x386fe000,
1696
  0x38700000, 0x38702000, 0x38704000, 0x38706000, 0x38708000, 0x3870a000, 0x3870c000, 0x3870e000,
1697
  0x38710000, 0x38712000, 0x38714000, 0x38716000, 0x38718000, 0x3871a000, 0x3871c000, 0x3871e000,
1698
  0x38720000, 0x38722000, 0x38724000, 0x38726000, 0x38728000, 0x3872a000, 0x3872c000, 0x3872e000,
1699
  0x38730000, 0x38732000, 0x38734000, 0x38736000, 0x38738000, 0x3873a000, 0x3873c000, 0x3873e000,
1700
  0x38740000, 0x38742000, 0x38744000, 0x38746000, 0x38748000, 0x3874a000, 0x3874c000, 0x3874e000,
1701
  0x38750000, 0x38752000, 0x38754000, 0x38756000, 0x38758000, 0x3875a000, 0x3875c000, 0x3875e000,
1702
  0x38760000, 0x38762000, 0x38764000, 0x38766000, 0x38768000, 0x3876a000, 0x3876c000, 0x3876e000,
1703
  0x38770000, 0x38772000, 0x38774000, 0x38776000, 0x38778000, 0x3877a000, 0x3877c000, 0x3877e000,
1704
  0x38780000, 0x38782000, 0x38784000, 0x38786000, 0x38788000, 0x3878a000, 0x3878c000, 0x3878e000,
1705
  0x38790000, 0x38792000, 0x38794000, 0x38796000, 0x38798000, 0x3879a000, 0x3879c000, 0x3879e000,
1706
  0x387a0000, 0x387a2000, 0x387a4000, 0x387a6000, 0x387a8000, 0x387aa000, 0x387ac000, 0x387ae000,
1707
  0x387b0000, 0x387b2000, 0x387b4000, 0x387b6000, 0x387b8000, 0x387ba000, 0x387bc000, 0x387be000,
1708
  0x387c0000, 0x387c2000, 0x387c4000, 0x387c6000, 0x387c8000, 0x387ca000, 0x387cc000, 0x387ce000,
1709
  0x387d0000, 0x387d2000, 0x387d4000, 0x387d6000, 0x387d8000, 0x387da000, 0x387dc000, 0x387de000,
1710
  0x387e0000, 0x387e2000, 0x387e4000, 0x387e6000, 0x387e8000, 0x387ea000, 0x387ec000, 0x387ee000,
1711
  0x387f0000, 0x387f2000, 0x387f4000, 0x387f6000, 0x387f8000, 0x387fa000, 0x387fc000, 0x387fe000,
1712
};
1713
1714
static uint32_t _ccv_exponent_table[64] = {
1715
  0x0, 0x800000, 0x1000000, 0x1800000, 0x2000000, 0x2800000, 0x3000000, 0x3800000,
1716
  0x4000000, 0x4800000, 0x5000000, 0x5800000, 0x6000000, 0x6800000, 0x7000000, 0x7800000,
1717
  0x8000000, 0x8800000, 0x9000000, 0x9800000, 0xa000000, 0xa800000, 0xb000000, 0xb800000,
1718
  0xc000000, 0xc800000, 0xd000000, 0xd800000, 0xe000000, 0xe800000, 0xf000000, 0x47800000,
1719
  0x80000000, 0x80800000, 0x81000000, 0x81800000, 0x82000000, 0x82800000, 0x83000000, 0x83800000,
1720
  0x84000000, 0x84800000, 0x85000000, 0x85800000, 0x86000000, 0x86800000, 0x87000000, 0x87800000,
1721
  0x88000000, 0x88800000, 0x89000000, 0x89800000, 0x8a000000, 0x8a800000, 0x8b000000, 0x8b800000,
1722
  0x8c000000, 0x8c800000, 0x8d000000, 0x8d800000, 0x8e000000, 0x8e800000, 0x8f000000, 0xc7800000,
1723
};
1724
1725
static uint16_t _ccv_offset_table[64] = {
1726
  0x0, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
1727
  0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
1728
  0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
1729
  0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
1730
  0x0, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
1731
  0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
1732
  0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
1733
  0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
1734
};
1735
1736
void ccv_half_precision_to_float(const uint16_t* h, float* f, size_t len)
1737
19.7M
{
1738
19.7M
  int i;
1739
19.7M
  uint32_t* u = (uint32_t*)f;
1740
1.18G
  for (i = 0; i < len; 
i++1.16G
)
1741
1.16G
    u[i] = _ccv_mantissa_table[_ccv_offset_table[h[i] >> 10] + (h[i] & 0x3ff)] + _ccv_exponent_table[h[i] >> 10];
1742
19.7M
}
1743
1744
void ccv_half_precision_to_double(const uint16_t* h, double* f, size_t len)
1745
0
{
1746
0
  int i;
1747
0
  for (i = 0; i < len; i++)
1748
0
  {
1749
0
    union {
1750
0
      float v;
1751
0
      uint32_t p;
1752
0
    } u = {
1753
0
      .p = _ccv_mantissa_table[_ccv_offset_table[h[i] >> 10] + (h[i] & 0x3ff)] + _ccv_exponent_table[h[i] >> 10]
1754
0
    };
1755
0
    f[i] = u.v;
1756
0
  }
1757
0
}
1758
1759
void ccv_array_push(ccv_array_t* array, const void* r)
1760
6.04M
{
1761
6.04M
  array->rnum++;
1762
6.04M
  if (array->rnum > array->size)
1763
136k
  {
1764
136k
    array->size = ccv_max(array->size * 3 / 2, array->size + 1);
1765
136k
    array->data = ccrealloc(array->data, (size_t)array->size * (size_t)array->rsize);
1766
136k
  }
1767
6.04M
  memcpy(ccv_array_get(array, array->rnum - 1), r, array->rsize);
1768
6.04M
}
1769
1770
void ccv_array_zero(ccv_array_t* array)
1771
69
{
1772
69
  memset(array->data, 0, (size_t)array->size * (size_t)array->rsize);
1773
69
}
1774
1775
void ccv_array_resize(ccv_array_t* array, int rnum)
1776
84.5k
{
1777
84.5k
  if (rnum > array->size)
1778
42.1k
  {
1779
42.1k
    array->size = ccv_max(array->size * 3 / 2, rnum);
1780
42.1k
    array->data = ccrealloc(array->data, (size_t)array->size * (size_t)array->rsize);
1781
42.1k
  }
1782
84.5k
  if (rnum > array->rnum)
1783
84.4k
    memset(ccv_array_get(array, array->rnum), 0, (size_t)array->rsize * (size_t)(rnum - array->rnum));
1784
84.5k
  array->rnum = rnum;
1785
84.5k
}
1786
1787
void ccv_array_clear(ccv_array_t* array)
1788
140k
{
1789
140k
  array->rnum = 0;
1790
140k
}
1791
1792
typedef struct ccv_ptree_node_t
1793
{
1794
  struct ccv_ptree_node_t* parent;
1795
  void* element;
1796
  int rank;
1797
} ccv_ptree_node_t;
1798
1799
/* the code for grouping array is adopted from OpenCV's cvSeqPartition func, it is essentially a find-union algorithm */
1800
int ccv_array_group(ccv_array_t* array, ccv_array_t** index, ccv_array_group_f gfunc, void* data)
1801
1
{
1802
1
  int i, j;
1803
1
  ccv_ptree_node_t* node = (ccv_ptree_node_t*)ccmalloc(array->rnum * sizeof(ccv_ptree_node_t));
1804
9
  for (i = 0; i < array->rnum; 
i++8
)
1805
8
  {
1806
8
    node[i].parent = 0;
1807
8
    node[i].element = ccv_array_get(array, i);
1808
8
    node[i].rank = 0;
1809
8
  }
1810
9
  for (i = 0; i < array->rnum; 
i++8
)
1811
8
  {
1812
8
    if (!node[i].element)
1813
0
      continue;
1814
8
    ccv_ptree_node_t* root = node + i;
1815
9
    while (root->parent)
1816
1
      root = root->parent;
1817
72
    for (j = 0; j < array->rnum; 
j++64
)
1818
64
    {
1819
64
      if( i != j && 
node[j].element56
&&
gfunc(node[i].element, node[j].element, data)56
)
1820
8
      {
1821
8
        ccv_ptree_node_t* root2 = node + j;
1822
1823
12
        while(root2->parent)
1824
4
          root2 = root2->parent;
1825
1826
8
        if(root2 != root)
1827
3
        {
1828
3
          if(root->rank > root2->rank)
1829
1
            root2->parent = root;
1830
2
          else
1831
2
          {
1832
2
            root->parent = root2;
1833
2
            root2->rank += root->rank == root2->rank;
1834
2
            root = root2;
1835
2
          }
1836
1837
          /* compress path from node2 to the root: */
1838
3
          ccv_ptree_node_t* node2 = node + j;
1839
4
          while(node2->parent)
1840
1
          {
1841
1
            ccv_ptree_node_t* temp = node2;
1842
1
            node2 = node2->parent;
1843
1
            temp->parent = root;
1844
1
          }
1845
1846
          /* compress path from node to the root: */
1847
3
          node2 = node + i;
1848
6
          while(node2->parent)
1849
3
          {
1850
3
            ccv_ptree_node_t* temp = node2;
1851
3
            node2 = node2->parent;
1852
3
            temp->parent = root;
1853
3
          }
1854
3
        }
1855
8
      }
1856
64
    }
1857
8
  }
1858
1
  if (*index == 0)
1859
1
    *index = ccv_array_new(sizeof(int), array->rnum, 0);
1860
0
  else
1861
0
    ccv_array_clear(*index);
1862
1
  ccv_array_t* idx = *index;
1863
1864
1
  int class_idx = 0;
1865
9
  for(i = 0; i < array->rnum; 
i++8
)
1866
8
  {
1867
8
    j = -1;
1868
8
    ccv_ptree_node_t* node1 = node + i;
1869
8
    if(node1->element)
1870
8
    {
1871
11
      while(node1->parent)
1872
3
        node1 = node1->parent;
1873
8
      if(node1->rank >= 0)
1874
5
        node1->rank = ~class_idx++;
1875
8
      j = ~node1->rank;
1876
8
    }
1877
8
    ccv_array_push(idx, &j);
1878
8
  }
1879
1
  ccfree(node);
1880
1
  return class_idx;
1881
1
}
1882
1883
ccv_contour_t* ccv_contour_new(int set)
1884
0
{
1885
0
  ccv_contour_t* contour = (ccv_contour_t*)ccmalloc(sizeof(ccv_contour_t));
1886
0
  contour->rect.x = contour->rect.y =
1887
0
  contour->rect.width = contour->rect.height = 0;
1888
0
  contour->size = 0;
1889
0
  if (set)
1890
0
    contour->set = ccv_array_new(sizeof(ccv_point_t), 5, 0);
1891
0
  else
1892
0
    contour->set = 0;
1893
0
  return contour;
1894
0
}
1895
1896
void ccv_contour_push(ccv_contour_t* contour, ccv_point_t point)
1897
0
{
1898
0
  if (contour->size == 0)
1899
0
  {
1900
0
    contour->rect.x = point.x;
1901
0
    contour->rect.y = point.y;
1902
0
    contour->rect.width = contour->rect.height = 1;
1903
0
    contour->m10 = point.x;
1904
0
    contour->m01 = point.y;
1905
0
    contour->m11 = point.x * point.y;
1906
0
    contour->m20 = point.x * point.x;
1907
0
    contour->m02 = point.y * point.y;
1908
0
    contour->size = 1;
1909
0
  } else {
1910
0
    if (point.x < contour->rect.x)
1911
0
    {
1912
0
      contour->rect.width += contour->rect.x - point.x;
1913
0
      contour->rect.x = point.x;
1914
0
    } else if (point.x > contour->rect.x + contour->rect.width - 1) {
1915
0
      contour->rect.width = point.x - contour->rect.x + 1;
1916
0
    }
1917
0
    if (point.y < contour->rect.y)
1918
0
    {
1919
0
      contour->rect.height += contour->rect.y - point.y;
1920
0
      contour->rect.y = point.y;
1921
0
    } else if (point.y > contour->rect.y + contour->rect.height - 1) {
1922
0
      contour->rect.height = point.y - contour->rect.y + 1;
1923
0
    }
1924
0
    contour->m10 += point.x;
1925
0
    contour->m01 += point.y;
1926
0
    contour->m11 += point.x * point.y;
1927
0
    contour->m20 += point.x * point.x;
1928
0
    contour->m02 += point.y * point.y;
1929
0
    contour->size++;
1930
0
  }
1931
0
  if (contour->set)
1932
0
    ccv_array_push(contour->set, &point);
1933
0
}
1934
1935
void ccv_contour_free(ccv_contour_t* contour)
1936
0
{
1937
0
  if (contour->set)
1938
0
    ccv_array_free(contour->set);
1939
0
  ccfree(contour);
1940
0
}