Bug Summary

File:nnc/ccv_nnc_8i_rowwise.c
Warning:line 1913, column 5
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ccv_nnc_8i_rowwise.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +sse2 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/liu/actions-runner/_work/ccv/ccv/lib/nnc -fcoverage-compilation-dir=/home/liu/actions-runner/_work/ccv/ccv/lib/nnc -resource-dir /usr/local/lib/clang/19 -I ../ -I /usr/local/cuda/include -D HAVE_CBLAS -D HAVE_LIBPNG -D HAVE_LIBJPEG -D HAVE_FFTW3 -D HAVE_PTHREAD -D HAVE_LIBLINEAR -D HAVE_TESSERACT -D HAVE_AVCODEC -D HAVE_AVFORMAT -D HAVE_AVUTIL -D HAVE_SWSCALE -D HAVE_SSE2 -D HAVE_GSL -D HAVE_CUDA -D HAVE_CUDNN -D HAVE_NCCL -D USE_SYSTEM_CUB -I /usr/local/include -internal-isystem /usr/local/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/liu/actions-runner/_work/ccv/ccv/_analyze/2026-10-22-224059-1839023-1 -x c ccv_nnc_8i_rowwise.c
1#include "ccv_nnc.h"
2#include "ccv_nnc_internal.h"
3#include "ccv_nnc_easy.h"
4#include <float.h>
5#include <limits.h>
6#if HAVE_ACCELERATE_FRAMEWORK
7#include <Accelerate/Accelerate.h>
8#elif HAVE_CBLAS1
9#include <cblas.h>
10#endif
11#include "ccv_nnc_8i_rowwise_packed_grids.inc"
12#ifdef USE_DISPATCH
13#include <dispatch/dispatch.h>
14#endif
15#ifdef HAVE_CUDA1
16#include "gpu/ccv_nnc_compat.h"
17#elif defined(HAVE_MPS)
18#include "mps/ccv_nnc_mps.h"
19#endif
20
21enum {
22 CCV_NNC_8I_ROWWISE_X_REFINEMENT_STEPS = 8,
23 CCV_NNC_8I_ROWWISE_IQ2_CANDIDATES = 16,
24 CCV_NNC_8I_ROWWISE_IQ3_CANDIDATES = 24,
25 CCV_NNC_8I_ROWWISE_X_FEEDBACK_ROWS = 32,
26 CCV_NNC_8I_ROWWISE_X_CHOLESKY_PANEL = 64,
27};
28
29static size_t _ccv_nnc_8i_rowwise_packed_scale_offset(const int format, const size_t input_length, const size_t row_length)
30{
31 assert(row_length > 0)((void) sizeof ((row_length > 0) ? 1 : 0), __extension__ (
{ if (row_length > 0) ; else __assert_fail ("row_length > 0"
, "ccv_nnc_8i_rowwise.c", 31, __extension__ __PRETTY_FUNCTION__
); }))
;
32 assert(input_length % row_length == 0)((void) sizeof ((input_length % row_length == 0) ? 1 : 0), __extension__
({ if (input_length % row_length == 0) ; else __assert_fail (
"input_length % row_length == 0", "ccv_nnc_8i_rowwise.c", 32,
__extension__ __PRETTY_FUNCTION__); }))
;
33 const size_t row_count = input_length / row_length;
34 const size_t group_size = ccv_nnc_8i_rowwise_x_group_size(format);
35 const size_t groups_per_row = (row_length + group_size - 1) / group_size;
36 const size_t group_bits = ccv_nnc_8i_rowwise_x_group_bits(format);
37 const size_t payload_size = (row_count * groups_per_row * group_bits + 7) / 8;
38 return (payload_size + 127) & -128;
39}
40
41CCV_WARN_UNUSED(size_t)size_t __attribute__((warn_unused_result)) ccv_nnc_8i_rowwise_x_data_size(const int format, const int datatype, const size_t input_length, const size_t row_length)
42{
43 if (row_length == 0 || input_length % row_length != 0 ||
44 ((format & CCV_NNC_QX_8I_ROWWISE_HADAMARD_256) && row_length % 256 != 0))
45 return 0;
46 assert(datatype == CCV_16F || datatype == CCV_16BF || datatype == CCV_32F || datatype == CCV_64F)((void) sizeof ((datatype == CCV_16F || datatype == CCV_16BF ||
datatype == CCV_32F || datatype == CCV_64F) ? 1 : 0), __extension__
({ if (datatype == CCV_16F || datatype == CCV_16BF || datatype
== CCV_32F || datatype == CCV_64F) ; else __assert_fail ("datatype == CCV_16F || datatype == CCV_16BF || datatype == CCV_32F || datatype == CCV_64F"
, "ccv_nnc_8i_rowwise.c", 46, __extension__ __PRETTY_FUNCTION__
); }))
;
47 assert(row_length > 0)((void) sizeof ((row_length > 0) ? 1 : 0), __extension__ (
{ if (row_length > 0) ; else __assert_fail ("row_length > 0"
, "ccv_nnc_8i_rowwise.c", 47, __extension__ __PRETTY_FUNCTION__
); }))
;
48 assert(input_length % row_length == 0)((void) sizeof ((input_length % row_length == 0) ? 1 : 0), __extension__
({ if (input_length % row_length == 0) ; else __assert_fail (
"input_length % row_length == 0", "ccv_nnc_8i_rowwise.c", 48,
__extension__ __PRETTY_FUNCTION__); }))
;
49 const size_t row_count = input_length / row_length;
50 const size_t scale_offset = _ccv_nnc_8i_rowwise_packed_scale_offset(format, input_length, row_length);
51 return scale_offset + row_count * CCV_GET_DATA_TYPE_SIZE(datatype)_ccv_get_data_type_size[((datatype) & 0xFF000) >> 12
]
;
52}
53
54static void _ccv_nnc_8i_rowwise_packed_write_bits(uint8_t* const data, const size_t bit_offset, const uint32_t value, const int bits)
55{
56 int i;
57 for (i = 0; i < bits; i++)
58 if (value & (1u << i))
59 data[(bit_offset + i) >> 3] |= (uint8_t)(1u << ((bit_offset + i) & 7));
60}
61
62static uint32_t _ccv_nnc_8i_rowwise_packed_read_bits(const uint8_t* const data, const size_t bit_offset, const int bits)
63{
64 uint32_t value = 0;
65 int i;
66 for (i = 0; i < bits; i++)
67 if (data[(bit_offset + i) >> 3] & (uint8_t)(1u << ((bit_offset + i) & 7)))
68 value |= (1u << i);
69 return value;
70}
71
72static inline int _ccv_nnc_8i_rowwise_packed_sign_extend(const uint32_t value, const int bits)
73{
74 const uint32_t sign = 1u << (bits - 1);
75 return (value & sign) ? (int)value - (int)(1u << bits) : (int)value;
76}
77
78static inline int _ccv_nnc_8i_rowwise_packed_floor_div(const int numerator, const int denominator)
79{
80 assert(denominator > 0)((void) sizeof ((denominator > 0) ? 1 : 0), __extension__ (
{ if (denominator > 0) ; else __assert_fail ("denominator > 0"
, "ccv_nnc_8i_rowwise.c", 80, __extension__ __PRETTY_FUNCTION__
); }))
;
81 return numerator >= 0 ? numerator / denominator : -((-numerator + denominator - 1) / denominator);
82}
83
84static inline int _ccv_nnc_8i_rowwise_packed_ceil_div(const int numerator, const int denominator)
85{
86 assert(denominator > 0)((void) sizeof ((denominator > 0) ? 1 : 0), __extension__ (
{ if (denominator > 0) ; else __assert_fail ("denominator > 0"
, "ccv_nnc_8i_rowwise.c", 86, __extension__ __PRETTY_FUNCTION__
); }))
;
87 return numerator >= 0 ? (numerator + denominator - 1) / denominator : -((-numerator) / denominator);
88}
89
90static double _ccv_nnc_8i_rowwise_packed_stored_scale(const double scale, const int datatype)
91{
92 if (datatype == CCV_16F)
93 {
94 const float scale_f = (float)scale;
95 uint16_t scale_h;
96 float stored_scale;
97 ccv_float_to_half_precision(&scale_f, &scale_h, 1);
98 ccv_half_precision_to_float(&scale_h, &stored_scale, 1);
99 return stored_scale;
100 } else if (datatype == CCV_16BF) {
101 const float scale_f = (float)scale;
102 uint16_t scale_bf;
103 float stored_scale;
104 ccv_float_to_bfloat(&scale_f, &scale_bf, 1);
105 ccv_bfloat_to_float(&scale_bf, &stored_scale, 1);
106 return stored_scale;
107 } else if (datatype == CCV_32F)
108 return (float)scale;
109 return scale;
110}
111
112static void _ccv_nnc_8i_rowwise_packed_store_scale(uint8_t* const scales, const int datatype, const size_t i, const double scale)
113{
114 if (datatype == CCV_16F)
115 {
116 const float scale_f = (float)scale;
117 ccv_float_to_half_precision(&scale_f, (uint16_t*)scales + i, 1);
118 } else if (datatype == CCV_16BF) {
119 const float scale_f = (float)scale;
120 ccv_float_to_bfloat(&scale_f, (uint16_t*)scales + i, 1);
121 } else if (datatype == CCV_32F)
122 ((float*)scales)[i] = (float)scale;
123 else
124 ((double*)scales)[i] = scale;
125}
126
127static double _ccv_nnc_8i_rowwise_packed_load_scale(const uint8_t* const scales, const int datatype, const size_t i)
128{
129 if (datatype == CCV_16F)
130 {
131 float scale_f;
132 ccv_half_precision_to_float((const uint16_t*)scales + i, &scale_f, 1);
133 return scale_f;
134 } else if (datatype == CCV_16BF) {
135 float scale_f;
136 ccv_bfloat_to_float((const uint16_t*)scales + i, &scale_f, 1);
137 return scale_f;
138 } else if (datatype == CCV_32F)
139 return ((const float*)scales)[i];
140 return ((const double*)scales)[i];
141}
142
143static void _ccv_nnc_8i_rowwise_packed_read_row(const void* const input, const int datatype, const size_t row_start, const size_t row_length, const size_t padded_row_length, double* const row)
144{
145 size_t j;
146 if (datatype == CCV_16F)
147 {
148 const uint16_t* const f16 = (const uint16_t*)input + row_start;
149 for (j = 0; j < row_length; j++)
150 {
151 float v;
152 ccv_half_precision_to_float(f16 + j, &v, 1);
153 row[j] = v;
154 }
155 } else if (datatype == CCV_16BF) {
156 const uint16_t* const bf16 = (const uint16_t*)input + row_start;
157 for (j = 0; j < row_length; j++)
158 {
159 float v;
160 ccv_bfloat_to_float(bf16 + j, &v, 1);
161 row[j] = v;
162 }
163 } else if (datatype == CCV_32F) {
164 const float* const f32 = (const float*)input + row_start;
165 for (j = 0; j < row_length; j++)
166 row[j] = f32[j];
167 } else {
168 const double* const f64 = (const double*)input + row_start;
169 for (j = 0; j < row_length; j++)
170 row[j] = f64[j];
171 }
172 for (; j < padded_row_length; j++)
173 row[j] = 0;
174}
175
176static void _ccv_nnc_8i_rowwise_packed_write_value(void* const output, const int datatype, const size_t j, const double v)
177{
178 if (datatype == CCV_16F)
179 {
180 const float v_f = (float)v;
181 ccv_float_to_half_precision(&v_f, (uint16_t*)output + j, 1);
182 } else if (datatype == CCV_16BF) {
183 const float v_f = (float)v;
184 ccv_float_to_bfloat(&v_f, (uint16_t*)output + j, 1);
185 } else if (datatype == CCV_32F)
186 ((float*)output)[j] = (float)v;
187 else
188 ((double*)output)[j] = v;
189}
190
191static inline double _ccv_nnc_8i_rowwise_weight(const float* const imatrix, const size_t j)
192{
193 return imatrix ? ccv_max((double)imatrix[j], 0.)({ typeof ((double)imatrix[j]) _a = ((double)imatrix[j]); typeof
(0.) _b = (0.); (_a > _b) ? _a : _b; })
: 1.;
194}
195
196static inline int _ccv_nnc_8i_rowwise_imatrix_is_valid(const float* const imatrix, const size_t imatrix_length, const size_t row_length, const size_t row_count)
197{
198 if (!imatrix)
199 return 1;
200 if (imatrix_length < row_length || imatrix_length % row_length != 0)
201 return 0;
202 const size_t imatrix_slices = imatrix_length / row_length;
203 return imatrix_slices > 0 && row_count % imatrix_slices == 0;
204}
205
206static inline const float* _ccv_nnc_8i_rowwise_imatrix_for_row(const float* const imatrix, const size_t imatrix_length, const size_t row_length, const size_t row_count, const size_t row_idx)
207{
208 if (!imatrix)
209 return 0;
210 const size_t imatrix_slices = imatrix_length / row_length;
211 if (imatrix_slices == 1)
212 return imatrix;
213 const size_t rows_per_slice = row_count / imatrix_slices;
214 return imatrix + (row_idx / rows_per_slice) * row_length;
215}
216
217typedef struct {
218 int q[32];
219 int q8[32];
220 int m;
221 int b;
222 int z;
223 int scale;
224 int grid[4];
225 uint32_t signs;
226} ccv_nnc_8i_rowwise_packed_group_t;
227
228static const int ccv_nnc_8i_rowwise_packed_iq1s_scales[8] = {1, 2, 3, 5, 7, 9, 12, 16};
229static const int ccv_nnc_8i_rowwise_packed_iq1_powers[8] = {1, 3, 9, 27, 81, 243, 729, 2187};
230
231typedef struct {
232 int lane;
233 int trit[3];
234 double cost[3];
235} ccv_nnc_8i_rowwise_iq1_lane_t;
236
237typedef struct {
238 ccv_nnc_8i_rowwise_iq1_lane_t lanes[8];
239 const int16_t* map;
240 double best;
241 int index;
242} ccv_nnc_8i_rowwise_iq1_search_t;
243
244static void _ccv_nnc_8i_rowwise_packed_iq1_search(ccv_nnc_8i_rowwise_iq1_search_t* const search, const int depth, const int code, const double cost)
245{
246 if (cost >= search->best)
247 return;
248 if (depth == 8)
249 {
250 if (search->map[code] >= 0)
251 {
252 search->best = cost;
253 search->index = search->map[code];
254 }
255 return;
256 }
257 const ccv_nnc_8i_rowwise_iq1_lane_t* const lane = search->lanes + depth;
258 int k;
259 for (k = 0; k < 3; k++)
260 {
261 const double next = cost + lane->cost[k];
262 if (next >= search->best)
263 break;
264 _ccv_nnc_8i_rowwise_packed_iq1_search(search, depth + 1, code + lane->trit[k] * ccv_nnc_8i_rowwise_packed_iq1_powers[lane->lane], next);
265 }
266}
267
268static double _ccv_nnc_8i_rowwise_packed_iq1_nearest(const double* const y, const double* const w, const int m, const int shift, const int16_t* const map, int* const index)
269{
270 const int levels[3] = {ccv_max((-8 + shift) * m, -127)({ typeof ((-8 + shift) * m) _a = ((-8 + shift) * m); typeof (
-127) _b = (-127); (_a > _b) ? _a : _b; })
, shift * m, ccv_min((8 + shift) * m, 127)({ typeof ((8 + shift) * m) _a = ((8 + shift) * m); typeof (127
) _b = (127); (_a < _b) ? _a : _b; })
};
271 ccv_nnc_8i_rowwise_iq1_search_t search;
272 search.map = map;
273 double baseline = 0;
274 int natural_code = 0;
275 int j, k;
276 for (j = 0; j < 8; j++)
277 {
278 ccv_nnc_8i_rowwise_iq1_lane_t* const lane = search.lanes + j;
279 lane->lane = j;
280 for (k = 0; k < 3; k++)
281 {
282 const double d = levels[k] - y[j];
283 lane->trit[k] = k;
284 lane->cost[k] = w[j] * d * d;
285 }
286 for (k = 1; k < 3; k++)
287 {
288 int t;
289 for (t = k; t > 0 && lane->cost[t] < lane->cost[t - 1]; t--)
290 {
291 const double cost = lane->cost[t];
292 lane->cost[t] = lane->cost[t - 1];
293 lane->cost[t - 1] = cost;
294 const int trit = lane->trit[t];
295 lane->trit[t] = lane->trit[t - 1];
296 lane->trit[t - 1] = trit;
297 }
298 }
299 natural_code += lane->trit[0] * ccv_nnc_8i_rowwise_packed_iq1_powers[j];
300 const double minimum = lane->cost[0];
301 baseline += minimum;
302 for (k = 0; k < 3; k++)
303 lane->cost[k] -= minimum;
304 }
305 if (map[natural_code] >= 0)
306 {
307 *index = map[natural_code];
308 return baseline;
309 }
310 search.best = DBL_MAX1.7976931348623157e+308;
311 search.index = -1;
312 for (j = 0; j < 8; j++)
313 for (k = 1; k < 3; k++)
314 {
315 const ccv_nnc_8i_rowwise_iq1_lane_t* const lane = search.lanes + j;
316 const int code = natural_code + (lane->trit[k] - lane->trit[0]) * ccv_nnc_8i_rowwise_packed_iq1_powers[j];
317 if (map[code] >= 0 && lane->cost[k] < search.best)
318 {
319 search.best = lane->cost[k];
320 search.index = map[code];
321 }
322 }
323 // Independent lane costs bound the exact search; put cheap changes last.
324 for (j = 1; j < 8; j++)
325 for (k = j; k > 0 && search.lanes[k].cost[1] > search.lanes[k - 1].cost[1]; k--)
326 {
327 const ccv_nnc_8i_rowwise_iq1_lane_t lane = search.lanes[k];
328 search.lanes[k] = search.lanes[k - 1];
329 search.lanes[k - 1] = lane;
330 }
331 _ccv_nnc_8i_rowwise_packed_iq1_search(&search, 0, 0, 0);
332 assert(search.index >= 0)((void) sizeof ((search.index >= 0) ? 1 : 0), __extension__
({ if (search.index >= 0) ; else __assert_fail ("search.index >= 0"
, "ccv_nnc_8i_rowwise.c", 332, __extension__ __PRETTY_FUNCTION__
); }))
;
333 *index = search.index;
334 return baseline + search.best;
335}
336
337static void _ccv_nnc_8i_rowwise_packed_quant_iq1_m(const double* const y, const double* const w, const int16_t* const map, ccv_nnc_8i_rowwise_packed_group_t* const group)
338{
339 double best_sse = DBL_MAX1.7976931348623157e+308;
340 int m, sg, j;
341 for (m = 1; m <= 16; m++)
342 {
343 double sse = 0;
344 int grid[2];
345 uint32_t shifts = 0;
346 for (sg = 0; sg < 2; sg++)
347 {
348 int index[2];
349 const double plus = _ccv_nnc_8i_rowwise_packed_iq1_nearest(y + sg * 8, w + sg * 8, m, 1, map, index);
350 const double minus = _ccv_nnc_8i_rowwise_packed_iq1_nearest(y + sg * 8, w + sg * 8, m, -1, map, index + 1);
351 const int shift = minus < plus;
352 sse += shift ? minus : plus;
353 grid[sg] = index[shift];
354 shifts |= (uint32_t)shift << sg;
355 }
356 if (sse < best_sse)
357 {
358 best_sse = sse;
359 group->scale = m;
360 group->signs = shifts;
361 memcpy(group->grid, grid, sizeof(grid));
362 }
363 }
364 for (sg = 0; sg < 2; sg++)
365 for (j = 0; j < 8; j++)
366 {
367 const int g = (int)((ccv_nnc_8i_rowwise_packed_iq1_grid[group->grid[sg]] >> (2 * j)) & 3) - 1;
368 const int shift = (group->signs & (1u << sg)) ? -1 : 1;
369 group->q8[sg * 8 + j] = ccv_clamp(group->scale * (8 * g + shift), -127, 127)({ typeof (-127) _a = (-127); typeof (127) _b = (127); typeof
(group->scale * (8 * g + shift)) _x = (group->scale * (
8 * g + shift)); (_x < _a) ? _a : ((_x > _b) ? _b : _x)
; })
;
370 }
371}
372
373static void _ccv_nnc_8i_rowwise_packed_quant_iq1_s(const double* const y, const double* const w, const int16_t* const map, ccv_nnc_8i_rowwise_packed_group_t* const group)
374{
375 double best_sse = DBL_MAX1.7976931348623157e+308;
376 int sc, sg, j;
377 for (sc = 0; sc < 8; sc++)
378 {
379 const int m = ccv_nnc_8i_rowwise_packed_iq1s_scales[sc];
380 double costs[4][2];
381 int indices[4][2];
382 for (sg = 0; sg < 4; sg++)
383 for (j = 0; j < 2; j++)
384 costs[sg][j] = _ccv_nnc_8i_rowwise_packed_iq1_nearest(y + sg * 8, w + sg * 8, m, j ? -1 : 1, map, &indices[sg][j]);
385 int mask;
386 for (mask = 0; mask < 16; mask++)
387 {
388 if ((mask ^ (mask >> 1) ^ (mask >> 2) ^ (mask >> 3)) & 1)
389 continue;
390 double sse = 0;
391 for (sg = 0; sg < 4; sg++)
392 sse += costs[sg][(mask >> sg) & 1];
393 if (sse < best_sse)
394 {
395 best_sse = sse;
396 group->scale = sc;
397 group->signs = (uint32_t)mask;
398 for (sg = 0; sg < 4; sg++)
399 group->grid[sg] = indices[sg][(mask >> sg) & 1];
400 }
401 }
402 }
403 const int m = ccv_nnc_8i_rowwise_packed_iq1s_scales[group->scale];
404 for (sg = 0; sg < 4; sg++)
405 for (j = 0; j < 8; j++)
406 {
407 const int g = (int)((ccv_nnc_8i_rowwise_packed_iq1_grid[group->grid[sg]] >> (2 * j)) & 3) - 1;
408 const int shift = (group->signs & (1u << sg)) ? -1 : 1;
409 group->q8[sg * 8 + j] = ccv_clamp(m * (8 * g + shift), -127, 127)({ typeof (-127) _a = (-127); typeof (127) _b = (127); typeof
(m * (8 * g + shift)) _x = (m * (8 * g + shift)); (_x < _a
) ? _a : ((_x > _b) ? _b : _x); })
;
410 }
411}
412
413static void _ccv_nnc_8i_rowwise_packed_nearest_candidates(const uint8_t* const grid, const int grid_size, const int lanes, const int levels, const int code_count, const int candidate_count, uint16_t* const candidates)
414{
415 assert(candidate_count <= CCV_NNC_8I_ROWWISE_IQ3_CANDIDATES)((void) sizeof ((candidate_count <= CCV_NNC_8I_ROWWISE_IQ3_CANDIDATES
) ? 1 : 0), __extension__ ({ if (candidate_count <= CCV_NNC_8I_ROWWISE_IQ3_CANDIDATES
) ; else __assert_fail ("candidate_count <= CCV_NNC_8I_ROWWISE_IQ3_CANDIDATES"
, "ccv_nnc_8i_rowwise.c", 415, __extension__ __PRETTY_FUNCTION__
); }))
;
416 assert(candidate_count <= grid_size)((void) sizeof ((candidate_count <= grid_size) ? 1 : 0), __extension__
({ if (candidate_count <= grid_size) ; else __assert_fail
("candidate_count <= grid_size", "ccv_nnc_8i_rowwise.c", 416
, __extension__ __PRETTY_FUNCTION__); }))
;
417 int code;
418 for (code = 0; code < code_count; code++)
419 {
420 uint8_t target[8];
421 int value = code;
422 int j;
423 for (j = 0; j < lanes; j++)
424 {
425 target[j] = (uint8_t)(value % levels);
426 value /= levels;
427 }
428 int best_distance[CCV_NNC_8I_ROWWISE_IQ3_CANDIDATES];
429 int k;
430 for (k = 0; k < candidate_count; k++)
431 {
432 best_distance[k] = INT_MAX2147483647;
433 candidates[(size_t)code * candidate_count + k] = 0;
434 }
435 int index;
436 for (index = 0; index < grid_size; index++)
437 {
438 int distance = 0;
439 for (j = 0; j < lanes; j++)
440 {
441 const int d = (int)grid[(size_t)index * lanes + j] - target[j];
442 distance += d * d;
443 }
444 if (distance >= best_distance[candidate_count - 1])
445 continue;
446 k = candidate_count - 1;
447 while (k > 0 && distance < best_distance[k - 1])
448 {
449 best_distance[k] = best_distance[k - 1];
450 candidates[(size_t)code * candidate_count + k] = candidates[(size_t)code * candidate_count + k - 1];
451 --k;
452 }
453 best_distance[k] = distance;
454 candidates[(size_t)code * candidate_count + k] = (uint16_t)index;
455 }
456 }
457}
458
459static void _ccv_nnc_8i_rowwise_packed_quant_q5(const double* const y, const double* const w, ccv_nnc_8i_rowwise_packed_group_t* const group)
460{
461 double best_sse = DBL_MAX1.7976931348623157e+308;
462 int best_q[16] = {0};
463 int best_q8[16] = {0};
464 int best_m = 1, best_b = 0;
465 int m, b, j;
466 for (m = 1; m <= 8; m++)
467 for (b = -16; b <= 15; b++)
468 {
469 if (-16 * m + b < -127 || 15 * m + b > 127)
470 continue;
471 double sse = 0;
472 int q[16];
473 int q8[16];
474 for (j = 0; j < 16; j++)
475 {
476 q[j] = ccv_clamp((int)lrint((y[j] - b) / m), -16, 15)({ typeof (-16) _a = (-16); typeof (15) _b = (15); typeof ((int
)lrint((y[j] - b) / m)) _x = ((int)lrint((y[j] - b) / m)); (_x
< _a) ? _a : ((_x > _b) ? _b : _x); })
;
477 q8[j] = q[j] * m + b;
478 const double d = q8[j] - y[j];
479 sse += w[j] * d * d;
480 }
481 if (sse < best_sse)
482 {
483 best_sse = sse;
484 best_m = m;
485 best_b = b;
486 memcpy(best_q, q, sizeof(best_q));
487 memcpy(best_q8, q8, sizeof(best_q8));
488 }
489 }
490 group->m = best_m;
491 group->b = best_b;
492 memcpy(group->q, best_q, sizeof(best_q));
493 memcpy(group->q8, best_q8, sizeof(best_q8));
494}
495
496static void _ccv_nnc_8i_rowwise_packed_quant_q6(const double* const y, const double* const w, ccv_nnc_8i_rowwise_packed_group_t* const group)
497{
498 double best_sse = DBL_MAX1.7976931348623157e+308;
499 int best_q[8] = {0};
500 int best_q8[8] = {0};
501 int best_m = 1, best_b = 0;
502 int m, b, j;
503 for (m = 1; m <= 4; m++)
504 for (b = -2; b <= 1; b++)
505 {
506 const int qmin = ccv_max(-32, _ccv_nnc_8i_rowwise_packed_ceil_div(-127 - b, m))({ typeof (-32) _a = (-32); typeof (_ccv_nnc_8i_rowwise_packed_ceil_div
(-127 - b, m)) _b = (_ccv_nnc_8i_rowwise_packed_ceil_div(-127
- b, m)); (_a > _b) ? _a : _b; })
;
507 const int qmax = ccv_min(31, _ccv_nnc_8i_rowwise_packed_floor_div(127 - b, m))({ typeof (31) _a = (31); typeof (_ccv_nnc_8i_rowwise_packed_floor_div
(127 - b, m)) _b = (_ccv_nnc_8i_rowwise_packed_floor_div(127 -
b, m)); (_a < _b) ? _a : _b; })
;
508 if (qmin > qmax)
509 continue;
510 double sse = 0;
511 int q[8];
512 int q8[8];
513 for (j = 0; j < 8; j++)
514 {
515 q[j] = ccv_clamp((int)lrint((y[j] - b) / m), qmin, qmax)({ typeof (qmin) _a = (qmin); typeof (qmax) _b = (qmax); typeof
((int)lrint((y[j] - b) / m)) _x = ((int)lrint((y[j] - b) / m
)); (_x < _a) ? _a : ((_x > _b) ? _b : _x); })
;
516 q8[j] = q[j] * m + b;
517 const double d = q8[j] - y[j];
518 sse += w[j] * d * d;
519 }
520 if (sse < best_sse)
521 {
522 best_sse = sse;
523 best_m = m;
524 best_b = b;
525 memcpy(best_q, q, sizeof(best_q));
526 memcpy(best_q8, q8, sizeof(best_q8));
527 }
528 }
529 group->m = best_m;
530 group->b = best_b;
531 memcpy(group->q, best_q, sizeof(best_q));
532 memcpy(group->q8, best_q8, sizeof(best_q8));
533}
534
535static void _ccv_nnc_8i_rowwise_packed_quant_q4(const double* const y, const double* const w, ccv_nnc_8i_rowwise_packed_group_t* const group)
536{
537 double best_sse = DBL_MAX1.7976931348623157e+308;
538 int best_q[16] = {0};
539 int best_q8[16] = {0};
540 int best_m = 1, best_b = 0;
541 int m, b, j;
542 for (m = 1; m <= 16; m++)
543 for (b = -8; b <= 7; b++)
544 {
545 if (-8 * m + b < -127 || 7 * m + b > 127)
546 continue;
547 double sse = 0;
548 int q[16];
549 int q8[16];
550 for (j = 0; j < 16; j++)
551 {
552 q[j] = ccv_clamp((int)lrint((y[j] - b) / m), -8, 7)({ typeof (-8) _a = (-8); typeof (7) _b = (7); typeof ((int)lrint
((y[j] - b) / m)) _x = ((int)lrint((y[j] - b) / m)); (_x <
_a) ? _a : ((_x > _b) ? _b : _x); })
;
553 q8[j] = q[j] * m + b;
554 const double d = q8[j] - y[j];
555 sse += w[j] * d * d;
556 }
557 if (sse < best_sse)
558 {
559 best_sse = sse;
560 best_m = m;
561 best_b = b;
562 memcpy(best_q, q, sizeof(best_q));
563 memcpy(best_q8, q8, sizeof(best_q8));
564 }
565 }
566 group->m = best_m;
567 group->b = best_b;
568 memcpy(group->q, best_q, sizeof(best_q));
569 memcpy(group->q8, best_q8, sizeof(best_q8));
570}
571
572static void _ccv_nnc_8i_rowwise_packed_quant_q3(const double* const y, const double* const w, ccv_nnc_8i_rowwise_packed_group_t* const group)
573{
574 double best_sse = DBL_MAX1.7976931348623157e+308;
575 int best_q[16] = {0};
576 int best_q8[16] = {0};
577 int best_m = 1, best_b = 0;
578 int m, b, j;
579 for (m = 1; m <= 32; m++)
580 for (b = -8; b <= 6; b += 2)
581 {
582 if (-4 * m + b < -127 || 3 * m + b > 127)
583 continue;
584 double sse = 0;
585 int q[16];
586 int q8[16];
587 for (j = 0; j < 16; j++)
588 {
589 q[j] = ccv_clamp((int)lrint((y[j] - b) / m), -4, 3)({ typeof (-4) _a = (-4); typeof (3) _b = (3); typeof ((int)lrint
((y[j] - b) / m)) _x = ((int)lrint((y[j] - b) / m)); (_x <
_a) ? _a : ((_x > _b) ? _b : _x); })
;
590 q8[j] = q[j] * m + b;
591 const double d = q8[j] - y[j];
592 sse += w[j] * d * d;
593 }
594 if (sse < best_sse)
595 {
596 best_sse = sse;
597 best_m = m;
598 best_b = b;
599 memcpy(best_q, q, sizeof(best_q));
600 memcpy(best_q8, q8, sizeof(best_q8));
601 }
602 }
603 group->m = best_m;
604 group->b = best_b;
605 memcpy(group->q, best_q, sizeof(best_q));
606 memcpy(group->q8, best_q8, sizeof(best_q8));
607}
608
609static void _ccv_nnc_8i_rowwise_packed_quant_q2(const double* const y, const double* const w, ccv_nnc_8i_rowwise_packed_group_t* const group)
610{
611 double best_sse = DBL_MAX1.7976931348623157e+308;
612 int best_q[16] = {0};
613 int best_q8[16] = {0};
614 int best_m = 1, best_z = 0;
615 int m, z, j;
616 for (m = 1; m <= 64; m++)
617 for (z = 0; z <= 120; z += 8)
618 {
619 if (3 * m - z > 127)
620 continue;
621 double sse = 0;
622 int q[16];
623 int q8[16];
624 for (j = 0; j < 16; j++)
625 {
626 q[j] = ccv_clamp((int)lrint((y[j] + z) / m), 0, 3)({ typeof (0) _a = (0); typeof (3) _b = (3); typeof ((int)lrint
((y[j] + z) / m)) _x = ((int)lrint((y[j] + z) / m)); (_x <
_a) ? _a : ((_x > _b) ? _b : _x); })
;
627 q8[j] = q[j] * m - z;
628 const double d = q8[j] - y[j];
629 sse += w[j] * d * d;
630 }
631 if (sse < best_sse)
632 {
633 best_sse = sse;
634 best_m = m;
635 best_z = z;
636 memcpy(best_q, q, sizeof(best_q));
637 memcpy(best_q8, q8, sizeof(best_q8));
638 }
639 }
640 group->m = best_m;
641 group->z = best_z;
642 memcpy(group->q, best_q, sizeof(best_q));
643 memcpy(group->q8, best_q8, sizeof(best_q8));
644}
645
646static int _ccv_nnc_8i_rowwise_packed_iq2_value(const uint64_t* const grid, const int index, const int lane)
647{
648 const int v = (int)((grid[index] >> (lane * 8)) & 0xff);
649 if (v == 8)
650 return 1;
651 if (v == 25)
652 return 3;
653 assert(v == 43)((void) sizeof ((v == 43) ? 1 : 0), __extension__ ({ if (v ==
43) ; else __assert_fail ("v == 43", "ccv_nnc_8i_rowwise.c",
653, __extension__ __PRETTY_FUNCTION__); }))
;
654 return 5;
655}
656
657static int _ccv_nnc_8i_rowwise_packed_iq2xxs_value(const int index, const int lane)
658{
659 const int v = (int)((ccv_nnc_8i_rowwise_packed_iq2xxs_grid[index] >> (lane * 2)) & 3);
660 assert(v < 3)((void) sizeof ((v < 3) ? 1 : 0), __extension__ ({ if (v <
3) ; else __assert_fail ("v < 3", "ccv_nnc_8i_rowwise.c",
660, __extension__ __PRETTY_FUNCTION__); }))
;
661 return 1 + v * 2;
662}
663
664enum {
665 CCV_NNC_8I_ROWWISE_PACKED_IQ2XXS_GRID_SIZE = 256,
666 CCV_NNC_8I_ROWWISE_PACKED_IQ2S_GRID_SIZE = 1024,
667 CCV_NNC_8I_ROWWISE_PACKED_IQ2_CODE_COUNT = 6561,
668};
669
670static const int ccv_nnc_8i_rowwise_packed_iq2xxs_scales[16] = {1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32};
671static int ccv_nnc_8i_rowwise_packed_iq2_scale_initialized = 0;
672static uint8_t ccv_nnc_8i_rowwise_packed_iq2xxs_scale_level[33][3];
673static int ccv_nnc_8i_rowwise_packed_iq2xxs_initialized = 0;
674static int ccv_nnc_8i_rowwise_packed_iq2xxs_candidates_initialized = 0;
675static uint8_t ccv_nnc_8i_rowwise_packed_iq2xxs_level[CCV_NNC_8I_ROWWISE_PACKED_IQ2XXS_GRID_SIZE][8];
676static uint8_t ccv_nnc_8i_rowwise_packed_iq2xxs_scaled_value[33][CCV_NNC_8I_ROWWISE_PACKED_IQ2XXS_GRID_SIZE][8];
677static uint16_t ccv_nnc_8i_rowwise_packed_iq2xxs_candidates[CCV_NNC_8I_ROWWISE_PACKED_IQ2_CODE_COUNT][CCV_NNC_8I_ROWWISE_IQ2_CANDIDATES];
678
679static void _ccv_nnc_8i_rowwise_packed_iq2_scale_init(void)
680{
681 if (ccv_nnc_8i_rowwise_packed_iq2_scale_initialized)
682 return;
683 int scale, level;
684 for (scale = 1; scale <= 32; scale++)
685 for (level = 0; level < 3; level++)
686 ccv_nnc_8i_rowwise_packed_iq2xxs_scale_level[scale][level] = (uint8_t)ccv_min((1 + level * 2) * scale, 127)({ typeof ((1 + level * 2) * scale) _a = ((1 + level * 2) * scale
); typeof (127) _b = (127); (_a < _b) ? _a : _b; })
;
687 ccv_nnc_8i_rowwise_packed_iq2_scale_initialized = 1;
688}
689
690static void _ccv_nnc_8i_rowwise_packed_iq2xxs_init(void)
691{
692 if (ccv_nnc_8i_rowwise_packed_iq2xxs_initialized)
693 return;
694 _ccv_nnc_8i_rowwise_packed_iq2_scale_init();
695 int index, j, scale;
696 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ2XXS_GRID_SIZE; index++)
697 for (j = 0; j < 8; j++)
698 ccv_nnc_8i_rowwise_packed_iq2xxs_level[index][j] = (uint8_t)((_ccv_nnc_8i_rowwise_packed_iq2xxs_value(index, j) - 1) / 2);
699 for (scale = 1; scale <= 32; scale++)
700 {
701 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ2XXS_GRID_SIZE; index++)
702 for (j = 0; j < 8; j++)
703 ccv_nnc_8i_rowwise_packed_iq2xxs_scaled_value[scale][index][j] = ccv_nnc_8i_rowwise_packed_iq2xxs_scale_level[scale][ccv_nnc_8i_rowwise_packed_iq2xxs_level[index][j]];
704 }
705 ccv_nnc_8i_rowwise_packed_iq2xxs_initialized = 1;
706}
707
708static void _ccv_nnc_8i_rowwise_packed_iq2xxs_candidates_init(void)
709{
710 if (ccv_nnc_8i_rowwise_packed_iq2xxs_candidates_initialized)
711 return;
712 _ccv_nnc_8i_rowwise_packed_iq2xxs_init();
713 _ccv_nnc_8i_rowwise_packed_nearest_candidates(&ccv_nnc_8i_rowwise_packed_iq2xxs_level[0][0], CCV_NNC_8I_ROWWISE_PACKED_IQ2XXS_GRID_SIZE, 8, 3, CCV_NNC_8I_ROWWISE_PACKED_IQ2_CODE_COUNT, CCV_NNC_8I_ROWWISE_IQ2_CANDIDATES, &ccv_nnc_8i_rowwise_packed_iq2xxs_candidates[0][0]);
714 ccv_nnc_8i_rowwise_packed_iq2xxs_candidates_initialized = 1;
715}
716
717enum {
718 CCV_NNC_8I_ROWWISE_PACKED_IQ2XS_GRID_SIZE = 512,
719};
720
721static int ccv_nnc_8i_rowwise_packed_iq2xs_initialized = 0;
722static int ccv_nnc_8i_rowwise_packed_iq2xs_candidates_initialized = 0;
723static uint8_t ccv_nnc_8i_rowwise_packed_iq2xs_level[CCV_NNC_8I_ROWWISE_PACKED_IQ2XS_GRID_SIZE][8];
724static uint8_t ccv_nnc_8i_rowwise_packed_iq2xs_scaled_value[16][CCV_NNC_8I_ROWWISE_PACKED_IQ2XS_GRID_SIZE][8];
725static uint16_t ccv_nnc_8i_rowwise_packed_iq2xs_candidates[CCV_NNC_8I_ROWWISE_PACKED_IQ2_CODE_COUNT][CCV_NNC_8I_ROWWISE_IQ2_CANDIDATES];
726
727static void _ccv_nnc_8i_rowwise_packed_iq2xs_init(void)
728{
729 if (ccv_nnc_8i_rowwise_packed_iq2xs_initialized)
730 return;
731 _ccv_nnc_8i_rowwise_packed_iq2_scale_init();
732 int index, j, scale_code;
733 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ2XS_GRID_SIZE; index++)
734 for (j = 0; j < 8; j++)
735 ccv_nnc_8i_rowwise_packed_iq2xs_level[index][j] = (uint8_t)((_ccv_nnc_8i_rowwise_packed_iq2_value(ccv_nnc_8i_rowwise_packed_iq2xs_grid, index, j) - 1) / 2);
736 for (scale_code = 0; scale_code < 16; scale_code++)
737 {
738 const int scale = ccv_nnc_8i_rowwise_packed_iq2xxs_scales[scale_code];
739 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ2XS_GRID_SIZE; index++)
740 for (j = 0; j < 8; j++)
741 ccv_nnc_8i_rowwise_packed_iq2xs_scaled_value[scale_code][index][j] = ccv_nnc_8i_rowwise_packed_iq2xxs_scale_level[scale][ccv_nnc_8i_rowwise_packed_iq2xs_level[index][j]];
742 }
743 ccv_nnc_8i_rowwise_packed_iq2xs_initialized = 1;
744}
745
746static void _ccv_nnc_8i_rowwise_packed_iq2xs_candidates_init(void)
747{
748 if (ccv_nnc_8i_rowwise_packed_iq2xs_candidates_initialized)
749 return;
750 _ccv_nnc_8i_rowwise_packed_iq2xs_init();
751 _ccv_nnc_8i_rowwise_packed_nearest_candidates(&ccv_nnc_8i_rowwise_packed_iq2xs_level[0][0], CCV_NNC_8I_ROWWISE_PACKED_IQ2XS_GRID_SIZE, 8, 3, CCV_NNC_8I_ROWWISE_PACKED_IQ2_CODE_COUNT, CCV_NNC_8I_ROWWISE_IQ2_CANDIDATES, &ccv_nnc_8i_rowwise_packed_iq2xs_candidates[0][0]);
752 ccv_nnc_8i_rowwise_packed_iq2xs_candidates_initialized = 1;
753}
754
755static int ccv_nnc_8i_rowwise_packed_iq2s_initialized = 0;
756static uint8_t ccv_nnc_8i_rowwise_packed_iq2s_level[CCV_NNC_8I_ROWWISE_PACKED_IQ2S_GRID_SIZE][8];
757static uint8_t ccv_nnc_8i_rowwise_packed_iq2s_scale_level[65][3];
758static uint16_t ccv_nnc_8i_rowwise_packed_iq2s_scale_level2[65][3];
759static uint8_t ccv_nnc_8i_rowwise_packed_iq2s_scaled_value[65][CCV_NNC_8I_ROWWISE_PACKED_IQ2S_GRID_SIZE][8];
760
761static void _ccv_nnc_8i_rowwise_packed_iq2s_init(void)
762{
763 if (ccv_nnc_8i_rowwise_packed_iq2s_initialized)
764 return;
765 int index, j, scale;
766 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ2S_GRID_SIZE; index++)
767 for (j = 0; j < 8; j++)
768 {
769 const int v = _ccv_nnc_8i_rowwise_packed_iq2_value(ccv_nnc_8i_rowwise_packed_iq2s_grid, index, j);
770 ccv_nnc_8i_rowwise_packed_iq2s_level[index][j] = (uint8_t)((v - 1) / 2);
771 }
772 for (scale = 1; scale <= 64; scale++)
773 {
774 for (j = 0; j < 3; j++)
775 {
776 const int v = ccv_min((1 + j * 2) * scale, 127)({ typeof ((1 + j * 2) * scale) _a = ((1 + j * 2) * scale); typeof
(127) _b = (127); (_a < _b) ? _a : _b; })
;
777 ccv_nnc_8i_rowwise_packed_iq2s_scale_level[scale][j] = (uint8_t)v;
778 ccv_nnc_8i_rowwise_packed_iq2s_scale_level2[scale][j] = (uint16_t)(v * v);
779 }
780 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ2S_GRID_SIZE; index++)
781 for (j = 0; j < 8; j++)
782 ccv_nnc_8i_rowwise_packed_iq2s_scaled_value[scale][index][j] = ccv_nnc_8i_rowwise_packed_iq2s_scale_level[scale][ccv_nnc_8i_rowwise_packed_iq2s_level[index][j]];
783 }
784 ccv_nnc_8i_rowwise_packed_iq2s_initialized = 1;
785}
786
787static double _ccv_nnc_8i_rowwise_packed_iq2s_sse(const double* const ay, const double* const w, const int lane, const int scale, const int index)
788{
789 const uint8_t* const mag = ccv_nnc_8i_rowwise_packed_iq2s_scaled_value[scale][index];
790 double d = (double)mag[0] - ay[lane];
791 double sse = w[lane] * d * d;
792 d = (double)mag[1] - ay[lane + 1];
793 sse += w[lane + 1] * d * d;
794 d = (double)mag[2] - ay[lane + 2];
795 sse += w[lane + 2] * d * d;
796 d = (double)mag[3] - ay[lane + 3];
797 sse += w[lane + 3] * d * d;
798 d = (double)mag[4] - ay[lane + 4];
799 sse += w[lane + 4] * d * d;
800 d = (double)mag[5] - ay[lane + 5];
801 sse += w[lane + 5] * d * d;
802 d = (double)mag[6] - ay[lane + 6];
803 sse += w[lane + 6] * d * d;
804 d = (double)mag[7] - ay[lane + 7];
805 sse += w[lane + 7] * d * d;
806 return sse;
807}
808
809static int _ccv_nnc_8i_rowwise_packed_iq3xxs_value(const int index, const int lane)
810{
811 const int v = (int)((ccv_nnc_8i_rowwise_packed_iq3xxs_grid[index] >> (lane * 8)) & 0xff);
812 switch (v)
813 {
814 case 4: return 1;
815 case 12: return 3;
816 case 20: return 5;
817 case 28: return 7;
818 case 36: return 9;
819 case 44: return 11;
820 case 52: return 13;
821 default:
822 assert(v == 62)((void) sizeof ((v == 62) ? 1 : 0), __extension__ ({ if (v ==
62) ; else __assert_fail ("v == 62", "ccv_nnc_8i_rowwise.c",
822, __extension__ __PRETTY_FUNCTION__); }))
;
823 return 15;
824 }
825}
826
827static int _ccv_nnc_8i_rowwise_packed_iq3s_value(const int index, const int lane)
828{
829 return (int)((ccv_nnc_8i_rowwise_packed_iq3s_grid[index] >> (lane * 8)) & 0xff);
830}
831
832#define CCV_NNC_8I_ROWWISE_PACKED_IQ3S_GRID_SIZE(512) (512)
833#define CCV_NNC_8I_ROWWISE_PACKED_IQ3XXS_GRID_SIZE(256) (256)
834#define CCV_NNC_8I_ROWWISE_PACKED_IQ3_CODE_COUNT(4096) (4096)
835
836static int ccv_nnc_8i_rowwise_packed_iq3s_initialized = 0;
837static uint8_t ccv_nnc_8i_rowwise_packed_iq3s_scaled_value[17][CCV_NNC_8I_ROWWISE_PACKED_IQ3S_GRID_SIZE(512)][4];
838
839static int ccv_nnc_8i_rowwise_packed_iq3xxs_initialized = 0;
840static int ccv_nnc_8i_rowwise_packed_iq3xxs_candidates_initialized = 0;
841static uint8_t ccv_nnc_8i_rowwise_packed_iq3xxs_level[CCV_NNC_8I_ROWWISE_PACKED_IQ3XXS_GRID_SIZE(256)][4];
842static uint8_t ccv_nnc_8i_rowwise_packed_iq3xxs_scaled_value[17][CCV_NNC_8I_ROWWISE_PACKED_IQ3XXS_GRID_SIZE(256)][4];
843static uint16_t ccv_nnc_8i_rowwise_packed_iq3xxs_candidates[CCV_NNC_8I_ROWWISE_PACKED_IQ3_CODE_COUNT(4096)][CCV_NNC_8I_ROWWISE_IQ3_CANDIDATES];
844
845static void _ccv_nnc_8i_rowwise_packed_iq3s_init(void)
846{
847 if (ccv_nnc_8i_rowwise_packed_iq3s_initialized)
848 return;
849 int index, j, scale;
850 for (scale = 1; scale <= 16; scale++)
851 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ3S_GRID_SIZE(512); index++)
852 for (j = 0; j < 4; j++)
853 ccv_nnc_8i_rowwise_packed_iq3s_scaled_value[scale][index][j] = (uint8_t)ccv_min(_ccv_nnc_8i_rowwise_packed_iq3s_value(index, j) * scale, 127)({ typeof (_ccv_nnc_8i_rowwise_packed_iq3s_value(index, j) * scale
) _a = (_ccv_nnc_8i_rowwise_packed_iq3s_value(index, j) * scale
); typeof (127) _b = (127); (_a < _b) ? _a : _b; })
;
854 ccv_nnc_8i_rowwise_packed_iq3s_initialized = 1;
855}
856
857static void _ccv_nnc_8i_rowwise_packed_iq3xxs_init(void)
858{
859 if (ccv_nnc_8i_rowwise_packed_iq3xxs_initialized)
860 return;
861 int index, j, scale;
862 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ3XXS_GRID_SIZE(256); index++)
863 for (j = 0; j < 4; j++)
864 ccv_nnc_8i_rowwise_packed_iq3xxs_level[index][j] = (uint8_t)((_ccv_nnc_8i_rowwise_packed_iq3xxs_value(index, j) - 1) / 2);
865 for (scale = 1; scale <= 16; scale++)
866 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ3XXS_GRID_SIZE(256); index++)
867 for (j = 0; j < 4; j++)
868 ccv_nnc_8i_rowwise_packed_iq3xxs_scaled_value[scale][index][j] = (uint8_t)ccv_min((1 + ccv_nnc_8i_rowwise_packed_iq3xxs_level[index][j] * 2) * scale, 127)({ typeof ((1 + ccv_nnc_8i_rowwise_packed_iq3xxs_level[index]
[j] * 2) * scale) _a = ((1 + ccv_nnc_8i_rowwise_packed_iq3xxs_level
[index][j] * 2) * scale); typeof (127) _b = (127); (_a < _b
) ? _a : _b; })
;
869 ccv_nnc_8i_rowwise_packed_iq3xxs_initialized = 1;
870}
871
872static void _ccv_nnc_8i_rowwise_packed_iq3xxs_candidates_init(void)
873{
874 if (ccv_nnc_8i_rowwise_packed_iq3xxs_candidates_initialized)
875 return;
876 _ccv_nnc_8i_rowwise_packed_iq3xxs_init();
877 _ccv_nnc_8i_rowwise_packed_nearest_candidates(&ccv_nnc_8i_rowwise_packed_iq3xxs_level[0][0], CCV_NNC_8I_ROWWISE_PACKED_IQ3XXS_GRID_SIZE(256), 4, 8, CCV_NNC_8I_ROWWISE_PACKED_IQ3_CODE_COUNT(4096), CCV_NNC_8I_ROWWISE_IQ3_CANDIDATES, &ccv_nnc_8i_rowwise_packed_iq3xxs_candidates[0][0]);
878 ccv_nnc_8i_rowwise_packed_iq3xxs_candidates_initialized = 1;
879}
880
881static double _ccv_nnc_8i_rowwise_packed_iq3s_sse(const double* const ay, const double* const w, const int lane, const int scale, const int index)
882{
883 const uint8_t* const mag = ccv_nnc_8i_rowwise_packed_iq3s_scaled_value[scale][index];
884 double d = (double)mag[0] - ay[lane];
885 double sse = w[lane] * d * d;
886 d = (double)mag[1] - ay[lane + 1];
887 sse += w[lane + 1] * d * d;
888 d = (double)mag[2] - ay[lane + 2];
889 sse += w[lane + 2] * d * d;
890 d = (double)mag[3] - ay[lane + 3];
891 sse += w[lane + 3] * d * d;
892 return sse;
893}
894
895static inline double _ccv_nnc_8i_rowwise_packed_iq2_cost(const double cost[8][3], const uint8_t* const levels)
896{
897 double sse = 0;
898 int j;
899 for (j = 0; j < 8; j++)
900 sse += cost[j][levels[j]];
901 return sse;
902}
903
904static inline double _ccv_nnc_8i_rowwise_packed_safe_lower_bound(const double value)
905{
906 return nextafter(value - (fabs(value) + 1) * (64 * DBL_EPSILON2.2204460492503131e-16), -INFINITY(__builtin_inff ()));
907}
908
909static inline double _ccv_nnc_8i_rowwise_packed_iq2xxs_cost(const double cost[8][3], const double flipped_cost[8][3], const double flip_metric[8][3], const uint8_t* const levels, const uint8_t signs, const int flip_sign, int* const sign_index)
910{
911 int best_flip = -1;
912 int j;
913 if (flip_sign)
914 {
915 double best_flip_metric = DBL_MAX1.7976931348623157e+308;
916 for (j = 0; j < 8; j++)
917 {
918 const double metric = flip_metric[j][levels[j]];
919 if (metric < best_flip_metric)
920 {
921 best_flip_metric = metric;
922 best_flip = j;
923 }
924 }
925 }
926 double sse = 0;
927 for (j = 0; j < 8; j++)
928 sse += j == best_flip ? flipped_cost[j][levels[j]] : cost[j][levels[j]];
929 *sign_index = (signs ^ (best_flip >= 0 ? (uint8_t)(1u << best_flip) : 0)) & 0x7f;
930 return sse;
931}
932
933static void _ccv_nnc_8i_rowwise_packed_quant_iq2_xxs(const double* const y, const double* const w, ccv_nnc_8i_rowwise_packed_group_t* const group)
934{
935 assert(ccv_nnc_8i_rowwise_packed_iq2xxs_initialized)((void) sizeof ((ccv_nnc_8i_rowwise_packed_iq2xxs_initialized
) ? 1 : 0), __extension__ ({ if (ccv_nnc_8i_rowwise_packed_iq2xxs_initialized
) ; else __assert_fail ("ccv_nnc_8i_rowwise_packed_iq2xxs_initialized"
, "ccv_nnc_8i_rowwise.c", 935, __extension__ __PRETTY_FUNCTION__
); }))
;
936 double best_sse = DBL_MAX1.7976931348623157e+308;
937 int best_scale_code = 0;
938 int best_grid[4] = {0};
939 int best_sign[4] = {0};
940 int scale_code;
941 for (scale_code = 0; scale_code < 16; scale_code++)
942 {
943 const int scale = ccv_nnc_8i_rowwise_packed_iq2xxs_scales[scale_code];
944 double group_sse = 0;
945 int group_grid[4] = {0};
946 int group_sign[4] = {0};
947 int sg;
948 for (sg = 0; sg < 4; sg++)
949 {
950 double best_sub_sse = DBL_MAX1.7976931348623157e+308;
951 int best_sub_grid = 0;
952 int best_sub_sign = 0;
953 const int lane = sg * 8;
954 uint8_t signs = 0;
955 int negative_count = 0;
956 double cost[8][3];
957 double flipped_cost[8][3];
958 double flip_metric[8][3];
959 int j;
960 for (j = 0; j < 8; j++)
961 {
962 if (y[lane + j] < 0)
963 {
964 signs |= (uint8_t)(1u << j);
965 negative_count++;
966 }
967 int level;
968 for (level = 0; level < 3; level++)
969 {
970 const int mag = ccv_nnc_8i_rowwise_packed_iq2xxs_scale_level[scale][level];
971 const int q8 = (signs & (1u << j)) ? -mag : mag;
972 double d = (double)q8 - y[lane + j];
973 cost[j][level] = w[lane + j] * d * d;
974 d = (double)-q8 - y[lane + j];
975 flipped_cost[j][level] = w[lane + j] * d * d;
976 flip_metric[j][level] = w[lane + j] * (double)mag * fabs(y[lane + j]);
977 }
978 }
979 int target_code = 0;
980 int code_multiplier = 1;
981 uint8_t target_levels[8];
982 double lower_bound_base = 0;
983 double lower_bound_ratio = DBL_MAX1.7976931348623157e+308;
984 double lower_bound_flip = DBL_MAX1.7976931348623157e+308;
985 for (j = 0; j < 8; j++)
986 {
987 int target_level = 0;
988 if (cost[j][1] < cost[j][target_level])
989 target_level = 1;
990 if (cost[j][2] < cost[j][target_level])
991 target_level = 2;
992 target_levels[j] = (uint8_t)target_level;
993 target_code += target_level * code_multiplier;
994 code_multiplier *= 3;
995 lower_bound_base += cost[j][target_level];
996 int level;
997 for (level = 0; level < 3; level++)
998 {
999 if (level != target_level)
1000 {
1001 const int d = level - target_level;
1002 lower_bound_ratio = ccv_min(lower_bound_ratio, (cost[j][level] - cost[j][target_level]) / (double)(d * d))({ typeof (lower_bound_ratio) _a = (lower_bound_ratio); typeof
((cost[j][level] - cost[j][target_level]) / (double)(d * d))
_b = ((cost[j][level] - cost[j][target_level]) / (double)(d *
d)); (_a < _b) ? _a : _b; })
;
1003 }
1004 lower_bound_flip = ccv_min(lower_bound_flip, flipped_cost[j][level] - cost[j][level])({ typeof (lower_bound_flip) _a = (lower_bound_flip); typeof (
flipped_cost[j][level] - cost[j][level]) _b = (flipped_cost[j
][level] - cost[j][level]); (_a < _b) ? _a : _b; })
;
1005 }
1006 }
1007 int candidate;
1008 for (candidate = 0; candidate < CCV_NNC_8I_ROWWISE_IQ2_CANDIDATES; candidate++)
1009 {
1010 const int index = ccv_nnc_8i_rowwise_packed_iq2xxs_candidates[target_code][candidate];
1011 const uint8_t* const levels = ccv_nnc_8i_rowwise_packed_iq2xxs_level[index];
1012 int sign_index;
1013 const double sse = _ccv_nnc_8i_rowwise_packed_iq2xxs_cost(cost, flipped_cost, flip_metric, levels, signs, negative_count & 1, &sign_index);
1014 if (sse < best_sub_sse || (sse == best_sub_sse && index < best_sub_grid))
1015 {
1016 best_sub_sse = sse;
1017 best_sub_grid = index;
1018 best_sub_sign = sign_index;
1019 }
1020 }
1021 const uint8_t* const cutoff_levels = ccv_nnc_8i_rowwise_packed_iq2xxs_level[ccv_nnc_8i_rowwise_packed_iq2xxs_candidates[target_code][CCV_NNC_8I_ROWWISE_IQ2_CANDIDATES - 1]];
1022 int cutoff_distance = 0;
1023 for (j = 0; j < 8; j++)
1024 {
1025 const int d = (int)cutoff_levels[j] - target_levels[j];
1026 cutoff_distance += d * d;
1027 }
1028 const double safe_ratio = nextafter(lower_bound_ratio, 0);
1029 const double lower_bound = _ccv_nnc_8i_rowwise_packed_safe_lower_bound(lower_bound_base + safe_ratio * cutoff_distance + ((negative_count & 1) ? nextafter(lower_bound_flip, -INFINITY(__builtin_inff ())) : 0));
1030 if (!(best_sub_sse < lower_bound))
1031 {
1032 int index;
1033 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ2XXS_GRID_SIZE; index++)
1034 {
1035 int sign_index;
1036 const double sse = _ccv_nnc_8i_rowwise_packed_iq2xxs_cost(cost, flipped_cost, flip_metric, ccv_nnc_8i_rowwise_packed_iq2xxs_level[index], signs, negative_count & 1, &sign_index);
1037 if (sse < best_sub_sse || (sse == best_sub_sse && index < best_sub_grid))
1038 {
1039 best_sub_sse = sse;
1040 best_sub_grid = index;
1041 best_sub_sign = sign_index;
1042 }
1043 }
1044 }
1045 group_sse += best_sub_sse;
1046 group_grid[sg] = best_sub_grid;
1047 group_sign[sg] = best_sub_sign;
1048 }
1049 if (group_sse < best_sse)
1050 {
1051 best_sse = group_sse;
1052 best_scale_code = scale_code;
1053 memcpy(best_grid, group_grid, sizeof(best_grid));
1054 memcpy(best_sign, group_sign, sizeof(best_sign));
1055 }
1056 }
1057 group->scale = best_scale_code;
1058 group->signs = 0;
1059 memcpy(group->grid, best_grid, sizeof(best_grid));
1060 int j;
1061 for (j = 0; j < 4; j++)
1062 group->signs |= (uint32_t)best_sign[j] << (j * 7);
1063 for (j = 0; j < 32; j++)
1064 {
1065 const int sg = j >> 3;
1066 const int lane = j & 7;
1067 const uint8_t signs = ccv_nnc_8i_rowwise_packed_iq2xxs_ksigns[best_sign[sg]];
1068 const int mag = ccv_nnc_8i_rowwise_packed_iq2xxs_scaled_value[ccv_nnc_8i_rowwise_packed_iq2xxs_scales[best_scale_code]][best_grid[sg]][lane];
1069 group->q8[j] = (signs & (1u << lane)) ? -mag : mag;
1070 }
1071}
1072
1073static void _ccv_nnc_8i_rowwise_packed_quant_iq2_s(const double* const y, const double* const w, ccv_nnc_8i_rowwise_packed_group_t* const group)
1074{
1075 assert(ccv_nnc_8i_rowwise_packed_iq2s_initialized)((void) sizeof ((ccv_nnc_8i_rowwise_packed_iq2s_initialized) ?
1 : 0), __extension__ ({ if (ccv_nnc_8i_rowwise_packed_iq2s_initialized
) ; else __assert_fail ("ccv_nnc_8i_rowwise_packed_iq2s_initialized"
, "ccv_nnc_8i_rowwise.c", 1075, __extension__ __PRETTY_FUNCTION__
); }))
;
1076 double best_sse = DBL_MAX1.7976931348623157e+308;
1077 int best_scale = 1;
1078 int best_grid[2] = {0};
1079 double ay[16];
1080 double wy[16];
1081 uint32_t signs = 0;
1082 int j;
1083 for (j = 0; j < 16; j++)
1084 {
1085 ay[j] = fabs(y[j]);
1086 wy[j] = w[j] * ay[j];
1087 if (y[j] < 0)
1088 signs |= (1u << j);
1089 }
1090 double sub_sse[2][65];
1091 int sub_grid[2][65];
1092 int sg, scale;
1093 for (sg = 0; sg < 2; sg++)
1094 for (scale = 1; scale <= 64; scale++)
1095 {
1096 sub_sse[sg][scale] = DBL_MAX1.7976931348623157e+308;
1097 sub_grid[sg][scale] = 0;
1098 }
1099 for (sg = 0; sg < 2; sg++)
1100 {
1101 const int lane = sg * 8;
1102 double sum_y2 = 0;
1103 for (j = 0; j < 8; j++)
1104 sum_y2 += w[lane + j] * ay[lane + j] * ay[lane + j];
1105 int index;
1106 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ2S_GRID_SIZE; index++)
1107 {
1108 double sw[3] = {0};
1109 double swy[3] = {0};
1110 for (j = 0; j < 8; j++)
1111 {
1112 const int level = ccv_nnc_8i_rowwise_packed_iq2s_level[index][j];
1113 sw[level] += w[lane + j];
1114 swy[level] += wy[lane + j];
1115 }
1116 for (scale = 1; scale <= 64; scale++)
1117 {
1118 const double sse = sum_y2 +
1119 sw[0] * (double)ccv_nnc_8i_rowwise_packed_iq2s_scale_level2[scale][0] - 2 * swy[0] * (double)ccv_nnc_8i_rowwise_packed_iq2s_scale_level[scale][0] +
1120 sw[1] * (double)ccv_nnc_8i_rowwise_packed_iq2s_scale_level2[scale][1] - 2 * swy[1] * (double)ccv_nnc_8i_rowwise_packed_iq2s_scale_level[scale][1] +
1121 sw[2] * (double)ccv_nnc_8i_rowwise_packed_iq2s_scale_level2[scale][2] - 2 * swy[2] * (double)ccv_nnc_8i_rowwise_packed_iq2s_scale_level[scale][2];
1122 if (sub_sse[sg][scale] == DBL_MAX1.7976931348623157e+308 || sse <= sub_sse[sg][scale] + ccv_max(1., fabs(sub_sse[sg][scale]))({ typeof (1.) _a = (1.); typeof (fabs(sub_sse[sg][scale])) _b
= (fabs(sub_sse[sg][scale])); (_a > _b) ? _a : _b; })
* 1e-9)
1123 {
1124 const double exact_sse = _ccv_nnc_8i_rowwise_packed_iq2s_sse(ay, w, lane, scale, index);
1125 if (exact_sse < sub_sse[sg][scale])
1126 {
1127 sub_sse[sg][scale] = exact_sse;
1128 sub_grid[sg][scale] = index;
1129 }
1130 }
1131 }
1132 }
1133 }
1134 for (scale = 1; scale <= 64; scale++)
1135 {
1136 const double group_sse = sub_sse[0][scale] + sub_sse[1][scale];
1137 if (group_sse < best_sse)
1138 {
1139 best_sse = group_sse;
1140 best_scale = scale;
1141 best_grid[0] = sub_grid[0][scale];
1142 best_grid[1] = sub_grid[1][scale];
1143 }
1144 }
1145 group->scale = best_scale;
1146 group->signs = signs;
1147 memcpy(group->grid, best_grid, sizeof(best_grid));
1148 for (j = 0; j < 16; j++)
1149 {
1150 const int sg = j >> 3;
1151 const int lane = j & 7;
1152 const int mag = ccv_nnc_8i_rowwise_packed_iq2s_scaled_value[best_scale][best_grid[sg]][lane];
1153 group->q8[j] = (signs & (1u << j)) ? -mag : mag;
1154 }
1155}
1156
1157static void _ccv_nnc_8i_rowwise_packed_quant_iq2_xs(const double* const y, const double* const w, ccv_nnc_8i_rowwise_packed_group_t* const group)
1158{
1159 assert(ccv_nnc_8i_rowwise_packed_iq2xs_initialized)((void) sizeof ((ccv_nnc_8i_rowwise_packed_iq2xs_initialized)
? 1 : 0), __extension__ ({ if (ccv_nnc_8i_rowwise_packed_iq2xs_initialized
) ; else __assert_fail ("ccv_nnc_8i_rowwise_packed_iq2xs_initialized"
, "ccv_nnc_8i_rowwise.c", 1159, __extension__ __PRETTY_FUNCTION__
); }))
;
1160 double best_sse = DBL_MAX1.7976931348623157e+308;
1161 int best_scale_code = 0;
1162 int best_grid = 0;
1163 uint32_t signs = 0;
1164 int j;
1165 for (j = 0; j < 8; j++)
1166 if (y[j] < 0)
1167 signs |= (1u << j);
1168 int scale_code;
1169 for (scale_code = 0; scale_code < 16; scale_code++)
1170 {
1171 double cost[8][3];
1172 for (j = 0; j < 8; j++)
1173 {
1174 int level;
1175 for (level = 0; level < 3; level++)
1176 {
1177 const int mag = ccv_nnc_8i_rowwise_packed_iq2xxs_scale_level[ccv_nnc_8i_rowwise_packed_iq2xxs_scales[scale_code]][level];
1178 const int q8 = (signs & (1u << j)) ? -mag : mag;
1179 const double d = (double)q8 - y[j];
1180 cost[j][level] = w[j] * d * d;
1181 }
1182 }
1183 int target_code = 0;
1184 int code_multiplier = 1;
1185 uint8_t target_levels[8];
1186 double lower_bound_base = 0;
1187 double lower_bound_ratio = DBL_MAX1.7976931348623157e+308;
1188 for (j = 0; j < 8; j++)
1189 {
1190 int target_level = 0;
1191 if (cost[j][1] < cost[j][target_level])
1192 target_level = 1;
1193 if (cost[j][2] < cost[j][target_level])
1194 target_level = 2;
1195 target_levels[j] = (uint8_t)target_level;
1196 target_code += target_level * code_multiplier;
1197 code_multiplier *= 3;
1198 lower_bound_base += cost[j][target_level];
1199 int level;
1200 for (level = 0; level < 3; level++)
1201 if (level != target_level)
1202 {
1203 const int d = level - target_level;
1204 lower_bound_ratio = ccv_min(lower_bound_ratio, (cost[j][level] - cost[j][target_level]) / (double)(d * d))({ typeof (lower_bound_ratio) _a = (lower_bound_ratio); typeof
((cost[j][level] - cost[j][target_level]) / (double)(d * d))
_b = ((cost[j][level] - cost[j][target_level]) / (double)(d *
d)); (_a < _b) ? _a : _b; })
;
1205 }
1206 }
1207 int candidate;
1208 for (candidate = 0; candidate < CCV_NNC_8I_ROWWISE_IQ2_CANDIDATES; candidate++)
1209 {
1210 const int index = ccv_nnc_8i_rowwise_packed_iq2xs_candidates[target_code][candidate];
1211 const uint8_t* const levels = ccv_nnc_8i_rowwise_packed_iq2xs_level[index];
1212 const double sse = _ccv_nnc_8i_rowwise_packed_iq2_cost(cost, levels);
1213 if (sse < best_sse || (sse == best_sse && scale_code == best_scale_code && index < best_grid))
1214 {
1215 best_sse = sse;
1216 best_scale_code = scale_code;
1217 best_grid = index;
1218 }
1219 }
1220 const uint8_t* const cutoff_levels = ccv_nnc_8i_rowwise_packed_iq2xs_level[ccv_nnc_8i_rowwise_packed_iq2xs_candidates[target_code][CCV_NNC_8I_ROWWISE_IQ2_CANDIDATES - 1]];
1221 int cutoff_distance = 0;
1222 for (j = 0; j < 8; j++)
1223 {
1224 const int d = (int)cutoff_levels[j] - target_levels[j];
1225 cutoff_distance += d * d;
1226 }
1227 const double lower_bound = _ccv_nnc_8i_rowwise_packed_safe_lower_bound(lower_bound_base + nextafter(lower_bound_ratio, 0) * cutoff_distance);
1228 if (!(best_sse < lower_bound))
1229 {
1230 int index;
1231 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ2XS_GRID_SIZE; index++)
1232 {
1233 const double sse = _ccv_nnc_8i_rowwise_packed_iq2_cost(cost, ccv_nnc_8i_rowwise_packed_iq2xs_level[index]);
1234 if (sse < best_sse || (sse == best_sse && scale_code == best_scale_code && index < best_grid))
1235 {
1236 best_sse = sse;
1237 best_scale_code = scale_code;
1238 best_grid = index;
1239 }
1240 }
1241 }
1242 }
1243 group->scale = best_scale_code;
1244 group->grid[0] = best_grid;
1245 group->signs = signs;
1246 memset(group->q8, 0, sizeof(group->q8));
1247 for (j = 0; j < 8; j++)
1248 {
1249 const int mag = ccv_nnc_8i_rowwise_packed_iq2xs_scaled_value[best_scale_code][best_grid][j];
1250 group->q8[j] = (signs & (1u << j)) ? -mag : mag;
1251 }
1252}
1253
1254static void _ccv_nnc_8i_rowwise_packed_quant_iq3_s(const double* const y, const double* const w, ccv_nnc_8i_rowwise_packed_group_t* const group)
1255{
1256 assert(ccv_nnc_8i_rowwise_packed_iq3s_initialized)((void) sizeof ((ccv_nnc_8i_rowwise_packed_iq3s_initialized) ?
1 : 0), __extension__ ({ if (ccv_nnc_8i_rowwise_packed_iq3s_initialized
) ; else __assert_fail ("ccv_nnc_8i_rowwise_packed_iq3s_initialized"
, "ccv_nnc_8i_rowwise.c", 1256, __extension__ __PRETTY_FUNCTION__
); }))
;
1257 double best_sse = DBL_MAX1.7976931348623157e+308;
1258 int best_scale = 1;
1259 int best_grid[4] = {0};
1260 double ay[16];
1261 uint32_t signs = 0;
1262 int j;
1263 for (j = 0; j < 16; j++)
1264 {
1265 ay[j] = fabs(y[j]);
1266 if (y[j] < 0)
1267 signs |= (1u << j);
1268 }
1269 int scale;
1270 for (scale = 1; scale <= 16; scale++)
1271 {
1272 double group_sse = 0;
1273 int group_grid[4] = {0};
1274 int sg;
1275 for (sg = 0; sg < 4; sg++)
1276 {
1277 double best_sub_sse = DBL_MAX1.7976931348623157e+308;
1278 int best_sub_grid = 0;
1279 const int lane = sg * 4;
1280 int index;
1281 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ3S_GRID_SIZE(512); index++)
1282 {
1283 const double sse = _ccv_nnc_8i_rowwise_packed_iq3s_sse(ay, w, lane, scale, index);
1284 if (sse < best_sub_sse)
1285 {
1286 best_sub_sse = sse;
1287 best_sub_grid = index;
1288 }
1289 }
1290 group_sse += best_sub_sse;
1291 group_grid[sg] = best_sub_grid;
1292 }
1293 if (group_sse < best_sse)
1294 {
1295 best_sse = group_sse;
1296 best_scale = scale;
1297 memcpy(best_grid, group_grid, sizeof(best_grid));
1298 }
1299 }
1300 group->scale = best_scale;
1301 group->signs = signs;
1302 memcpy(group->grid, best_grid, sizeof(best_grid));
1303 for (j = 0; j < 16; j++)
1304 {
1305 const int sg = j >> 2;
1306 const int lane = j & 3;
1307 const int mag = ccv_nnc_8i_rowwise_packed_iq3s_scaled_value[best_scale][best_grid[sg]][lane];
1308 group->q8[j] = (signs & (1u << j)) ? -mag : mag;
1309 }
1310}
1311
1312static void _ccv_nnc_8i_rowwise_packed_quant_iq3_xxs(const double* const y, const double* const w, ccv_nnc_8i_rowwise_packed_group_t* const group)
1313{
1314 assert(ccv_nnc_8i_rowwise_packed_iq3xxs_initialized)((void) sizeof ((ccv_nnc_8i_rowwise_packed_iq3xxs_initialized
) ? 1 : 0), __extension__ ({ if (ccv_nnc_8i_rowwise_packed_iq3xxs_initialized
) ; else __assert_fail ("ccv_nnc_8i_rowwise_packed_iq3xxs_initialized"
, "ccv_nnc_8i_rowwise.c", 1314, __extension__ __PRETTY_FUNCTION__
); }))
;
1315 double best_sse = DBL_MAX1.7976931348623157e+308;
1316 int best_scale = 1;
1317 int best_grid[2] = {0};
1318 double ay[8];
1319 uint32_t signs = 0;
1320 int j;
1321 for (j = 0; j < 8; j++)
1322 {
1323 ay[j] = fabs(y[j]);
1324 if (y[j] < 0)
1325 signs |= (1u << j);
1326 }
1327 int scale;
1328 for (scale = 1; scale <= 16; scale++)
1329 {
1330 double group_sse = 0;
1331 int group_grid[2] = {0};
1332 int sg;
1333 for (sg = 0; sg < 2; sg++)
1334 {
1335 double best_sub_sse = DBL_MAX1.7976931348623157e+308;
1336 int best_sub_grid = 0;
1337 const int lane = sg * 4;
1338 double cost[4][8];
1339 for (j = 0; j < 4; j++)
1340 {
1341 int level;
1342 for (level = 0; level < 8; level++)
1343 {
1344 const int mag = ccv_min((1 + level * 2) * scale, 127)({ typeof ((1 + level * 2) * scale) _a = ((1 + level * 2) * scale
); typeof (127) _b = (127); (_a < _b) ? _a : _b; })
;
1345 const double d = (double)mag - ay[lane + j];
1346 cost[j][level] = w[lane + j] * d * d;
1347 }
1348 }
1349 int target_code = 0;
1350 uint8_t target_levels[4];
1351 double lower_bound_base = 0;
1352 double lower_bound_ratio = DBL_MAX1.7976931348623157e+308;
1353 for (j = 0; j < 4; j++)
1354 {
1355 int target_level = 0;
1356 int level;
1357 for (level = 1; level < 8; level++)
1358 if (cost[j][level] < cost[j][target_level])
1359 target_level = level;
1360 target_levels[j] = (uint8_t)target_level;
1361 target_code |= target_level << (j * 3);
1362 lower_bound_base += cost[j][target_level];
1363 for (level = 0; level < 8; level++)
1364 if (level != target_level)
1365 {
1366 const int d = level - target_level;
1367 lower_bound_ratio = ccv_min(lower_bound_ratio, (cost[j][level] - cost[j][target_level]) / (double)(d * d))({ typeof (lower_bound_ratio) _a = (lower_bound_ratio); typeof
((cost[j][level] - cost[j][target_level]) / (double)(d * d))
_b = ((cost[j][level] - cost[j][target_level]) / (double)(d *
d)); (_a < _b) ? _a : _b; })
;
1368 }
1369 }
1370 int candidate;
1371 for (candidate = 0; candidate < CCV_NNC_8I_ROWWISE_IQ3_CANDIDATES; candidate++)
1372 {
1373 const int index = ccv_nnc_8i_rowwise_packed_iq3xxs_candidates[target_code][candidate];
1374 const uint8_t* const levels = ccv_nnc_8i_rowwise_packed_iq3xxs_level[index];
1375 const double sse = cost[0][levels[0]] + cost[1][levels[1]] + cost[2][levels[2]] + cost[3][levels[3]];
1376 if (sse < best_sub_sse || (sse == best_sub_sse && index < best_sub_grid))
1377 {
1378 best_sub_sse = sse;
1379 best_sub_grid = index;
1380 }
1381 }
1382 const uint8_t* const cutoff_levels = ccv_nnc_8i_rowwise_packed_iq3xxs_level[ccv_nnc_8i_rowwise_packed_iq3xxs_candidates[target_code][CCV_NNC_8I_ROWWISE_IQ3_CANDIDATES - 1]];
1383 int cutoff_distance = 0;
1384 for (j = 0; j < 4; j++)
1385 {
1386 const int d = (int)cutoff_levels[j] - target_levels[j];
1387 cutoff_distance += d * d;
1388 }
1389 const double lower_bound = _ccv_nnc_8i_rowwise_packed_safe_lower_bound(lower_bound_base + nextafter(lower_bound_ratio, 0) * cutoff_distance);
1390 if (!(best_sub_sse < lower_bound))
1391 {
1392 int index;
1393 for (index = 0; index < CCV_NNC_8I_ROWWISE_PACKED_IQ3XXS_GRID_SIZE(256); index++)
1394 {
1395 const uint8_t* const levels = ccv_nnc_8i_rowwise_packed_iq3xxs_level[index];
1396 const double sse = cost[0][levels[0]] + cost[1][levels[1]] + cost[2][levels[2]] + cost[3][levels[3]];
1397 if (sse < best_sub_sse || (sse == best_sub_sse && index < best_sub_grid))
1398 {
1399 best_sub_sse = sse;
1400 best_sub_grid = index;
1401 }
1402 }
1403 }
1404 group_sse += best_sub_sse;
1405 group_grid[sg] = best_sub_grid;
1406 }
1407 if (group_sse < best_sse)
1408 {
1409 best_sse = group_sse;
1410 best_scale = scale;
1411 memcpy(best_grid, group_grid, sizeof(best_grid));
1412 }
1413 }
1414 group->scale = best_scale;
1415 group->signs = signs;
1416 memcpy(group->grid, best_grid, sizeof(best_grid));
1417 memset(group->q8, 0, sizeof(group->q8));
1418 for (j = 0; j < 8; j++)
1419 {
1420 const int sg = j >> 2;
1421 const int lane = j & 3;
1422 const int mag = ccv_nnc_8i_rowwise_packed_iq3xxs_scaled_value[best_scale][best_grid[sg]][lane];
1423 group->q8[j] = (signs & (1u << j)) ? -mag : mag;
1424 }
1425}
1426
1427static void _ccv_nnc_8i_rowwise_packed_quant_group(const int format, const double* const y, const double* const w, const int16_t* const iq1_map, ccv_nnc_8i_rowwise_packed_group_t* const group)
1428{
1429 switch (format)
1430 {
1431 case CCV_NNC_QX_8I_ROWWISE_IQ1_S:
1432 _ccv_nnc_8i_rowwise_packed_quant_iq1_s(y, w, iq1_map, group);
1433 break;
1434 case CCV_NNC_QX_8I_ROWWISE_IQ1_M:
1435 _ccv_nnc_8i_rowwise_packed_quant_iq1_m(y, w, iq1_map, group);
1436 break;
1437 case CCV_NNC_QX_8I_ROWWISE_Q5_K:
1438 _ccv_nnc_8i_rowwise_packed_quant_q5(y, w, group);
1439 break;
1440 case CCV_NNC_QX_8I_ROWWISE_Q6_K:
1441 _ccv_nnc_8i_rowwise_packed_quant_q6(y, w, group);
1442 break;
1443 case CCV_NNC_QX_8I_ROWWISE_Q4_K:
1444 _ccv_nnc_8i_rowwise_packed_quant_q4(y, w, group);
1445 break;
1446 case CCV_NNC_QX_8I_ROWWISE_Q3_K:
1447 _ccv_nnc_8i_rowwise_packed_quant_q3(y, w, group);
1448 break;
1449 case CCV_NNC_QX_8I_ROWWISE_Q2_K:
1450 _ccv_nnc_8i_rowwise_packed_quant_q2(y, w, group);
1451 break;
1452 case CCV_NNC_QX_8I_ROWWISE_IQ2_XXS:
1453 _ccv_nnc_8i_rowwise_packed_quant_iq2_xxs(y, w, group);
1454 break;
1455 case CCV_NNC_QX_8I_ROWWISE_IQ2_S:
1456 _ccv_nnc_8i_rowwise_packed_quant_iq2_s(y, w, group);
1457 break;
1458 case CCV_NNC_QX_8I_ROWWISE_IQ2_XS:
1459 _ccv_nnc_8i_rowwise_packed_quant_iq2_xs(y, w, group);
1460 break;
1461 case CCV_NNC_QX_8I_ROWWISE_IQ3_S:
1462 _ccv_nnc_8i_rowwise_packed_quant_iq3_s(y, w, group);
1463 break;
1464 case CCV_NNC_QX_8I_ROWWISE_IQ3_XXS:
1465 _ccv_nnc_8i_rowwise_packed_quant_iq3_xxs(y, w, group);
1466 break;
1467 default:
1468 assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_8i_rowwise.c", 1468, __extension__ __PRETTY_FUNCTION__
); }))
;
1469 }
1470}
1471
1472static void _ccv_nnc_8i_rowwise_packed_pack_group(uint8_t* const output, const size_t group_index, const int format, const ccv_nnc_8i_rowwise_packed_group_t* const group)
1473{
1474 const size_t bit_offset = group_index * ccv_nnc_8i_rowwise_x_group_bits(format);
1475 size_t bit = bit_offset;
1476 int j;
1477 switch (format)
1478 {
1479 case CCV_NNC_QX_8I_ROWWISE_IQ1_S:
1480 for (j = 0; j < 4; j++)
1481 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + j * 11, (uint32_t)group->grid[j], 11);
1482 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 44, group->signs & 7, 3);
1483 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 47, (uint32_t)group->scale, 3);
1484 break;
1485 case CCV_NNC_QX_8I_ROWWISE_IQ1_M:
1486 for (j = 0; j < 2; j++)
1487 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + j * 12, (uint32_t)group->grid[j] | (((group->signs >> j) & 1) << 11), 12);
1488 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 24, (uint32_t)(group->scale - 1), 4);
1489 break;
1490 case CCV_NNC_QX_8I_ROWWISE_Q5_K:
1491 for (j = 0; j < 16; j++, bit += 5)
1492 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)(group->q[j] + 16), 5);
1493 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)(group->m - 1), 3);
1494 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 3, (uint32_t)(group->b + 16), 5);
1495 break;
1496 case CCV_NNC_QX_8I_ROWWISE_Q6_K:
1497 for (j = 0; j < 8; j++, bit += 6)
1498 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)(group->q[j] & 0x3f), 6);
1499 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)(group->m - 1), 2);
1500 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 2, (uint32_t)(group->b & 3), 2);
1501 break;
1502 case CCV_NNC_QX_8I_ROWWISE_Q4_K:
1503 for (j = 0; j < 16; j++, bit += 4)
1504 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)(group->q[j] + 8), 4);
1505 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)(group->m - 1), 4);
1506 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 4, (uint32_t)(group->b + 8), 4);
1507 break;
1508 case CCV_NNC_QX_8I_ROWWISE_Q3_K:
1509 for (j = 0; j < 16; j++, bit += 3)
1510 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)(group->q[j] + 4), 3);
1511 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)(group->m - 1), 5);
1512 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 5, (uint32_t)(group->b / 2 + 4), 3);
1513 break;
1514 case CCV_NNC_QX_8I_ROWWISE_Q2_K:
1515 for (j = 0; j < 16; j++, bit += 2)
1516 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)group->q[j], 2);
1517 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)(group->m - 1), 6);
1518 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 6, (uint32_t)(group->z >> 3), 4);
1519 break;
1520 case CCV_NNC_QX_8I_ROWWISE_IQ2_S:
1521 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)group->grid[0], 10);
1522 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 10, (uint32_t)group->grid[1], 10);
1523 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 20, group->signs, 16);
1524 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 36, (uint32_t)(group->scale - 1), 6);
1525 break;
1526 case CCV_NNC_QX_8I_ROWWISE_IQ2_XS:
1527 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)group->grid[0], 9);
1528 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 9, group->signs, 8);
1529 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 17, (uint32_t)group->scale, 4);
1530 break;
1531 case CCV_NNC_QX_8I_ROWWISE_IQ2_XXS:
1532 for (j = 0; j < 4; j++)
1533 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + j * 8, (uint32_t)group->grid[j], 8);
1534 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 32, group->signs, 28);
1535 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 60, (uint32_t)group->scale, 4);
1536 break;
1537 case CCV_NNC_QX_8I_ROWWISE_IQ3_S:
1538 for (j = 0; j < 4; j++)
1539 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + j * 9, (uint32_t)group->grid[j], 9);
1540 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 36, group->signs, 16);
1541 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 52, (uint32_t)(group->scale - 1), 4);
1542 break;
1543 case CCV_NNC_QX_8I_ROWWISE_IQ3_XXS:
1544 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit, (uint32_t)group->grid[0], 8);
1545 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 8, (uint32_t)group->grid[1], 8);
1546 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 16, group->signs, 8);
1547 _ccv_nnc_8i_rowwise_packed_write_bits(output, bit + 24, (uint32_t)(group->scale - 1), 4);
1548 break;
1549 default:
1550 assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_8i_rowwise.c", 1550, __extension__ __PRETTY_FUNCTION__
); }))
;
1551 }
1552}
1553
1554static void _ccv_nnc_8i_rowwise_packed_decode_group(const uint8_t* const input, const size_t group_index, const int format, int* const q8)
1555{
1556 static const int q2_xs_scales[16] = {1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32};
1557 const size_t bit_offset = group_index * ccv_nnc_8i_rowwise_x_group_bits(format);
1558 size_t bit = bit_offset;
1559 int j;
1560 switch (format)
1561 {
1562 case CCV_NNC_QX_8I_ROWWISE_IQ1_S: {
1563 uint32_t shifts = _ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 44, 3);
1564 shifts |= ((shifts ^ (shifts >> 1) ^ (shifts >> 2)) & 1) << 3;
1565 const int m = ccv_nnc_8i_rowwise_packed_iq1s_scales[_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 47, 3)];
1566 int sg;
1567 for (sg = 0; sg < 4; sg++)
1568 {
1569 const int index = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + sg * 11, 11);
1570 const int shift = (shifts & (1u << sg)) ? -1 : 1;
1571 for (j = 0; j < 8; j++)
1572 {
1573 const int g = (int)((ccv_nnc_8i_rowwise_packed_iq1_grid[index] >> (2 * j)) & 3) - 1;
1574 q8[sg * 8 + j] = ccv_clamp(m * (8 * g + shift), -127, 127)({ typeof (-127) _a = (-127); typeof (127) _b = (127); typeof
(m * (8 * g + shift)) _x = (m * (8 * g + shift)); (_x < _a
) ? _a : ((_x > _b) ? _b : _x); })
;
1575 }
1576 }
1577 break;
1578 }
1579 case CCV_NNC_QX_8I_ROWWISE_IQ1_M: {
1580 const int m = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 24, 4) + 1;
1581 int sg;
1582 for (sg = 0; sg < 2; sg++)
1583 {
1584 const uint32_t code = _ccv_nnc_8i_rowwise_packed_read_bits(input, bit + sg * 12, 12);
1585 const int shift = (code & 2048) ? -1 : 1;
1586 for (j = 0; j < 8; j++)
1587 {
1588 const int g = (int)((ccv_nnc_8i_rowwise_packed_iq1_grid[code & 2047] >> (2 * j)) & 3) - 1;
1589 q8[sg * 8 + j] = ccv_clamp(m * (8 * g + shift), -127, 127)({ typeof (-127) _a = (-127); typeof (127) _b = (127); typeof
(m * (8 * g + shift)) _x = (m * (8 * g + shift)); (_x < _a
) ? _a : ((_x > _b) ? _b : _x); })
;
1590 }
1591 }
1592 break;
1593 }
1594 case CCV_NNC_QX_8I_ROWWISE_Q5_K: {
1595 int q[16];
1596 for (j = 0; j < 16; j++, bit += 5)
1597 q[j] = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 5) - 16;
1598 const int m = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 3) + 1;
1599 const int b = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 3, 5) - 16;
1600 for (j = 0; j < 16; j++)
1601 q8[j] = q[j] * m + b;
1602 break;
1603 }
1604 case CCV_NNC_QX_8I_ROWWISE_Q6_K: {
1605 int q[8];
1606 for (j = 0; j < 8; j++, bit += 6)
1607 q[j] = _ccv_nnc_8i_rowwise_packed_sign_extend(_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 6), 6);
1608 const int m = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 2) + 1;
1609 const int b = _ccv_nnc_8i_rowwise_packed_sign_extend(_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 2, 2), 2);
1610 for (j = 0; j < 8; j++)
1611 q8[j] = q[j] * m + b;
1612 break;
1613 }
1614 case CCV_NNC_QX_8I_ROWWISE_Q4_K: {
1615 int q[16];
1616 for (j = 0; j < 16; j++, bit += 4)
1617 q[j] = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 4) - 8;
1618 const int m = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 4) + 1;
1619 const int b = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 4, 4) - 8;
1620 for (j = 0; j < 16; j++)
1621 q8[j] = q[j] * m + b;
1622 break;
1623 }
1624 case CCV_NNC_QX_8I_ROWWISE_Q3_K: {
1625 int q[16];
1626 for (j = 0; j < 16; j++, bit += 3)
1627 q[j] = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 3) - 4;
1628 const int m = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 5) + 1;
1629 const int b = ((int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 5, 3) - 4) << 1;
1630 for (j = 0; j < 16; j++)
1631 q8[j] = q[j] * m + b;
1632 break;
1633 }
1634 case CCV_NNC_QX_8I_ROWWISE_Q2_K: {
1635 int q[16];
1636 for (j = 0; j < 16; j++, bit += 2)
1637 q[j] = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 2);
1638 const int m = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 6) + 1;
1639 const int z = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 6, 4) << 3;
1640 for (j = 0; j < 16; j++)
1641 q8[j] = q[j] * m - z;
1642 break;
1643 }
1644 case CCV_NNC_QX_8I_ROWWISE_IQ2_S: {
1645 const int grid0 = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 10);
1646 const int grid1 = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 10, 10);
1647 const uint32_t signs = _ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 20, 16);
1648 const int scale = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 36, 6) + 1;
1649 for (j = 0; j < 8; j++)
1650 {
1651 const int mag0 = ccv_min(_ccv_nnc_8i_rowwise_packed_iq2_value(ccv_nnc_8i_rowwise_packed_iq2s_grid, grid0, j) * scale, 127)({ typeof (_ccv_nnc_8i_rowwise_packed_iq2_value(ccv_nnc_8i_rowwise_packed_iq2s_grid
, grid0, j) * scale) _a = (_ccv_nnc_8i_rowwise_packed_iq2_value
(ccv_nnc_8i_rowwise_packed_iq2s_grid, grid0, j) * scale); typeof
(127) _b = (127); (_a < _b) ? _a : _b; })
;
1652 const int mag1 = ccv_min(_ccv_nnc_8i_rowwise_packed_iq2_value(ccv_nnc_8i_rowwise_packed_iq2s_grid, grid1, j) * scale, 127)({ typeof (_ccv_nnc_8i_rowwise_packed_iq2_value(ccv_nnc_8i_rowwise_packed_iq2s_grid
, grid1, j) * scale) _a = (_ccv_nnc_8i_rowwise_packed_iq2_value
(ccv_nnc_8i_rowwise_packed_iq2s_grid, grid1, j) * scale); typeof
(127) _b = (127); (_a < _b) ? _a : _b; })
;
1653 q8[j] = (signs & (1u << j)) ? -mag0 : mag0;
1654 q8[8 + j] = (signs & (1u << (8 + j))) ? -mag1 : mag1;
1655 }
1656 break;
1657 }
1658 case CCV_NNC_QX_8I_ROWWISE_IQ2_XS: {
1659 const int grid0 = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 9);
1660 const uint32_t signs = _ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 9, 8);
1661 const int scale = q2_xs_scales[_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 17, 4)];
1662 for (j = 0; j < 8; j++)
1663 {
1664 const int mag = ccv_min(_ccv_nnc_8i_rowwise_packed_iq2_value(ccv_nnc_8i_rowwise_packed_iq2xs_grid, grid0, j) * scale, 127)({ typeof (_ccv_nnc_8i_rowwise_packed_iq2_value(ccv_nnc_8i_rowwise_packed_iq2xs_grid
, grid0, j) * scale) _a = (_ccv_nnc_8i_rowwise_packed_iq2_value
(ccv_nnc_8i_rowwise_packed_iq2xs_grid, grid0, j) * scale); typeof
(127) _b = (127); (_a < _b) ? _a : _b; })
;
1665 q8[j] = (signs & (1u << j)) ? -mag : mag;
1666 }
1667 break;
1668 }
1669 case CCV_NNC_QX_8I_ROWWISE_IQ2_XXS: {
1670 int grid[4];
1671 for (j = 0; j < 4; j++)
1672 grid[j] = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + j * 8, 8);
1673 const uint32_t sign_codes = _ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 32, 28);
1674 const int scale = ccv_nnc_8i_rowwise_packed_iq2xxs_scales[_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 60, 4)];
1675 int sg;
1676 for (sg = 0; sg < 4; sg++)
1677 {
1678 const uint8_t signs = ccv_nnc_8i_rowwise_packed_iq2xxs_ksigns[(sign_codes >> (sg * 7)) & 0x7f];
1679 for (j = 0; j < 8; j++)
1680 {
1681 const int lane = sg * 8 + j;
1682 const int mag = ccv_min(_ccv_nnc_8i_rowwise_packed_iq2xxs_value(grid[sg], j) * scale, 127)({ typeof (_ccv_nnc_8i_rowwise_packed_iq2xxs_value(grid[sg], j
) * scale) _a = (_ccv_nnc_8i_rowwise_packed_iq2xxs_value(grid
[sg], j) * scale); typeof (127) _b = (127); (_a < _b) ? _a
: _b; })
;
1683 q8[lane] = (signs & (1u << j)) ? -mag : mag;
1684 }
1685 }
1686 break;
1687 }
1688 case CCV_NNC_QX_8I_ROWWISE_IQ3_S: {
1689 int grid[4];
1690 for (j = 0; j < 4; j++)
1691 grid[j] = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + j * 9, 9);
1692 const uint32_t signs = _ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 36, 16);
1693 const int scale = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 52, 4) + 1;
1694 int sg;
1695 for (sg = 0; sg < 4; sg++)
1696 for (j = 0; j < 4; j++)
1697 {
1698 const int lane = sg * 4 + j;
1699 const int mag = ccv_min(_ccv_nnc_8i_rowwise_packed_iq3s_value(grid[sg], j) * scale, 127)({ typeof (_ccv_nnc_8i_rowwise_packed_iq3s_value(grid[sg], j)
* scale) _a = (_ccv_nnc_8i_rowwise_packed_iq3s_value(grid[sg
], j) * scale); typeof (127) _b = (127); (_a < _b) ? _a : _b
; })
;
1700 q8[lane] = (signs & (1u << lane)) ? -mag : mag;
1701 }
1702 break;
1703 }
1704 case CCV_NNC_QX_8I_ROWWISE_IQ3_XXS: {
1705 const int grid0 = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit, 8);
1706 const int grid1 = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 8, 8);
1707 const uint32_t signs = _ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 16, 8);
1708 const int scale = (int)_ccv_nnc_8i_rowwise_packed_read_bits(input, bit + 24, 4) + 1;
1709 for (j = 0; j < 4; j++)
1710 {
1711 const int mag0 = ccv_min(_ccv_nnc_8i_rowwise_packed_iq3xxs_value(grid0, j) * scale, 127)({ typeof (_ccv_nnc_8i_rowwise_packed_iq3xxs_value(grid0, j) *
scale) _a = (_ccv_nnc_8i_rowwise_packed_iq3xxs_value(grid0, j
) * scale); typeof (127) _b = (127); (_a < _b) ? _a : _b; }
)
;
1712 const int mag1 = ccv_min(_ccv_nnc_8i_rowwise_packed_iq3xxs_value(grid1, j) * scale, 127)({ typeof (_ccv_nnc_8i_rowwise_packed_iq3xxs_value(grid1, j) *
scale) _a = (_ccv_nnc_8i_rowwise_packed_iq3xxs_value(grid1, j
) * scale); typeof (127) _b = (127); (_a < _b) ? _a : _b; }
)
;
1713 q8[j] = (signs & (1u << j)) ? -mag0 : mag0;
1714 q8[4 + j] = (signs & (1u << (4 + j))) ? -mag1 : mag1;
1715 }
1716 break;
1717 }
1718 default:
1719 assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "ccv_nnc_8i_rowwise.c", 1719, __extension__ __PRETTY_FUNCTION__
); }))
;
1720 }
1721}
1722
1723// Regular normalized H256, matching NAInt8MatMul activation staging. This is
1724// not the Sylvester WHT. Transform the existing floating row before fitting scales.
1725static void _ccv_nnc_8i_rowwise_hadamard_256(double* const row, const size_t row_length)
1726{
1727 size_t base;
1728 for (base = 0; base < row_length; base += 256)
1729 {
1730 int stride;
1731 for (stride = 1; stride < 256; stride *= 4)
1732 {
1733 int i, j;
1734 for (i = 0; i < 256; i += stride * 4)
1735 for (j = 0; j < stride; j++)
1736 {
1737 double* const v = row + base + i + j;
1738 const double a = v[0], b = v[stride], c = v[stride * 2], d = v[stride * 3];
1739 v[0] = a + b + c - d;
1740 v[stride] = a + b - c + d;
1741 v[stride * 2] = a - b + c + d;
1742 v[stride * 3] = -a + b + c + d;
1743 }
1744 }
1745 int i;
1746 for (i = 0; i < 256; i++)
1747 row[base + i] *= 1. / 16.;
1748 }
1749}
1750
1751typedef struct {
1752 const float* hessian; // row_length x row_length Hessian of the current slice, e.g. input second moments.
1753 double ridge; // Added to the Hessian diagonal to keep it positive definite.
1754 double* u; // Feedback coefficients U[j][k] for lane j and lanes k in later groups.
1755 double* rbb; // Upper-triangular diagonal blocks R_bb of H = R R^T, one group_size^2 block per group.
1756 double* weights; // Conditional variances diag(D_b) = diag(R_bb R_bb^T), 0 for padded lanes.
1757} ccv_nnc_8i_rowwise_x_feedback_t;
1758
1759// a[i][j] -= sum_{m in [k0, k1)} a[i][m] a[j][m] for i <= j < k0.
1760static void _ccv_nnc_8i_rowwise_x_rank_update(double* const a, const size_t n, const size_t k0, const size_t k1)
1761{
1762#if (defined HAVE_CBLAS1 || defined HAVE_ACCELERATE_FRAMEWORK)
1763 cblas_dsyrk(CblasRowMajor, CblasUpper, CblasNoTrans, (int)k0, (int)(k1 - k0), -1, a + k0, (int)n, 1, a, (int)n);
1764#else
1765 const size_t w = k1 - k0;
1766 double* const panel = (double*)ccmallocmalloc(sizeof(double) * k0 * w);
1767 size_t i;
1768 for (i = 0; i < k0; i++)
1769 memcpy(panel + i * w, a + i * n + k0, sizeof(double) * w);
1770 const size_t blocks = (k0 + 15) / 16;
1771#ifdef USE_DISPATCH
1772 dispatch_apply(blocks, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t block_idx) {
1773#else
1774 parallel_for(block_idx, (int)blocks){ int block_idx; for ((block_idx) = 0; (block_idx) < ((int
)blocks); (block_idx)++) {
{
1775#endif
1776 const size_t row_end = ccv_min(((size_t)block_idx + 1) * 16, k0)({ typeof (((size_t)block_idx + 1) * 16) _a = (((size_t)block_idx
+ 1) * 16); typeof (k0) _b = (k0); (_a < _b) ? _a : _b; }
)
;
1777 size_t r, j, m;
1778 for (r = (size_t)block_idx * 16; r < row_end; r++)
1779 {
1780 const double* const pr = panel + r * w;
1781 for (j = r; j < k0; j++)
1782 {
1783 const double* const pj = panel + j * w;
1784 double v = 0;
1785 for (m = 0; m < w; m++)
1786 v += pr[m] * pj[m];
1787 a[r * n + j] -= v;
1788 }
1789 }
1790#ifdef USE_DISPATCH
1791 });
1792#else
1793 } parallel_endfor} }
1794#endif
1795 ccfreefree(panel);
1796#endif
1797}
1798
1799// Factor H = R R^T with R upper triangular, in place on the upper triangle of a, starting from the
1800// last column so that column k only depends on lanes at or after k. Columns go in panels: factor the
1801// panel's diagonal block, solve each row above it on its contiguous panel segment, then one rank-k
1802// update of the leading block.
1803static int _ccv_nnc_8i_rowwise_x_reverse_cholesky(double* const a, const size_t n)
1804{
1805 size_t k1 = n;
1806 while (k1
51.1
'k1' is > 0
> 0)
62
Loop condition is false. Execution continues on line 1859
1807 {
1808 const size_t k0 = k1
52.1
'k1' is <= CCV_NNC_8I_ROWWISE_X_CHOLESKY_PANEL
> CCV_NNC_8I_ROWWISE_X_CHOLESKY_PANEL ? k1 - CCV_NNC_8I_ROWWISE_X_CHOLESKY_PANEL : 0;
52
Loop condition is true. Entering loop body
53
'?' condition is false
1809 size_t k = k1;
1810 while (k-- > k0)
54
Loop condition is true. Entering loop body
59
Loop condition is false. Execution continues on line 1828
1811 {
1812 const double d = a[k * n + k];
1813 if (!(d > 0))
55
Assuming 'd' is > 0
56
Taking false branch
1814 return 0;
1815 const double rkk = sqrt(d);
1816 a[k * n + k] = rkk;
1817 size_t i, j;
1818 for (i = k0; i < k; i++)
57
Loop condition is false. Execution continues on line 1820
1819 a[i * n + k] /= rkk;
1820 for (i = k0; i < k; i++)
58
Loop condition is false. Execution continues on line 1810
1821 {
1822 const double ci = a[i * n + k];
1823 for (j = i; j < k; j++)
1824 a[i * n + j] -= ci * a[j * n + k];
1825 }
1826 }
1827 // R[i][m] = (H[i][m] - sum_{p in (m, k1)} R[i][p] R[m][p]) / R[m][m] for rows i above the panel.
1828 const size_t blocks = (k0 + 63) / 64;
1829#ifdef USE_DISPATCH
1830 dispatch_apply(blocks, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t block_idx) {
1831#else
1832 parallel_for(block_idx, (int)blocks){ int block_idx; for ((block_idx) = 0; (block_idx) < ((int
)blocks); (block_idx)++) {
{
60
Loop condition is false. Execution continues on line 1855
1833#endif
1834 const size_t row_end = ccv_min(((size_t)block_idx + 1) * 64, k0)({ typeof (((size_t)block_idx + 1) * 64) _a = (((size_t)block_idx
+ 1) * 64); typeof (k0) _b = (k0); (_a < _b) ? _a : _b; }
)
;
1835 size_t r;
1836 for (r = (size_t)block_idx * 64; r < row_end; r++)
1837 {
1838 double* const ar = a + r * n;
1839 size_t m = k1;
1840 while (m-- > k0)
1841 {
1842 const double* const am = a + m * n;
1843 double v = ar[m];
1844 size_t p;
1845 for (p = m + 1; p < k1; p++)
1846 v -= ar[p] * am[p];
1847 ar[m] = v / am[m];
1848 }
1849 }
1850#ifdef USE_DISPATCH
1851 });
1852#else
1853 } parallel_endfor} }
1854#endif
1855 if (k0
60.1
'k0' is <= 0
> 0)
61
Taking false branch
1856 _ccv_nnc_8i_rowwise_x_rank_update(a, n, k0, k1);
1857 k1 = k0;
1858 }
1859 return 1;
1860}
1861
1862// Block UDU^T of H = hessian + ridge I over quantization groups, U unit upper block-triangular. Walking
1863// the groups in order with targets t_k = x_k + sum_{j in earlier groups} e_j U[j][k], where e = x - x_hat,
1864// makes e H e^T = sum_b r_b D_b r_b^T for the rounding residuals r = t - x_hat. Each group then only rounds
1865// against D_b (the input variance conditioned on later groups) instead of the imatrix diagonal.
1866static void _ccv_nnc_8i_rowwise_x_feedback_init(ccv_nnc_8i_rowwise_x_feedback_t* const feedback, const float* const hessian, const size_t row_length, const size_t padded_row_length, const size_t group_size)
1867{
1868 double* const u = feedback->u;
1869 const size_t n = padded_row_length;
1870 size_t i, j;
1871 double mean_diag = 0;
1872 for (i = 0; i
36.1
'i' is < 'row_length'
< row_length
; i++)
37
Loop condition is true. Entering loop body
38
Assuming 'i' is >= 'row_length'
39
Loop condition is false. Execution continues on line 1874
1873 mean_diag += hessian[i * row_length + i];
1874 mean_diag /= (double)row_length;
1875 if (!(mean_diag > 0))
40
Assuming 'mean_diag' is > 0
41
Taking false branch
1876 mean_diag = 1;
1877 double ridge = mean_diag * 1e-6;
1878 int factored = 0;
1879 int attempt;
1880 for (attempt = 0; !factored
41.1
'factored' is 0
63.1
'factored' is 1
&& attempt < 8; attempt++)
42
Loop condition is true. Entering loop body
1881 {
1882 if (attempt
42.1
'attempt' is <= 0
> 0)
43
Taking false branch
1883 ridge *= 10;
1884 for (i = 0; i < n; i++)
44
Assuming 'i' is < 'n'
45
Loop condition is true. Entering loop body
50
Loop condition is false. Execution continues on line 1890
1885 {
1886 for (j = i; j
45.1
'j' is < 'n'
< n
; j++)
47
Assuming 'j' is >= 'n'
48
Loop condition is false. Execution continues on line 1888
1887 u[i * n + j] = (j
45.2
'j' is < 'row_length'
< row_length) ? hessian[i * row_length + j] : 0;
46
'?' condition is true
1888 u[i * n + i] += i
48.1
'i' is < 'row_length'
< row_length ? ridge : mean_diag;
49
'?' condition is true
1889 }
1890 factored = _ccv_nnc_8i_rowwise_x_reverse_cholesky(u, n);
51
Calling '_ccv_nnc_8i_rowwise_x_reverse_cholesky'
63
Returning from '_ccv_nnc_8i_rowwise_x_reverse_cholesky'
1891 }
1892 if (!factored
63.2
'factored' is 1
)
64
Taking false branch
1893 {
1894 // Not positive definite even with a large ridge (non-finite input): drop the feedback.
1895 memset(u, 0, sizeof(double) * n * n);
1896 for (i = 0; i < n; i++)
1897 u[i * n + i] = sqrt(i < row_length ? ccv_max((double)hessian[i * row_length + i], 0.)({ typeof ((double)hessian[i * row_length + i]) _a = ((double
)hessian[i * row_length + i]); typeof (0.) _b = (0.); (_a >
_b) ? _a : _b; })
+ ridge : mean_diag);
1898 }
1899 feedback->hessian = hessian;
1900 feedback->ridge = ridge;
1901 const size_t groups = n / group_size;
1902 size_t g;
1903 for (g = 0; g < groups; g++)
65
Assuming 'g' is < 'groups'
66
Loop condition is true. Entering loop body
1904 {
1905 const size_t s = g * group_size;
1906 double* const rbb = feedback->rbb + g * group_size * group_size;
1907 size_t m, l;
1908 for (m = 0; m < group_size; m++)
67
Assuming 'm' is < 'group_size'
68
Loop condition is true. Entering loop body
1909 {
1910 double d = 0;
1911 for (l = 0; l
68.1
'l' is < 'group_size'
< group_size
; l++)
71
Assuming 'l' is < 'group_size'
1912 {
1913 const double v = l
69.1
'l' is >= 'm'
72.1
'l' is >= 'm'
>= m ? u[(s + m) * n + s + l] : 0
;
69
Loop condition is true. Entering loop body
70
'?' condition is true
72
Loop condition is true. Entering loop body
73
'?' condition is true
74
Assigned value is garbage or undefined
1914 rbb[m * group_size + l] = v;
1915 d += v * v;
1916 }
1917 feedback->weights[s + m] = s + m < row_length ? d : 0;
1918 }
1919 if (s == 0)
1920 continue;
1921 double inv_data[32 * 32] = {0};
1922 double* const inv = inv_data;
1923 for (l = 0; l < group_size; l++)
1924 {
1925 inv[l * group_size + l] = 1. / rbb[l * group_size + l];
1926 m = l;
1927 while (m-- > 0)
1928 {
1929 double v = 0;
1930 size_t t;
1931 for (t = m + 1; t <= l; t++)
1932 v += rbb[m * group_size + t] * inv[t * group_size + l];
1933 inv[m * group_size + l] = -v / rbb[m * group_size + m];
1934 }
1935 }
1936 // U[j][group g] = R[j][group g] R_gg^-1 for every lane j in earlier groups.
1937 const size_t blocks = (s + 63) / 64;
1938#ifdef USE_DISPATCH
1939 dispatch_apply(blocks, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t block_idx) {
1940#else
1941 parallel_for(block_idx, (int)blocks){ int block_idx; for ((block_idx) = 0; (block_idx) < ((int
)blocks); (block_idx)++) {
{
1942#endif
1943 const size_t row_end = ccv_min(((size_t)block_idx + 1) * 64, s)({ typeof (((size_t)block_idx + 1) * 64) _a = (((size_t)block_idx
+ 1) * 64); typeof (s) _b = (s); (_a < _b) ? _a : _b; })
;
1944 size_t r, a, b;
1945 for (r = (size_t)block_idx * 64; r < row_end; r++)
1946 {
1947 double* const ur = u + r * n + s;
1948 double t[32];
1949 for (b = 0; b < group_size; b++)
1950 {
1951 double v = 0;
1952 for (a = 0; a <= b; a++)
1953 v += ur[a] * inv[a * group_size + b];
1954 t[b] = v;
1955 }
1956 memcpy(ur, t, sizeof(double) * group_size);
1957 }
1958#ifdef USE_DISPATCH
1959 });
1960#else
1961 } parallel_endfor} }
1962#endif
1963 }
1964}
1965
1966typedef struct {
1967 const void* input;
1968 int datatype;
1969 int format;
1970 int codec;
1971 int starts;
1972 size_t row_length;
1973 size_t row_count;
1974 const float* imatrix;
1975 size_t imatrix_length;
1976 size_t group_size;
1977 size_t groups_per_row;
1978 size_t padded_row_length;
1979 const int16_t* iq1_map;
1980 uint8_t* u8;
1981 uint8_t* scales;
1982} ccv_nnc_8i_rowwise_x_rows_t;
1983
1984static double _ccv_nnc_8i_rowwise_x_start_scale(const double max_abs, const int start, const int starts, const int datatype)
1985{
1986 double scale = max_abs / 127.;
1987 if (starts == 3)
1988 {
1989 scale *= start == 0 ? 0.75 : start == 1 ? 1. : 1.25;
1990 if (datatype == CCV_16F && max_abs > 0 && _ccv_nnc_8i_rowwise_packed_stored_scale(scale, datatype) == 0)
1991 scale = 0x1p-24;
1992 }
1993 return scale;
1994}
1995
1996static void _ccv_nnc_8i_rowwise_x_pack_row(const ccv_nnc_8i_rowwise_x_rows_t* const ctx, const size_t i, const double* const row, const double* const weights, const int has_best, const double best_scale, const ccv_nnc_8i_rowwise_packed_group_t* const best_groups)
1997{
1998 const size_t group_size = ctx->group_size;
1999 _ccv_nnc_8i_rowwise_packed_store_scale(ctx->scales, ctx->datatype, i, best_scale);
2000 size_t g, j;
2001 if (has_best)
2002 {
2003 for (g = 0; g < ctx->groups_per_row; g++)
2004 _ccv_nnc_8i_rowwise_packed_pack_group(ctx->u8, i * ctx->groups_per_row + g, ctx->codec, best_groups + g);
2005 } else {
2006 for (g = 0; g < ctx->groups_per_row; g++)
2007 {
2008 double y[32] = {0};
2009 double w[32] = {0};
2010 for (j = 0; j < group_size; j++)
2011 {
2012 y[j] = row[g * group_size + j];
2013 w[j] = weights[g * group_size + j];
2014 }
2015 ccv_nnc_8i_rowwise_packed_group_t group;
2016 _ccv_nnc_8i_rowwise_packed_quant_group(ctx->codec, y, w, ctx->iq1_map, &group);
2017 _ccv_nnc_8i_rowwise_packed_pack_group(ctx->u8, i * ctx->groups_per_row + g, ctx->codec, &group);
2018 }
2019 }
2020}
2021
2022static void _ccv_nnc_8i_rowwise_x_quantize_rows(const ccv_nnc_8i_rowwise_x_rows_t* const ctx, const size_t row_begin, const size_t row_end)
2023{
2024 const size_t row_length = ctx->row_length;
2025 const size_t padded_row_length = ctx->padded_row_length;
2026 const size_t group_size = ctx->group_size;
2027 const size_t groups_per_row = ctx->groups_per_row;
2028 const int datatype = ctx->datatype;
2029 double* const row = (double*)ccmallocmalloc(sizeof(double) * padded_row_length);
2030 double* const weights = (double*)ccmallocmalloc(sizeof(double) * padded_row_length);
2031 ccv_nnc_8i_rowwise_packed_group_t* const groups = (ccv_nnc_8i_rowwise_packed_group_t*)ccmallocmalloc(sizeof(ccv_nnc_8i_rowwise_packed_group_t) * groups_per_row);
2032 ccv_nnc_8i_rowwise_packed_group_t* const best_groups = (ccv_nnc_8i_rowwise_packed_group_t*)ccmallocmalloc(sizeof(ccv_nnc_8i_rowwise_packed_group_t) * groups_per_row);
2033 size_t i;
2034 for (i = row_begin; i < row_end; i++)
2035 {
2036 const size_t row_start = i * row_length;
2037 const float* const row_imatrix = _ccv_nnc_8i_rowwise_imatrix_for_row(ctx->imatrix, ctx->imatrix_length, row_length, ctx->row_count, i);
2038 _ccv_nnc_8i_rowwise_packed_read_row(ctx->input, datatype, row_start, row_length, padded_row_length, row);
2039 if (ctx->format & CCV_NNC_QX_8I_ROWWISE_HADAMARD_256)
2040 _ccv_nnc_8i_rowwise_hadamard_256(row, row_length);
2041 double max_abs = 0;
2042 size_t j;
2043 for (j = 0; j < row_length; j++)
2044 {
2045 max_abs = ccv_max(max_abs, fabs(row[j]))({ typeof (max_abs) _a = (max_abs); typeof (fabs(row[j])) _b =
(fabs(row[j])); (_a > _b) ? _a : _b; })
;
2046 weights[j] = _ccv_nnc_8i_rowwise_weight(row_imatrix, j);
2047 }
2048 for (; j < padded_row_length; j++)
2049 weights[j] = 0;
2050 double best_scale = 0;
2051 double best_sse = DBL_MAX1.7976931348623157e+308;
2052 int has_best = 0;
2053 int start;
2054 for (start = 0; start < ctx->starts; start++)
2055 {
2056 double scale = _ccv_nnc_8i_rowwise_x_start_scale(max_abs, start, ctx->starts, datatype);
2057 int k;
2058 for (k = 0; k < CCV_NNC_8I_ROWWISE_X_REFINEMENT_STEPS; k++)
2059 {
2060 const double stored_scale = _ccv_nnc_8i_rowwise_packed_stored_scale(scale, datatype);
2061 if (!(stored_scale > 0))
2062 break;
2063 double sse = 0;
2064 double sum_qx = 0;
2065 double sum_qq = 0;
2066 size_t g;
2067 for (g = 0; g < groups_per_row; g++)
2068 {
2069 double y[32] = {0};
2070 double w[32] = {0};
2071 for (j = 0; j < group_size; j++)
2072 {
2073 y[j] = row[g * group_size + j] / stored_scale;
2074 w[j] = weights[g * group_size + j];
2075 }
2076 ccv_nnc_8i_rowwise_packed_group_t group;
2077 _ccv_nnc_8i_rowwise_packed_quant_group(ctx->codec, y, w, ctx->iq1_map, &group);
2078 groups[g] = group;
2079 const size_t group_start = g * group_size;
2080 const size_t group_end = ccv_min(group_start + group_size, row_length)({ typeof (group_start + group_size) _a = (group_start + group_size
); typeof (row_length) _b = (row_length); (_a < _b) ? _a :
_b; })
;
2081 for (j = group_start; j < group_end; j++)
2082 {
2083 const int q8 = group.q8[j - group_start];
2084 const double d = row[j] - stored_scale * q8;
2085 sse += weights[j] * d * d;
2086 sum_qx += weights[j] * q8 * row[j];
2087 sum_qq += weights[j] * q8 * q8;
2088 }
2089 }
2090 if (sse < best_sse)
2091 {
2092 best_sse = sse;
2093 best_scale = stored_scale;
2094 has_best = 1;
2095 memcpy(best_groups, groups, sizeof(ccv_nnc_8i_rowwise_packed_group_t) * groups_per_row);
2096 }
2097 if (!(sum_qq > 0) || !(sum_qx > 0))
2098 break;
2099 const double next_scale = sum_qx / sum_qq;
2100 if (_ccv_nnc_8i_rowwise_packed_stored_scale(next_scale, datatype) == stored_scale)
2101 break;
2102 scale = next_scale;
2103 }
2104 }
2105 _ccv_nnc_8i_rowwise_x_pack_row(ctx, i, row, weights, has_best, best_scale, best_groups);
2106 }
2107 ccfreefree(best_groups);
2108 ccfreefree(groups);
2109 ccfreefree(weights);
2110 ccfreefree(row);
2111}
2112
2113// The same refinement as the imatrix path, with each pass adding group errors into later targets. Rows of a
2114// chunk run their passes in lockstep so every pass reads the feedback matrix once per chunk, not per row.
2115static void _ccv_nnc_8i_rowwise_x_quantize_rows_feedback(const ccv_nnc_8i_rowwise_x_rows_t* const ctx, const ccv_nnc_8i_rowwise_x_feedback_t* const fb, const size_t row_begin, const size_t row_end)
2116{
2117 enum { R = CCV_NNC_8I_ROWWISE_X_FEEDBACK_ROWS };
2118 const size_t rows = row_end - row_begin;
2119 assert(rows <= R)((void) sizeof ((rows <= R) ? 1 : 0), __extension__ ({ if (
rows <= R) ; else __assert_fail ("rows <= R", "ccv_nnc_8i_rowwise.c"
, 2119, __extension__ __PRETTY_FUNCTION__); }))
;
2120 const size_t row_length = ctx->row_length;
2121 const size_t n = ctx->padded_row_length;
2122 const size_t group_size = ctx->group_size;
2123 const size_t groups_per_row = ctx->groups_per_row;
2124 double* const x = (double*)ccmallocmalloc(sizeof(double) * rows * n);
2125 double* const target = (double*)ccmallocmalloc(sizeof(double) * n * R); // Lane-major: target[l * R + r].
2126 double* const hx = (double*)ccmallocmalloc(sizeof(double) * rows * row_length);
2127 ccv_nnc_8i_rowwise_packed_group_t* const groups = (ccv_nnc_8i_rowwise_packed_group_t*)ccmallocmalloc(sizeof(ccv_nnc_8i_rowwise_packed_group_t) * rows * groups_per_row);
2128 ccv_nnc_8i_rowwise_packed_group_t* const best_groups = (ccv_nnc_8i_rowwise_packed_group_t*)ccmallocmalloc(sizeof(ccv_nnc_8i_rowwise_packed_group_t) * rows * groups_per_row);
2129 double max_abs[R], xhx[R], scale[R], stored_scale[R], sse[R], sum_qx[R], best_sse[R], best_scale[R];
2130 int has_best[R], start[R], step[R], ready[R], done[R];
2131 double e[32][R];
2132 size_t r, j, l;
2133 for (r = 0; r < rows; r++)
2134 {
2135 double* const xr = x + r * n;
2136 _ccv_nnc_8i_rowwise_packed_read_row(ctx->input, ctx->datatype, (row_begin + r) * row_length, row_length, n, xr);
2137 max_abs[r] = 0;
2138 for (j = 0; j < row_length; j++)
2139 max_abs[r] = ccv_max(max_abs[r], fabs(xr[j]))({ typeof (max_abs[r]) _a = (max_abs[r]); typeof (fabs(xr[j])
) _b = (fabs(xr[j])); (_a > _b) ? _a : _b; })
;
2140 xhx[r] = 0;
2141 best_sse[r] = DBL_MAX1.7976931348623157e+308;
2142 best_scale[r] = 0;
2143 has_best[r] = 0;
2144 start[r] = 0;
2145 step[r] = 0;
2146 done[r] = 0;
2147 scale[r] = _ccv_nnc_8i_rowwise_x_start_scale(max_abs[r], 0, ctx->starts, ctx->datatype);
2148 }
2149 // hx = (hessian + ridge I) x, reading each Hessian row once for the chunk.
2150 for (j = 0; j < row_length; j++)
2151 {
2152 const float* const cj = fb->hessian + j * row_length;
2153 for (r = 0; r < rows; r++)
2154 {
2155 const double* const xr = x + r * n;
2156 double v = fb->ridge * xr[j];
2157 for (l = 0; l < row_length; l++)
2158 v += cj[l] * xr[l];
2159 hx[r * row_length + j] = v;
2160 xhx[r] += xr[j] * v;
2161 }
2162 }
2163 for (;;)
2164 {
2165 int any = 0;
2166 for (r = 0; r < rows; r++)
2167 {
2168 ready[r] = 0;
2169 while (!done[r])
2170 {
2171 stored_scale[r] = _ccv_nnc_8i_rowwise_packed_stored_scale(scale[r], ctx->datatype);
2172 if (stored_scale[r] > 0)
2173 {
2174 ready[r] = 1;
2175 any = 1;
2176 break;
2177 }
2178 if (++start[r] >= ctx->starts)
2179 done[r] = 1;
2180 else {
2181 step[r] = 0;
2182 scale[r] = _ccv_nnc_8i_rowwise_x_start_scale(max_abs[r], start[r], ctx->starts, ctx->datatype);
2183 }
2184 }
2185 sse[r] = 0;
2186 sum_qx[r] = 0;
2187 }
2188 if (!any)
2189 break;
2190 for (l = 0; l < n; l++)
2191 for (r = 0; r < R; r++)
2192 target[l * R + r] = (r < rows && ready[r]) ? x[r * n + l] : 0;
2193 size_t g;
2194 for (g = 0; g < groups_per_row; g++)
2195 {
2196 const size_t group_start = g * group_size;
2197 const size_t group_end = ccv_min(group_start + group_size, row_length)({ typeof (group_start + group_size) _a = (group_start + group_size
); typeof (row_length) _b = (row_length); (_a < _b) ? _a :
_b; })
;
2198 const size_t next_group = group_start + group_size;
2199 memset(e, 0, sizeof(e));
2200 for (r = 0; r < rows; r++)
2201 {
2202 if (!ready[r])
2203 continue;
2204 double y[32] = {0};
2205 double w[32] = {0};
2206 for (j = 0; j < group_size; j++)
2207 {
2208 y[j] = target[(group_start + j) * R + r] / stored_scale[r];
2209 w[j] = fb->weights[group_start + j];
2210 }
2211 ccv_nnc_8i_rowwise_packed_group_t* const group = groups + r * groups_per_row + g;
2212 _ccv_nnc_8i_rowwise_packed_quant_group(ctx->codec, y, w, ctx->iq1_map, group);
2213 double res[32] = {0};
2214 for (j = group_start; j < group_end; j++)
2215 {
2216 const int q8 = group->q8[j - group_start];
2217 res[j - group_start] = target[j * R + r] - stored_scale[r] * q8;
2218 e[j - group_start][r] = x[r * n + j] - stored_scale[r] * q8;
2219 sum_qx[r] += q8 * hx[r * row_length + j];
2220 }
2221 // r_b D_b r_b^T = |r_b R_bb|^2.
2222 const double* const rbb = fb->rbb + g * group_size * group_size;
2223 size_t m;
2224 for (l = 0; l < group_size; l++)
2225 {
2226 double v = 0;
2227 for (m = 0; m <= l; m++)
2228 v += res[m] * rbb[m * group_size + l];
2229 sse[r] += v * v;
2230 }
2231 }
2232 // Later lanes in tiles that stay in cache across this group's feedback rows.
2233 size_t l0;
2234 for (l0 = next_group; l0 < n; l0 += 64)
2235 {
2236 const size_t l1 = ccv_min(l0 + 64, n)({ typeof (l0 + 64) _a = (l0 + 64); typeof (n) _b = (n); (_a <
_b) ? _a : _b; })
;
2237 for (j = 0; j < group_end - group_start; j++)
2238 {
2239 const double* const uj = fb->u + (group_start + j) * n;
2240 const double* const ej = e[j];
2241 for (l = l0; l < l1; l++)
2242 {
2243 const double u = uj[l];
2244 double* const t = target + l * R;
2245 for (r = 0; r < R; r++)
2246 t[r] += ej[r] * u;
2247 }
2248 }
2249 }
2250 }
2251 for (r = 0; r < rows; r++)
2252 {
2253 if (!ready[r])
2254 continue;
2255 // sse = e H e^T = x H x - 2 s q H x + s^2 q H q.
2256 const double s = stored_scale[r];
2257 const double sum_qq = (sse[r] - xhx[r] + 2 * s * sum_qx[r]) / (s * s);
2258 if (sse[r] < best_sse[r])
2259 {
2260 best_sse[r] = sse[r];
2261 best_scale[r] = s;
2262 has_best[r] = 1;
2263 memcpy(best_groups + r * groups_per_row, groups + r * groups_per_row, sizeof(ccv_nnc_8i_rowwise_packed_group_t) * groups_per_row);
2264 }
2265 int next_start = 1;
2266 if (sum_qq > 0 && sum_qx[r] > 0)
2267 {
2268 const double next_scale = sum_qx[r] / sum_qq;
2269 if (_ccv_nnc_8i_rowwise_packed_stored_scale(next_scale, ctx->datatype) != s && ++step[r] < CCV_NNC_8I_ROWWISE_X_REFINEMENT_STEPS)
2270 {
2271 scale[r] = next_scale;
2272 next_start = 0;
2273 }
2274 }
2275 if (next_start)
2276 {
2277 step[r] = 0;
2278 if (++start[r] >= ctx->starts)
2279 done[r] = 1;
2280 else
2281 scale[r] = _ccv_nnc_8i_rowwise_x_start_scale(max_abs[r], start[r], ctx->starts, ctx->datatype);
2282 }
2283 }
2284 }
2285 for (r = 0; r < rows; r++)
2286 _ccv_nnc_8i_rowwise_x_pack_row(ctx, row_begin + r, x + r * n, fb->weights, has_best[r], best_scale[r], best_groups + r * groups_per_row);
2287 ccfreefree(best_groups);
2288 ccfreefree(groups);
2289 ccfreefree(hx);
2290 ccfreefree(target);
2291 ccfreefree(x);
2292}
2293
2294static size_t _ccv_nnc_quantize_8i_rowwise_x(const void* input, const int datatype, const size_t input_length, const size_t row_length, const int format, const float* const imatrix, const size_t imatrix_length, const float* const hessian, const size_t hessian_length, void* output, const size_t output_length)
2295{
2296 const int codec = format & CCV_NNC_QX_8I_ROWWISE_FORMAT_MASK;
2297 const size_t row_count = input_length / row_length;
2298 const size_t group_size = ccv_nnc_8i_rowwise_x_group_size(format);
2299 const int group_bits = ccv_nnc_8i_rowwise_x_group_bits(format);
2300 const size_t groups_per_row = (row_length + group_size - 1) / group_size;
2301 const size_t padded_row_length = groups_per_row * group_size;
2302 const size_t scale_offset = _ccv_nnc_8i_rowwise_packed_scale_offset(format, input_length, row_length);
2303 const size_t output_size = scale_offset + row_count * CCV_GET_DATA_TYPE_SIZE(datatype)_ccv_get_data_type_size[((datatype) & 0xFF000) >> 12
]
;
2304 if (output_length < output_size)
20
Assuming 'output_length' is >= 'output_size'
21
Taking false branch
2305 return 0;
2306 int16_t* iq1_map = 0;
2307 const int starts = (codec == CCV_NNC_QX_8I_ROWWISE_IQ1_S || codec == CCV_NNC_QX_8I_ROWWISE_IQ1_M) ? 3 : 1;
22
Assuming 'codec' is not equal to CCV_NNC_QX_8I_ROWWISE_IQ1_S
23
Assuming 'codec' is not equal to CCV_NNC_QX_8I_ROWWISE_IQ1_M
24
'?' condition is false
2308 if (starts
24.1
'starts' is not equal to 3
== 3)
25
Taking false branch
2309 {
2310 iq1_map = (int16_t*)ccmallocmalloc(sizeof(int16_t) * 6561);
2311 int i, j;
2312 for (i = 0; i < 6561; i++)
2313 iq1_map[i] = -1;
2314 for (i = 0; i < 2048; i++)
2315 {
2316 int code = 0;
2317 for (j = 0; j < 8; j++)
2318 code += ((ccv_nnc_8i_rowwise_packed_iq1_grid[i] >> (2 * j)) & 3) * ccv_nnc_8i_rowwise_packed_iq1_powers[j];
2319 iq1_map[code] = (int16_t)i;
2320 }
2321 }
2322 switch (codec)
26
'Default' branch taken. Execution continues on line 2340
2323 {
2324 case CCV_NNC_QX_8I_ROWWISE_IQ2_XXS:
2325 _ccv_nnc_8i_rowwise_packed_iq2xxs_candidates_init();
2326 break;
2327 case CCV_NNC_QX_8I_ROWWISE_IQ2_XS:
2328 _ccv_nnc_8i_rowwise_packed_iq2xs_candidates_init();
2329 break;
2330 case CCV_NNC_QX_8I_ROWWISE_IQ2_S:
2331 _ccv_nnc_8i_rowwise_packed_iq2s_init();
2332 break;
2333 case CCV_NNC_QX_8I_ROWWISE_IQ3_S:
2334 _ccv_nnc_8i_rowwise_packed_iq3s_init();
2335 break;
2336 case CCV_NNC_QX_8I_ROWWISE_IQ3_XXS:
2337 _ccv_nnc_8i_rowwise_packed_iq3xxs_candidates_init();
2338 break;
2339 }
2340 uint8_t* const u8 = (uint8_t*)output;
2341 uint8_t* const scales = u8 + scale_offset;
2342 memset(u8, 0, scale_offset);
2343 const size_t row_bits = groups_per_row * group_bits;
2344 size_t rows_per_chunk;
2345 switch (row_bits & 7)
27
Control jumps to the 'default' case at line 2357
2346 {
2347 case 0:
2348 rows_per_chunk = 1;
2349 break;
2350 case 4:
2351 rows_per_chunk = 2;
2352 break;
2353 case 2:
2354 case 6:
2355 rows_per_chunk = 4;
2356 break;
2357 default:
2358 rows_per_chunk = 8;
2359 break;
28
Execution continues on line 2361
2360 }
2361 rows_per_chunk = ccv_max(rows_per_chunk, (size_t)8)({ typeof (rows_per_chunk) _a = (rows_per_chunk); typeof ((size_t
)8) _b = ((size_t)8); (_a > _b) ? _a : _b; })
;
29
'?' condition is false
2362 // Feedback chunks are a multiple of the packing chunk, so they stay byte aligned.
2363 if (hessian
29.1
'hessian' is non-null
)
30
Taking true branch
2364 rows_per_chunk = CCV_NNC_8I_ROWWISE_X_FEEDBACK_ROWS;
2365 const ccv_nnc_8i_rowwise_x_rows_t rows_data = {
2366 .input = input,
2367 .datatype = datatype,
2368 .format = format,
2369 .codec = codec,
2370 .starts = starts,
2371 .row_length = row_length,
2372 .row_count = row_count,
2373 .imatrix = imatrix,
2374 .imatrix_length = imatrix_length,
2375 .group_size = group_size,
2376 .groups_per_row = groups_per_row,
2377 .padded_row_length = padded_row_length,
2378 .iq1_map = iq1_map,
2379 .u8 = u8,
2380 .scales = scales,
2381 };
2382 const ccv_nnc_8i_rowwise_x_rows_t* const ctx = &rows_data;
2383 // Each Hessian slice is factored once and shared by its rows. Slices run one after another, so a
2384 // chunk that straddles two slices never writes its packed bytes concurrently.
2385 const size_t slices = hessian
30.1
'hessian' is non-null
? hessian_length / (row_length * row_length) : 1;
31
'?' condition is true
2386 const size_t rows_per_slice = row_count / slices;
2387 ccv_nnc_8i_rowwise_x_feedback_t feedback = {0};
2388 if (hessian
31.1
'hessian' is non-null
)
32
Taking true branch
2389 {
2390 feedback.u = (double*)ccmallocmalloc(sizeof(double) * padded_row_length * padded_row_length);
33
Storing uninitialized value
2391 feedback.rbb = (double*)ccmallocmalloc(sizeof(double) * padded_row_length * group_size);
2392 feedback.weights = (double*)ccmallocmalloc(sizeof(double) * padded_row_length);
2393 }
2394 size_t slice;
2395 for (slice = 0; slice
33.1
'slice' is < 'slices'
< slices; slice++)
34
Loop condition is true. Entering loop body
2396 {
2397 const size_t row_begin = slice * rows_per_slice;
2398 const size_t row_end = row_begin + rows_per_slice;
2399 if (hessian
34.1
'hessian' is non-null
)
35
Taking true branch
2400 _ccv_nnc_8i_rowwise_x_feedback_init(&feedback, hessian + slice * row_length * row_length, row_length, padded_row_length, group_size);
36
Calling '_ccv_nnc_8i_rowwise_x_feedback_init'
2401 const ccv_nnc_8i_rowwise_x_feedback_t* const fb = hessian ? &feedback : 0;
2402 const size_t first_chunk = row_begin / rows_per_chunk;
2403 const size_t row_chunks = (row_end + rows_per_chunk - 1) / rows_per_chunk - first_chunk;
2404#ifdef USE_DISPATCH
2405 dispatch_apply(row_chunks, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t chunk_idx) {
2406#else
2407 parallel_for(chunk_idx, (int)row_chunks){ int chunk_idx; for ((chunk_idx) = 0; (chunk_idx) < ((int
)row_chunks); (chunk_idx)++) {
{
2408#endif
2409 const size_t chunk_begin = ccv_max((first_chunk + (size_t)chunk_idx) * rows_per_chunk, row_begin)({ typeof ((first_chunk + (size_t)chunk_idx) * rows_per_chunk
) _a = ((first_chunk + (size_t)chunk_idx) * rows_per_chunk); typeof
(row_begin) _b = (row_begin); (_a > _b) ? _a : _b; })
;
2410 const size_t chunk_end = ccv_min((first_chunk + (size_t)chunk_idx + 1) * rows_per_chunk, row_end)({ typeof ((first_chunk + (size_t)chunk_idx + 1) * rows_per_chunk
) _a = ((first_chunk + (size_t)chunk_idx + 1) * rows_per_chunk
); typeof (row_end) _b = (row_end); (_a < _b) ? _a : _b; }
)
;
2411 if (fb)
2412 _ccv_nnc_8i_rowwise_x_quantize_rows_feedback(ctx, fb, chunk_begin, chunk_end);
2413 else
2414 _ccv_nnc_8i_rowwise_x_quantize_rows(ctx, chunk_begin, chunk_end);
2415#ifdef USE_DISPATCH
2416 });
2417#else
2418 } parallel_endfor} }
2419#endif
2420 }
2421 if (hessian)
2422 {
2423 ccfreefree(feedback.weights);
2424 ccfreefree(feedback.rbb);
2425 ccfreefree(feedback.u);
2426 }
2427 ccfreefree(iq1_map);
2428 return output_size;
2429}
2430
2431CCV_WARN_UNUSED(size_t)size_t __attribute__((warn_unused_result)) ccv_nnc_quantize_8i_rowwise_x(const void* input, const int datatype, const int memory_type, const size_t input_length, const size_t row_length, const int format, const float* const imatrix, const size_t imatrix_length, const float* const hessian, const size_t hessian_length, void* output, const size_t output_length)
2432{
2433 if (row_length == 0 || input_length % row_length != 0 || (imatrix && hessian) ||
1
Assuming 'row_length' is not equal to 0
2
Assuming the condition is false
3
Assuming 'imatrix' is null
2434 ((format & CCV_NNC_QX_8I_ROWWISE_HADAMARD_256) && (row_length % 256 != 0 || hessian)))
4
Assuming the condition is false
2435 return 0;
2436 assert(datatype == CCV_16F || datatype == CCV_16BF || datatype == CCV_32F || datatype == CCV_64F)((void) sizeof ((datatype == CCV_16F || datatype == CCV_16BF ||
datatype == CCV_32F || datatype == CCV_64F) ? 1 : 0), __extension__
({ if (datatype == CCV_16F || datatype == CCV_16BF || datatype
== CCV_32F || datatype == CCV_64F) ; else __assert_fail ("datatype == CCV_16F || datatype == CCV_16BF || datatype == CCV_32F || datatype == CCV_64F"
, "ccv_nnc_8i_rowwise.c", 2436, __extension__ __PRETTY_FUNCTION__
); }))
;
5
Assuming 'datatype' is not equal to CCV_16F
6
Assuming 'datatype' is not equal to CCV_16BF
7
Assuming 'datatype' is not equal to CCV_32F
8
Assuming 'datatype' is equal to CCV_64F
9
Taking true branch
2437 assert(memory_type == CCV_TENSOR_CPU_MEMORY)((void) sizeof ((memory_type == CCV_TENSOR_CPU_MEMORY) ? 1 : 0
), __extension__ ({ if (memory_type == CCV_TENSOR_CPU_MEMORY)
; else __assert_fail ("memory_type == CCV_TENSOR_CPU_MEMORY"
, "ccv_nnc_8i_rowwise.c", 2437, __extension__ __PRETTY_FUNCTION__
); }))
;
10
Assuming 'memory_type' is equal to CCV_TENSOR_CPU_MEMORY
11
Taking true branch
2438 const size_t row_count = input_length / row_length;
2439 if (!_ccv_nnc_8i_rowwise_imatrix_is_valid(imatrix, imatrix_length, row_length, row_count))
12
Taking false branch
2440 return 0;
2441 if (hessian)
13
Assuming 'hessian' is non-null
14
Taking true branch
2442 {
2443 const size_t matrix_length = row_length * row_length;
2444 if (hessian_length < matrix_length || hessian_length % matrix_length != 0 || row_count % (hessian_length / matrix_length) != 0)
15
Assuming 'hessian_length' is >= 'matrix_length'
16
Assuming the condition is false
17
Assuming the condition is false
18
Taking false branch
2445 return 0;
2446 }
2447 return _ccv_nnc_quantize_8i_rowwise_x(input, datatype, input_length, row_length, format, imatrix, imatrix_length, hessian, hessian_length, output, output_length);
19
Calling '_ccv_nnc_quantize_8i_rowwise_x'
2448}
2449
2450void ccv_nnc_dequantize_8i_rowwise_x(const void* input, const int datatype, const int memory_type, const size_t input_length, const size_t row_length, const int format, void* output, const size_t output_length)
2451{
2452 assert(datatype == CCV_16F || datatype == CCV_16BF || datatype == CCV_32F || datatype == CCV_64F)((void) sizeof ((datatype == CCV_16F || datatype == CCV_16BF ||
datatype == CCV_32F || datatype == CCV_64F) ? 1 : 0), __extension__
({ if (datatype == CCV_16F || datatype == CCV_16BF || datatype
== CCV_32F || datatype == CCV_64F) ; else __assert_fail ("datatype == CCV_16F || datatype == CCV_16BF || datatype == CCV_32F || datatype == CCV_64F"
, "ccv_nnc_8i_rowwise.c", 2452, __extension__ __PRETTY_FUNCTION__
); }))
;
2453 assert(memory_type == CCV_TENSOR_CPU_MEMORY || memory_type == CCV_TENSOR_GPU_MEMORY)((void) sizeof ((memory_type == CCV_TENSOR_CPU_MEMORY || memory_type
== CCV_TENSOR_GPU_MEMORY) ? 1 : 0), __extension__ ({ if (memory_type
== CCV_TENSOR_CPU_MEMORY || memory_type == CCV_TENSOR_GPU_MEMORY
) ; else __assert_fail ("memory_type == CCV_TENSOR_CPU_MEMORY || memory_type == CCV_TENSOR_GPU_MEMORY"
, "ccv_nnc_8i_rowwise.c", 2453, __extension__ __PRETTY_FUNCTION__
); }))
;
2454 assert(row_length > 0)((void) sizeof ((row_length > 0) ? 1 : 0), __extension__ (
{ if (row_length > 0) ; else __assert_fail ("row_length > 0"
, "ccv_nnc_8i_rowwise.c", 2454, __extension__ __PRETTY_FUNCTION__
); }))
;
2455 assert(output_length % row_length == 0)((void) sizeof ((output_length % row_length == 0) ? 1 : 0), __extension__
({ if (output_length % row_length == 0) ; else __assert_fail
("output_length % row_length == 0", "ccv_nnc_8i_rowwise.c", 2455
, __extension__ __PRETTY_FUNCTION__); }))
;
2456 assert(!(format & CCV_NNC_QX_8I_ROWWISE_HADAMARD_256) || row_length % 256 == 0)((void) sizeof ((!(format & CCV_NNC_QX_8I_ROWWISE_HADAMARD_256
) || row_length % 256 == 0) ? 1 : 0), __extension__ ({ if (!(
format & CCV_NNC_QX_8I_ROWWISE_HADAMARD_256) || row_length
% 256 == 0) ; else __assert_fail ("!(format & CCV_NNC_QX_8I_ROWWISE_HADAMARD_256) || row_length % 256 == 0"
, "ccv_nnc_8i_rowwise.c", 2456, __extension__ __PRETTY_FUNCTION__
); }))
;
2457 if (memory_type != CCV_TENSOR_CPU_MEMORY)
2458 {
2459#ifdef HAVE_CUDA1
2460 ccv_nnc_compat_dequantize_8i_rowwise_x_fp(input, datatype, input_length, row_length, format, output, output_length, 0);
2461#elif defined(HAVE_MPS)
2462 assert(datatype != CCV_64F)((void) sizeof ((datatype != CCV_64F) ? 1 : 0), __extension__
({ if (datatype != CCV_64F) ; else __assert_fail ("datatype != CCV_64F"
, "ccv_nnc_8i_rowwise.c", 2462, __extension__ __PRETTY_FUNCTION__
); }))
;
2463 ccv_nnc_mps_dequantize_8i_rowwise_x(input, datatype, input_length, row_length, format, output, output_length, 0);
2464#else
2465 assert(memory_type == CCV_TENSOR_CPU_MEMORY)((void) sizeof ((memory_type == CCV_TENSOR_CPU_MEMORY) ? 1 : 0
), __extension__ ({ if (memory_type == CCV_TENSOR_CPU_MEMORY)
; else __assert_fail ("memory_type == CCV_TENSOR_CPU_MEMORY"
, "ccv_nnc_8i_rowwise.c", 2465, __extension__ __PRETTY_FUNCTION__
); }))
;
2466#endif
2467 return;
2468 }
2469 const size_t row_count = output_length / row_length;
2470 const size_t group_size = ccv_nnc_8i_rowwise_x_group_size(format);
2471 const size_t groups_per_row = (row_length + group_size - 1) / group_size;
2472 const size_t scale_offset = _ccv_nnc_8i_rowwise_packed_scale_offset(format, output_length, row_length);
2473 assert(input_length >= scale_offset + row_count * CCV_GET_DATA_TYPE_SIZE(datatype))((void) sizeof ((input_length >= scale_offset + row_count *
_ccv_get_data_type_size[((datatype) & 0xFF000) >> 12
]) ? 1 : 0), __extension__ ({ if (input_length >= scale_offset
+ row_count * _ccv_get_data_type_size[((datatype) & 0xFF000
) >> 12]) ; else __assert_fail ("input_length >= scale_offset + row_count * CCV_GET_DATA_TYPE_SIZE(datatype)"
, "ccv_nnc_8i_rowwise.c", 2473, __extension__ __PRETTY_FUNCTION__
); }))
;
2474 const uint8_t* const u8 = (const uint8_t*)input;
2475 const uint8_t* const scales = u8 + scale_offset;
2476 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2477 const double scale = _ccv_nnc_8i_rowwise_packed_load_scale(scales, datatype, i);
2478 if (format & CCV_NNC_QX_8I_ROWWISE_HADAMARD_256)
2479 {
2480 // Transform decoded integers before scaling / rounding to the destination
2481 // precision. H256 is its own inverse and acts on independent blocks.
2482 double block[256];
2483 size_t base;
2484 for (base = 0; base < row_length; base += 256)
2485 {
2486 size_t g;
2487 for (g = 0; g < 256 / group_size; g++)
2488 {
2489 int q8[32] = {0};
2490 _ccv_nnc_8i_rowwise_packed_decode_group(u8, (size_t)i * groups_per_row + base / group_size + g, format & CCV_NNC_QX_8I_ROWWISE_FORMAT_MASK, q8);
2491 size_t j;
2492 for (j = 0; j < group_size; j++)
2493 block[g * group_size + j] = q8[j];
2494 }
2495 _ccv_nnc_8i_rowwise_hadamard_256(block, 256);
2496 size_t j;
2497 for (j = 0; j < 256; j++)
2498 _ccv_nnc_8i_rowwise_packed_write_value(output, datatype, (size_t)i * row_length + base + j, scale * block[j]);
2499 }
2500 } else {
2501 size_t g;
2502 for (g = 0; g < groups_per_row; g++)
2503 {
2504 int q8[32] = {0};
2505 _ccv_nnc_8i_rowwise_packed_decode_group(u8, (size_t)i * groups_per_row + g, format, q8);
2506 size_t j;
2507 for (j = 0; j < group_size; j++)
2508 {
2509 const size_t col = g * group_size + j;
2510 if (col < row_length)
2511 _ccv_nnc_8i_rowwise_packed_write_value(output, datatype, (size_t)i * row_length + col, scale * q8[j]);
2512 }
2513 }
2514 }
2515 } parallel_endfor} }
2516}
2517
2518static inline int _ccv_nnc_8i_rowwise_quantize(const double v, const double inv_scale)
2519{
2520 const int q = (int)lrint(v * inv_scale);
2521 return ccv_clamp(q, -127, 127)({ typeof (-127) _a = (-127); typeof (127) _b = (127); typeof
(q) _x = (q); (_x < _a) ? _a : ((_x > _b) ? _b : _x); }
)
;
2522}
2523
2524static float _ccv_nnc_quantize_8i_rowwise_16f(const uint16_t* const row, const size_t row_length, const float* const imatrix, int8_t* const q)
2525{
2526 size_t j;
2527 double max_abs = 0;
2528 for (j = 0; j < row_length; j++)
2529 {
2530 float v;
2531 ccv_half_precision_to_float(row + j, &v, 1);
2532 max_abs = ccv_max(max_abs, fabs(v))({ typeof (max_abs) _a = (max_abs); typeof (fabs(v)) _b = (fabs
(v)); (_a > _b) ? _a : _b; })
;
2533 }
2534 if (max_abs == 0)
2535 {
2536 memset(q, 0, row_length);
2537 return 0;
2538 }
2539 double scale = max_abs / 127.;
2540 float best_scale = 0;
2541 double best_sse = DBL_MAX1.7976931348623157e+308;
2542 int k;
2543 for (k = 0; k < 8; k++)
2544 {
2545 // Round with the scale that will actually be stored, then refit scale by least squares.
2546 const float scale_f = (float)scale;
2547 uint16_t scale_h;
2548 float stored_scale;
2549 ccv_float_to_half_precision(&scale_f, &scale_h, 1);
2550 ccv_half_precision_to_float(&scale_h, &stored_scale, 1);
2551 if (!(stored_scale > 0))
2552 break;
2553 const double inv_scale = 1. / stored_scale;
2554 double sum_qx = 0;
2555 double sum_qq = 0;
2556 double sse = 0;
2557 for (j = 0; j < row_length; j++)
2558 {
2559 const double w = _ccv_nnc_8i_rowwise_weight(imatrix, j);
2560 float v_f;
2561 ccv_half_precision_to_float(row + j, &v_f, 1);
2562 const double v = v_f;
2563 const int qj = _ccv_nnc_8i_rowwise_quantize(v, inv_scale);
2564 const double d = v - stored_scale * qj;
2565 sse += w * d * d;
2566 sum_qx += w * qj * v;
2567 sum_qq += w * qj * qj;
2568 }
2569 if (sse < best_sse)
2570 {
2571 best_sse = sse;
2572 best_scale = stored_scale;
2573 }
2574 if (!(sum_qq > 0) || !(sum_qx > 0))
2575 break;
2576 const double next_scale = sum_qx / sum_qq;
2577 const float next_scale_f = (float)next_scale;
2578 uint16_t next_scale_h;
2579 float next_stored_scale;
2580 ccv_float_to_half_precision(&next_scale_f, &next_scale_h, 1);
2581 ccv_half_precision_to_float(&next_scale_h, &next_stored_scale, 1);
2582 if (next_stored_scale == stored_scale)
2583 break;
2584 scale = next_scale;
2585 }
2586 if (!(best_scale > 0))
2587 {
2588 memset(q, 0, row_length);
2589 return 0;
2590 }
2591 const double inv_scale = 1. / best_scale;
2592 for (j = 0; j < row_length; j++)
2593 {
2594 float v;
2595 ccv_half_precision_to_float(row + j, &v, 1);
2596 q[j] = (int8_t)_ccv_nnc_8i_rowwise_quantize(v, inv_scale);
2597 }
2598 return best_scale;
2599}
2600
2601static float _ccv_nnc_quantize_8i_rowwise_16bf(const uint16_t* const row, const size_t row_length, const float* const imatrix, int8_t* const q)
2602{
2603 size_t j;
2604 double max_abs = 0;
2605 for (j = 0; j < row_length; j++)
2606 {
2607 float v;
2608 ccv_bfloat_to_float(row + j, &v, 1);
2609 max_abs = ccv_max(max_abs, fabs(v))({ typeof (max_abs) _a = (max_abs); typeof (fabs(v)) _b = (fabs
(v)); (_a > _b) ? _a : _b; })
;
2610 }
2611 if (max_abs == 0)
2612 {
2613 memset(q, 0, row_length);
2614 return 0;
2615 }
2616 double scale = max_abs / 127.;
2617 float best_scale = 0;
2618 double best_sse = DBL_MAX1.7976931348623157e+308;
2619 int k;
2620 for (k = 0; k < 8; k++)
2621 {
2622 const float scale_f = (float)scale;
2623 uint16_t scale_bf;
2624 float stored_scale;
2625 ccv_float_to_bfloat(&scale_f, &scale_bf, 1);
2626 ccv_bfloat_to_float(&scale_bf, &stored_scale, 1);
2627 if (!(stored_scale > 0))
2628 break;
2629 const double inv_scale = 1. / stored_scale;
2630 double sum_qx = 0;
2631 double sum_qq = 0;
2632 double sse = 0;
2633 for (j = 0; j < row_length; j++)
2634 {
2635 const double w = _ccv_nnc_8i_rowwise_weight(imatrix, j);
2636 float v_f;
2637 ccv_bfloat_to_float(row + j, &v_f, 1);
2638 const double v = v_f;
2639 const int qj = _ccv_nnc_8i_rowwise_quantize(v, inv_scale);
2640 const double d = v - stored_scale * qj;
2641 sse += w * d * d;
2642 sum_qx += w * qj * v;
2643 sum_qq += w * qj * qj;
2644 }
2645 if (sse < best_sse)
2646 {
2647 best_sse = sse;
2648 best_scale = stored_scale;
2649 }
2650 if (!(sum_qq > 0) || !(sum_qx > 0))
2651 break;
2652 const double next_scale = sum_qx / sum_qq;
2653 const float next_scale_f = (float)next_scale;
2654 uint16_t next_scale_bf;
2655 float next_stored_scale;
2656 ccv_float_to_bfloat(&next_scale_f, &next_scale_bf, 1);
2657 ccv_bfloat_to_float(&next_scale_bf, &next_stored_scale, 1);
2658 if (next_stored_scale == stored_scale)
2659 break;
2660 scale = next_scale;
2661 }
2662 if (!(best_scale > 0))
2663 {
2664 memset(q, 0, row_length);
2665 return 0;
2666 }
2667 const double inv_scale = 1. / best_scale;
2668 for (j = 0; j < row_length; j++)
2669 {
2670 float v;
2671 ccv_bfloat_to_float(row + j, &v, 1);
2672 q[j] = (int8_t)_ccv_nnc_8i_rowwise_quantize(v, inv_scale);
2673 }
2674 return best_scale;
2675}
2676
2677static float _ccv_nnc_quantize_8i_rowwise_32f(const float* const row, const size_t row_length, const float* const imatrix, int8_t* const q)
2678{
2679 size_t j;
2680 double max_abs = 0;
2681 for (j = 0; j < row_length; j++)
2682 max_abs = ccv_max(max_abs, fabs(row[j]))({ typeof (max_abs) _a = (max_abs); typeof (fabs(row[j])) _b =
(fabs(row[j])); (_a > _b) ? _a : _b; })
;
2683 if (max_abs == 0)
2684 {
2685 memset(q, 0, row_length);
2686 return 0;
2687 }
2688 double scale = max_abs / 127.;
2689 float best_scale = 0;
2690 double best_sse = DBL_MAX1.7976931348623157e+308;
2691 int k;
2692 for (k = 0; k < 8; k++)
2693 {
2694 const float stored_scale = (float)scale;
2695 if (!(stored_scale > 0))
2696 break;
2697 const double inv_scale = 1. / stored_scale;
2698 double sum_qx = 0;
2699 double sum_qq = 0;
2700 double sse = 0;
2701 for (j = 0; j < row_length; j++)
2702 {
2703 const double w = _ccv_nnc_8i_rowwise_weight(imatrix, j);
2704 const double v = row[j];
2705 const int qj = _ccv_nnc_8i_rowwise_quantize(v, inv_scale);
2706 const double d = v - stored_scale * qj;
2707 sse += w * d * d;
2708 sum_qx += w * qj * v;
2709 sum_qq += w * qj * qj;
2710 }
2711 if (sse < best_sse)
2712 {
2713 best_sse = sse;
2714 best_scale = stored_scale;
2715 }
2716 if (!(sum_qq > 0) || !(sum_qx > 0))
2717 break;
2718 const double next_scale = sum_qx / sum_qq;
2719 if ((float)next_scale == stored_scale)
2720 break;
2721 scale = next_scale;
2722 }
2723 if (!(best_scale > 0))
2724 {
2725 memset(q, 0, row_length);
2726 return 0;
2727 }
2728 const double inv_scale = 1. / best_scale;
2729 for (j = 0; j < row_length; j++)
2730 q[j] = (int8_t)_ccv_nnc_8i_rowwise_quantize(row[j], inv_scale);
2731 return best_scale;
2732}
2733
2734static double _ccv_nnc_quantize_8i_rowwise_64f(const double* const row, const size_t row_length, const float* const imatrix, int8_t* const q)
2735{
2736 size_t j;
2737 double max_abs = 0;
2738 for (j = 0; j < row_length; j++)
2739 max_abs = ccv_max(max_abs, fabs(row[j]))({ typeof (max_abs) _a = (max_abs); typeof (fabs(row[j])) _b =
(fabs(row[j])); (_a > _b) ? _a : _b; })
;
2740 if (max_abs == 0)
2741 {
2742 memset(q, 0, row_length);
2743 return 0;
2744 }
2745 double scale = max_abs / 127.;
2746 double best_scale = 0;
2747 double best_sse = DBL_MAX1.7976931348623157e+308;
2748 int k;
2749 for (k = 0; k < 8; k++)
2750 {
2751 const double stored_scale = scale;
2752 if (!(stored_scale > 0))
2753 break;
2754 const double inv_scale = 1. / stored_scale;
2755 double sum_qx = 0;
2756 double sum_qq = 0;
2757 double sse = 0;
2758 for (j = 0; j < row_length; j++)
2759 {
2760 const double w = _ccv_nnc_8i_rowwise_weight(imatrix, j);
2761 const double v = row[j];
2762 const int qj = _ccv_nnc_8i_rowwise_quantize(v, inv_scale);
2763 const double d = v - stored_scale * qj;
2764 sse += w * d * d;
2765 sum_qx += w * qj * v;
2766 sum_qq += w * qj * qj;
2767 }
2768 if (sse < best_sse)
2769 {
2770 best_sse = sse;
2771 best_scale = stored_scale;
2772 }
2773 if (!(sum_qq > 0) || !(sum_qx > 0))
2774 break;
2775 const double next_scale = sum_qx / sum_qq;
2776 if (next_scale == stored_scale)
2777 break;
2778 scale = next_scale;
2779 }
2780 if (!(best_scale > 0))
2781 {
2782 memset(q, 0, row_length);
2783 return 0;
2784 }
2785 const double inv_scale = 1. / best_scale;
2786 for (j = 0; j < row_length; j++)
2787 q[j] = (int8_t)_ccv_nnc_8i_rowwise_quantize(row[j], inv_scale);
2788 return best_scale;
2789}
2790
2791CCV_WARN_UNUSED(size_t)size_t __attribute__((warn_unused_result)) ccv_nnc_quantize_8i_rowwise(const void* input, const int datatype, const int memory_type, const size_t input_length, const size_t row_length, const float* const imatrix, const size_t imatrix_length, void* output, const size_t output_length)
2792{
2793 assert(datatype == CCV_16F || datatype == CCV_16BF || datatype == CCV_32F || datatype == CCV_64F)((void) sizeof ((datatype == CCV_16F || datatype == CCV_16BF ||
datatype == CCV_32F || datatype == CCV_64F) ? 1 : 0), __extension__
({ if (datatype == CCV_16F || datatype == CCV_16BF || datatype
== CCV_32F || datatype == CCV_64F) ; else __assert_fail ("datatype == CCV_16F || datatype == CCV_16BF || datatype == CCV_32F || datatype == CCV_64F"
, "ccv_nnc_8i_rowwise.c", 2793, __extension__ __PRETTY_FUNCTION__
); }))
;
2794 assert(memory_type == CCV_TENSOR_CPU_MEMORY)((void) sizeof ((memory_type == CCV_TENSOR_CPU_MEMORY) ? 1 : 0
), __extension__ ({ if (memory_type == CCV_TENSOR_CPU_MEMORY)
; else __assert_fail ("memory_type == CCV_TENSOR_CPU_MEMORY"
, "ccv_nnc_8i_rowwise.c", 2794, __extension__ __PRETTY_FUNCTION__
); }))
;
2795 assert(row_length > 0)((void) sizeof ((row_length > 0) ? 1 : 0), __extension__ (
{ if (row_length > 0) ; else __assert_fail ("row_length > 0"
, "ccv_nnc_8i_rowwise.c", 2795, __extension__ __PRETTY_FUNCTION__
); }))
;
2796 assert(input_length % row_length == 0)((void) sizeof ((input_length % row_length == 0) ? 1 : 0), __extension__
({ if (input_length % row_length == 0) ; else __assert_fail (
"input_length % row_length == 0", "ccv_nnc_8i_rowwise.c", 2796
, __extension__ __PRETTY_FUNCTION__); }))
;
2797 const size_t row_count = input_length / row_length;
2798 if (!_ccv_nnc_8i_rowwise_imatrix_is_valid(imatrix, imatrix_length, row_length, row_count))
2799 return 0;
2800 const size_t scale_offset = (input_length + 127) & -128;
2801 const size_t scale_size = row_count * CCV_GET_DATA_TYPE_SIZE(datatype)_ccv_get_data_type_size[((datatype) & 0xFF000) >> 12
]
;
2802 assert(output_length >= scale_offset + scale_size)((void) sizeof ((output_length >= scale_offset + scale_size
) ? 1 : 0), __extension__ ({ if (output_length >= scale_offset
+ scale_size) ; else __assert_fail ("output_length >= scale_offset + scale_size"
, "ccv_nnc_8i_rowwise.c", 2802, __extension__ __PRETTY_FUNCTION__
); }))
;
2803 int8_t* const q = (int8_t*)output;
2804 uint8_t* const u8 = (uint8_t*)output;
2805 if (datatype == CCV_16F)
2806 {
2807 const uint16_t* const f16 = (const uint16_t*)input;
2808 uint16_t* const scales = (uint16_t*)(u8 + scale_offset);
2809 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2810 const size_t row_start = (size_t)i * row_length;
2811 const float* const row_imatrix = _ccv_nnc_8i_rowwise_imatrix_for_row(imatrix, imatrix_length, row_length, row_count, (size_t)i);
2812 const float scale_f = _ccv_nnc_quantize_8i_rowwise_16f(f16 + row_start, row_length, row_imatrix, q + row_start);
2813 ccv_float_to_half_precision(&scale_f, scales + i, 1);
2814 } parallel_endfor} }
2815 } else if (datatype == CCV_16BF) {
2816 const uint16_t* const bf16 = (const uint16_t*)input;
2817 uint16_t* const scales = (uint16_t*)(u8 + scale_offset);
2818 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2819 const size_t row_start = (size_t)i * row_length;
2820 const float* const row_imatrix = _ccv_nnc_8i_rowwise_imatrix_for_row(imatrix, imatrix_length, row_length, row_count, (size_t)i);
2821 const float scale_f = _ccv_nnc_quantize_8i_rowwise_16bf(bf16 + row_start, row_length, row_imatrix, q + row_start);
2822 ccv_float_to_bfloat(&scale_f, scales + i, 1);
2823 } parallel_endfor} }
2824 } else if (datatype == CCV_32F) {
2825 const float* const f32 = (const float*)input;
2826 float* const scales = (float*)(u8 + scale_offset);
2827 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2828 const size_t row_start = (size_t)i * row_length;
2829 const float* const row_imatrix = _ccv_nnc_8i_rowwise_imatrix_for_row(imatrix, imatrix_length, row_length, row_count, (size_t)i);
2830 scales[i] = _ccv_nnc_quantize_8i_rowwise_32f(f32 + row_start, row_length, row_imatrix, q + row_start);
2831 } parallel_endfor} }
2832 } else {
2833 assert(datatype == CCV_64F)((void) sizeof ((datatype == CCV_64F) ? 1 : 0), __extension__
({ if (datatype == CCV_64F) ; else __assert_fail ("datatype == CCV_64F"
, "ccv_nnc_8i_rowwise.c", 2833, __extension__ __PRETTY_FUNCTION__
); }))
;
2834 const double* const f64 = (const double*)input;
2835 double* const scales = (double*)(u8 + scale_offset);
2836 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2837 const size_t row_start = (size_t)i * row_length;
2838 const float* const row_imatrix = _ccv_nnc_8i_rowwise_imatrix_for_row(imatrix, imatrix_length, row_length, row_count, (size_t)i);
2839 scales[i] = _ccv_nnc_quantize_8i_rowwise_64f(f64 + row_start, row_length, row_imatrix, q + row_start);
2840 } parallel_endfor} }
2841 }
2842 return scale_offset + scale_size;
2843}
2844
2845void ccv_nnc_dequantize_8i_rowwise(const void* input, const int datatype, const int memory_type, const size_t input_length, const size_t row_length, void* output, const size_t output_length)
2846{
2847 assert(datatype == CCV_16F || datatype == CCV_16BF || datatype == CCV_32F || datatype == CCV_64F)((void) sizeof ((datatype == CCV_16F || datatype == CCV_16BF ||
datatype == CCV_32F || datatype == CCV_64F) ? 1 : 0), __extension__
({ if (datatype == CCV_16F || datatype == CCV_16BF || datatype
== CCV_32F || datatype == CCV_64F) ; else __assert_fail ("datatype == CCV_16F || datatype == CCV_16BF || datatype == CCV_32F || datatype == CCV_64F"
, "ccv_nnc_8i_rowwise.c", 2847, __extension__ __PRETTY_FUNCTION__
); }))
;
2848 assert(memory_type == CCV_TENSOR_CPU_MEMORY || memory_type == CCV_TENSOR_GPU_MEMORY)((void) sizeof ((memory_type == CCV_TENSOR_CPU_MEMORY || memory_type
== CCV_TENSOR_GPU_MEMORY) ? 1 : 0), __extension__ ({ if (memory_type
== CCV_TENSOR_CPU_MEMORY || memory_type == CCV_TENSOR_GPU_MEMORY
) ; else __assert_fail ("memory_type == CCV_TENSOR_CPU_MEMORY || memory_type == CCV_TENSOR_GPU_MEMORY"
, "ccv_nnc_8i_rowwise.c", 2848, __extension__ __PRETTY_FUNCTION__
); }))
;
2849 assert(row_length > 0)((void) sizeof ((row_length > 0) ? 1 : 0), __extension__ (
{ if (row_length > 0) ; else __assert_fail ("row_length > 0"
, "ccv_nnc_8i_rowwise.c", 2849, __extension__ __PRETTY_FUNCTION__
); }))
;
2850 assert(output_length % row_length == 0)((void) sizeof ((output_length % row_length == 0) ? 1 : 0), __extension__
({ if (output_length % row_length == 0) ; else __assert_fail
("output_length % row_length == 0", "ccv_nnc_8i_rowwise.c", 2850
, __extension__ __PRETTY_FUNCTION__); }))
;
2851 if (memory_type != CCV_TENSOR_CPU_MEMORY)
2852 {
2853#ifdef HAVE_CUDA1
2854 ccv_nnc_compat_dequantize_8i_rowwise(input, datatype, input_length, row_length, output, output_length, 0);
2855#elif defined(HAVE_MPS)
2856 assert(datatype != CCV_64F)((void) sizeof ((datatype != CCV_64F) ? 1 : 0), __extension__
({ if (datatype != CCV_64F) ; else __assert_fail ("datatype != CCV_64F"
, "ccv_nnc_8i_rowwise.c", 2856, __extension__ __PRETTY_FUNCTION__
); }))
;
2857 ccv_nnc_mps_dequantize_8i_rowwise(input, datatype, input_length, row_length, output, output_length, 0);
2858#else
2859 assert(memory_type == CCV_TENSOR_CPU_MEMORY)((void) sizeof ((memory_type == CCV_TENSOR_CPU_MEMORY) ? 1 : 0
), __extension__ ({ if (memory_type == CCV_TENSOR_CPU_MEMORY)
; else __assert_fail ("memory_type == CCV_TENSOR_CPU_MEMORY"
, "ccv_nnc_8i_rowwise.c", 2859, __extension__ __PRETTY_FUNCTION__
); }))
;
2860#endif
2861 return;
2862 }
2863 const size_t row_count = output_length / row_length;
2864 const size_t scale_offset = (output_length + 127) & -128;
2865 assert(input_length >= scale_offset + row_count * CCV_GET_DATA_TYPE_SIZE(datatype))((void) sizeof ((input_length >= scale_offset + row_count *
_ccv_get_data_type_size[((datatype) & 0xFF000) >> 12
]) ? 1 : 0), __extension__ ({ if (input_length >= scale_offset
+ row_count * _ccv_get_data_type_size[((datatype) & 0xFF000
) >> 12]) ; else __assert_fail ("input_length >= scale_offset + row_count * CCV_GET_DATA_TYPE_SIZE(datatype)"
, "ccv_nnc_8i_rowwise.c", 2865, __extension__ __PRETTY_FUNCTION__
); }))
;
2866 const int8_t* const q = (const int8_t*)input;
2867 const uint8_t* const u8 = (const uint8_t*)input;
2868 if (datatype == CCV_16F)
2869 {
2870 uint16_t* const f16 = (uint16_t*)output;
2871 const uint16_t* const scales = (const uint16_t*)(u8 + scale_offset);
2872 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2873 const size_t row_start = (size_t)i * row_length;
2874 float scale_f;
2875 ccv_half_precision_to_float(scales + i, &scale_f, 1);
2876 size_t j;
2877 for (j = 0; j < row_length; j++)
2878 {
2879 const float v = q[row_start + j] * scale_f;
2880 ccv_float_to_half_precision(&v, f16 + row_start + j, 1);
2881 }
2882 } parallel_endfor} }
2883 } else if (datatype == CCV_16BF) {
2884 uint16_t* const bf16 = (uint16_t*)output;
2885 const uint16_t* const scales = (const uint16_t*)(u8 + scale_offset);
2886 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2887 const size_t row_start = (size_t)i * row_length;
2888 float scale_f;
2889 ccv_bfloat_to_float(scales + i, &scale_f, 1);
2890 size_t j;
2891 for (j = 0; j < row_length; j++)
2892 {
2893 const float v = q[row_start + j] * scale_f;
2894 ccv_float_to_bfloat(&v, bf16 + row_start + j, 1);
2895 }
2896 } parallel_endfor} }
2897 } else if (datatype == CCV_32F) {
2898 float* const f32 = (float*)output;
2899 const float* const scales = (const float*)(u8 + scale_offset);
2900 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2901 const size_t row_start = (size_t)i * row_length;
2902 const float scale = scales[i];
2903 size_t j;
2904 for (j = 0; j < row_length; j++)
2905 f32[row_start + j] = q[row_start + j] * scale;
2906 } parallel_endfor} }
2907 } else {
2908 assert(datatype == CCV_64F)((void) sizeof ((datatype == CCV_64F) ? 1 : 0), __extension__
({ if (datatype == CCV_64F) ; else __assert_fail ("datatype == CCV_64F"
, "ccv_nnc_8i_rowwise.c", 2908, __extension__ __PRETTY_FUNCTION__
); }))
;
2909 double* const f64 = (double*)output;
2910 const double* const scales = (const double*)(u8 + scale_offset);
2911 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2912 const size_t row_start = (size_t)i * row_length;
2913 const double scale = scales[i];
2914 size_t j;
2915 for (j = 0; j < row_length; j++)
2916 f64[row_start + j] = q[row_start + j] * scale;
2917 } parallel_endfor} }
2918 }
2919}