Bug Summary

File:nnc/ccv_nnc_8i_rowwise.c
Warning:line 1917, 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-26-140650-29116-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* hessian64; // Double copy of hessian for BLAS products; 0 without BLAS.
1754 double ridge; // Added to the Hessian diagonal to keep it positive definite.
1755 double* u; // Feedback coefficients U[j][k] for lane j and lanes k in later groups.
1756 double* rbb; // Upper-triangular diagonal blocks R_bb of H = R R^T, one group_size^2 block per group.
1757 double* weights; // Conditional variances diag(D_b) = diag(R_bb R_bb^T), 0 for padded lanes.
1758} ccv_nnc_8i_rowwise_x_feedback_t;
1759
1760// a[i][j] -= sum_{m in [k0, k1)} a[i][m] a[j][m] for i <= j < k0.
1761static void _ccv_nnc_8i_rowwise_x_rank_update(double* const a, const size_t n, const size_t k0, const size_t k1)
1762{
1763#if (defined HAVE_CBLAS1 || defined HAVE_ACCELERATE_FRAMEWORK)
1764 cblas_dsyrk(CblasRowMajor, CblasUpper, CblasNoTrans, (int)k0, (int)(k1 - k0), -1, a + k0, (int)n, 1, a, (int)n);
1765#else
1766 const size_t w = k1 - k0;
1767 double* const panel = (double*)ccmallocmalloc(sizeof(double) * k0 * w);
1768 size_t i;
1769 for (i = 0; i < k0; i++)
1770 memcpy(panel + i * w, a + i * n + k0, sizeof(double) * w);
1771 const size_t blocks = (k0 + 15) / 16;
1772#ifdef USE_DISPATCH
1773 dispatch_apply(blocks, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t block_idx) {
1774#else
1775 parallel_for(block_idx, (int)blocks){ int block_idx; for ((block_idx) = 0; (block_idx) < ((int
)blocks); (block_idx)++) {
{
1776#endif
1777 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; }
)
;
1778 size_t r, j, m;
1779 for (r = (size_t)block_idx * 16; r < row_end; r++)
1780 {
1781 const double* const pr = panel + r * w;
1782 for (j = r; j < k0; j++)
1783 {
1784 const double* const pj = panel + j * w;
1785 double v = 0;
1786 for (m = 0; m < w; m++)
1787 v += pr[m] * pj[m];
1788 a[r * n + j] -= v;
1789 }
1790 }
1791#ifdef USE_DISPATCH
1792 });
1793#else
1794 } parallel_endfor} }
1795#endif
1796 ccfreefree(panel);
1797#endif
1798}
1799
1800// Factor H = R R^T with R upper triangular, in place on the upper triangle of a, starting from the
1801// last column so that column k only depends on lanes at or after k. Columns go in panels: factor the
1802// panel's diagonal block, solve each row above it on its contiguous panel segment, then one rank-k
1803// update of the leading block.
1804static int _ccv_nnc_8i_rowwise_x_reverse_cholesky(double* const a, const size_t n)
1805{
1806 size_t k1 = n;
1807 while (k1
51.1
'k1' is > 0
> 0)
62
Loop condition is false. Execution continues on line 1860
1808 {
1809 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
1810 size_t k = k1;
1811 while (k-- > k0)
54
Loop condition is true. Entering loop body
59
Loop condition is false. Execution continues on line 1829
1812 {
1813 const double d = a[k * n + k];
1814 if (!(d > 0))
55
Assuming 'd' is > 0
56
Taking false branch
1815 return 0;
1816 const double rkk = sqrt(d);
1817 a[k * n + k] = rkk;
1818 size_t i, j;
1819 for (i = k0; i < k; i++)
57
Loop condition is false. Execution continues on line 1821
1820 a[i * n + k] /= rkk;
1821 for (i = k0; i < k; i++)
58
Loop condition is false. Execution continues on line 1811
1822 {
1823 const double ci = a[i * n + k];
1824 for (j = i; j < k; j++)
1825 a[i * n + j] -= ci * a[j * n + k];
1826 }
1827 }
1828 // 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.
1829 const size_t blocks = (k0 + 63) / 64;
1830#ifdef USE_DISPATCH
1831 dispatch_apply(blocks, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t block_idx) {
1832#else
1833 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 1856
1834#endif
1835 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; }
)
;
1836 size_t r;
1837 for (r = (size_t)block_idx * 64; r < row_end; r++)
1838 {
1839 double* const ar = a + r * n;
1840 size_t m = k1;
1841 while (m-- > k0)
1842 {
1843 const double* const am = a + m * n;
1844 double v = ar[m];
1845 size_t p;
1846 for (p = m + 1; p < k1; p++)
1847 v -= ar[p] * am[p];
1848 ar[m] = v / am[m];
1849 }
1850 }
1851#ifdef USE_DISPATCH
1852 });
1853#else
1854 } parallel_endfor} }
1855#endif
1856 if (k0
60.1
'k0' is <= 0
> 0)
61
Taking false branch
1857 _ccv_nnc_8i_rowwise_x_rank_update(a, n, k0, k1);
1858 k1 = k0;
1859 }
1860 return 1;
1861}
1862
1863// Block UDU^T of H = hessian + ridge I over quantization groups, U unit upper block-triangular. Walking
1864// 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,
1865// 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
1866// against D_b (the input variance conditioned on later groups) instead of the imatrix diagonal.
1867static 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)
1868{
1869 double* const u = feedback->u;
1870 const size_t n = padded_row_length;
1871 size_t i, j;
1872 double mean_diag = 0;
1873 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 1875
1874 mean_diag += hessian[i * row_length + i];
1875 mean_diag /= (double)row_length;
1876 if (!(mean_diag > 0))
40
Assuming 'mean_diag' is > 0
41
Taking false branch
1877 mean_diag = 1;
1878 double ridge = mean_diag * 1e-6;
1879 int factored = 0;
1880 int attempt;
1881 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
1882 {
1883 if (attempt
42.1
'attempt' is <= 0
> 0)
43
Taking false branch
1884 ridge *= 10;
1885 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 1891
1886 {
1887 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 1889
1888 u[i * n + j] = (j
45.2
'j' is < 'row_length'
< row_length) ? hessian[i * row_length + j] : 0;
46
'?' condition is true
1889 u[i * n + i] += i
48.1
'i' is < 'row_length'
< row_length ? ridge : mean_diag;
49
'?' condition is true
1890 }
1891 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'
1892 }
1893 if (!factored
63.2
'factored' is 1
)
64
Taking false branch
1894 {
1895 // Not positive definite even with a large ridge (non-finite input): drop the feedback.
1896 memset(u, 0, sizeof(double) * n * n);
1897 for (i = 0; i < n; i++)
1898 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);
1899 }
1900 feedback->hessian = hessian;
1901 feedback->ridge = ridge;
1902 if (feedback->hessian64)
65
Assuming field 'hessian64' is null
66
Taking false branch
1903 for (i = 0; i < row_length * row_length; i++)
1904 feedback->hessian64[i] = hessian[i];
1905 const size_t groups = n / group_size;
1906 size_t g;
1907 for (g = 0; g < groups; g++)
67
Assuming 'g' is < 'groups'
68
Loop condition is true. Entering loop body
1908 {
1909 const size_t s = g * group_size;
1910 double* const rbb = feedback->rbb + g * group_size * group_size;
1911 size_t m, l;
1912 for (m = 0; m < group_size; m++)
69
Assuming 'm' is < 'group_size'
70
Loop condition is true. Entering loop body
1913 {
1914 double d = 0;
1915 for (l = 0; l
70.1
'l' is < 'group_size'
< group_size
; l++)
73
Assuming 'l' is < 'group_size'
1916 {
1917 const double v = l
71.1
'l' is >= 'm'
74.1
'l' is >= 'm'
>= m ? u[(s + m) * n + s + l] : 0
;
71
Loop condition is true. Entering loop body
72
'?' condition is true
74
Loop condition is true. Entering loop body
75
'?' condition is true
76
Assigned value is garbage or undefined
1918 rbb[m * group_size + l] = v;
1919 d += v * v;
1920 }
1921 feedback->weights[s + m] = s + m < row_length ? d : 0;
1922 }
1923 if (s == 0)
1924 continue;
1925 double inv_data[32 * 32] = {0};
1926 double* const inv = inv_data;
1927 for (l = 0; l < group_size; l++)
1928 {
1929 inv[l * group_size + l] = 1. / rbb[l * group_size + l];
1930 m = l;
1931 while (m-- > 0)
1932 {
1933 double v = 0;
1934 size_t t;
1935 for (t = m + 1; t <= l; t++)
1936 v += rbb[m * group_size + t] * inv[t * group_size + l];
1937 inv[m * group_size + l] = -v / rbb[m * group_size + m];
1938 }
1939 }
1940 // U[j][group g] = R[j][group g] R_gg^-1 for every lane j in earlier groups.
1941 const size_t blocks = (s + 63) / 64;
1942#ifdef USE_DISPATCH
1943 dispatch_apply(blocks, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t block_idx) {
1944#else
1945 parallel_for(block_idx, (int)blocks){ int block_idx; for ((block_idx) = 0; (block_idx) < ((int
)blocks); (block_idx)++) {
{
1946#endif
1947 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; })
;
1948 size_t r, a, b;
1949 for (r = (size_t)block_idx * 64; r < row_end; r++)
1950 {
1951 double* const ur = u + r * n + s;
1952 double t[32];
1953 for (b = 0; b < group_size; b++)
1954 {
1955 double v = 0;
1956 for (a = 0; a <= b; a++)
1957 v += ur[a] * inv[a * group_size + b];
1958 t[b] = v;
1959 }
1960 memcpy(ur, t, sizeof(double) * group_size);
1961 }
1962#ifdef USE_DISPATCH
1963 });
1964#else
1965 } parallel_endfor} }
1966#endif
1967 }
1968}
1969
1970typedef struct {
1971 const void* input;
1972 int datatype;
1973 int format;
1974 int codec;
1975 int starts;
1976 size_t row_length;
1977 size_t row_count;
1978 const float* imatrix;
1979 size_t imatrix_length;
1980 size_t group_size;
1981 size_t groups_per_row;
1982 size_t padded_row_length;
1983 const int16_t* iq1_map;
1984 uint8_t* u8;
1985 uint8_t* scales;
1986} ccv_nnc_8i_rowwise_x_rows_t;
1987
1988static double _ccv_nnc_8i_rowwise_x_start_scale(const double max_abs, const int start, const int starts, const int datatype)
1989{
1990 double scale = max_abs / 127.;
1991 if (starts == 3)
1992 {
1993 scale *= start == 0 ? 0.75 : start == 1 ? 1. : 1.25;
1994 if (datatype == CCV_16F && max_abs > 0 && _ccv_nnc_8i_rowwise_packed_stored_scale(scale, datatype) == 0)
1995 scale = 0x1p-24;
1996 }
1997 return scale;
1998}
1999
2000static 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)
2001{
2002 const size_t group_size = ctx->group_size;
2003 _ccv_nnc_8i_rowwise_packed_store_scale(ctx->scales, ctx->datatype, i, best_scale);
2004 size_t g, j;
2005 if (has_best)
2006 {
2007 for (g = 0; g < ctx->groups_per_row; g++)
2008 _ccv_nnc_8i_rowwise_packed_pack_group(ctx->u8, i * ctx->groups_per_row + g, ctx->codec, best_groups + g);
2009 } else {
2010 for (g = 0; g < ctx->groups_per_row; g++)
2011 {
2012 double y[32] = {0};
2013 double w[32] = {0};
2014 for (j = 0; j < group_size; j++)
2015 {
2016 y[j] = row[g * group_size + j];
2017 w[j] = weights[g * group_size + j];
2018 }
2019 ccv_nnc_8i_rowwise_packed_group_t group;
2020 _ccv_nnc_8i_rowwise_packed_quant_group(ctx->codec, y, w, ctx->iq1_map, &group);
2021 _ccv_nnc_8i_rowwise_packed_pack_group(ctx->u8, i * ctx->groups_per_row + g, ctx->codec, &group);
2022 }
2023 }
2024}
2025
2026static 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)
2027{
2028 const size_t row_length = ctx->row_length;
2029 const size_t padded_row_length = ctx->padded_row_length;
2030 const size_t group_size = ctx->group_size;
2031 const size_t groups_per_row = ctx->groups_per_row;
2032 const int datatype = ctx->datatype;
2033 double* const row = (double*)ccmallocmalloc(sizeof(double) * padded_row_length);
2034 double* const weights = (double*)ccmallocmalloc(sizeof(double) * padded_row_length);
2035 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);
2036 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);
2037 size_t i;
2038 for (i = row_begin; i < row_end; i++)
2039 {
2040 const size_t row_start = i * row_length;
2041 const float* const row_imatrix = _ccv_nnc_8i_rowwise_imatrix_for_row(ctx->imatrix, ctx->imatrix_length, row_length, ctx->row_count, i);
2042 _ccv_nnc_8i_rowwise_packed_read_row(ctx->input, datatype, row_start, row_length, padded_row_length, row);
2043 if (ctx->format & CCV_NNC_QX_8I_ROWWISE_HADAMARD_256)
2044 _ccv_nnc_8i_rowwise_hadamard_256(row, row_length);
2045 double max_abs = 0;
2046 size_t j;
2047 for (j = 0; j < row_length; j++)
2048 {
2049 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; })
;
2050 weights[j] = _ccv_nnc_8i_rowwise_weight(row_imatrix, j);
2051 }
2052 for (; j < padded_row_length; j++)
2053 weights[j] = 0;
2054 double best_scale = 0;
2055 double best_sse = DBL_MAX1.7976931348623157e+308;
2056 int has_best = 0;
2057 int start;
2058 for (start = 0; start < ctx->starts; start++)
2059 {
2060 double scale = _ccv_nnc_8i_rowwise_x_start_scale(max_abs, start, ctx->starts, datatype);
2061 int k;
2062 for (k = 0; k < CCV_NNC_8I_ROWWISE_X_REFINEMENT_STEPS; k++)
2063 {
2064 const double stored_scale = _ccv_nnc_8i_rowwise_packed_stored_scale(scale, datatype);
2065 if (!(stored_scale > 0))
2066 break;
2067 double sse = 0;
2068 double sum_qx = 0;
2069 double sum_qq = 0;
2070 size_t g;
2071 for (g = 0; g < groups_per_row; g++)
2072 {
2073 double y[32] = {0};
2074 double w[32] = {0};
2075 for (j = 0; j < group_size; j++)
2076 {
2077 y[j] = row[g * group_size + j] / stored_scale;
2078 w[j] = weights[g * group_size + j];
2079 }
2080 ccv_nnc_8i_rowwise_packed_group_t group;
2081 _ccv_nnc_8i_rowwise_packed_quant_group(ctx->codec, y, w, ctx->iq1_map, &group);
2082 groups[g] = group;
2083 const size_t group_start = g * group_size;
2084 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; })
;
2085 for (j = group_start; j < group_end; j++)
2086 {
2087 const int q8 = group.q8[j - group_start];
2088 const double d = row[j] - stored_scale * q8;
2089 sse += weights[j] * d * d;
2090 sum_qx += weights[j] * q8 * row[j];
2091 sum_qq += weights[j] * q8 * q8;
2092 }
2093 }
2094 if (sse < best_sse)
2095 {
2096 best_sse = sse;
2097 best_scale = stored_scale;
2098 has_best = 1;
2099 memcpy(best_groups, groups, sizeof(ccv_nnc_8i_rowwise_packed_group_t) * groups_per_row);
2100 }
2101 if (!(sum_qq > 0) || !(sum_qx > 0))
2102 break;
2103 const double next_scale = sum_qx / sum_qq;
2104 if (_ccv_nnc_8i_rowwise_packed_stored_scale(next_scale, datatype) == stored_scale)
2105 break;
2106 scale = next_scale;
2107 }
2108 }
2109 _ccv_nnc_8i_rowwise_x_pack_row(ctx, i, row, weights, has_best, best_scale, best_groups);
2110 }
2111 ccfreefree(best_groups);
2112 ccfreefree(groups);
2113 ccfreefree(weights);
2114 ccfreefree(row);
2115}
2116
2117// The same refinement as the imatrix path, with each pass adding group errors into later targets. Rows of a
2118// chunk run their passes in lockstep so every pass reads the feedback matrix once per chunk, not per row.
2119static 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)
2120{
2121 enum { R = CCV_NNC_8I_ROWWISE_X_FEEDBACK_ROWS };
2122 const size_t rows = row_end - row_begin;
2123 assert(rows <= R)((void) sizeof ((rows <= R) ? 1 : 0), __extension__ ({ if (
rows <= R) ; else __assert_fail ("rows <= R", "ccv_nnc_8i_rowwise.c"
, 2123, __extension__ __PRETTY_FUNCTION__); }))
;
2124 const size_t row_length = ctx->row_length;
2125 const size_t n = ctx->padded_row_length;
2126 const size_t group_size = ctx->group_size;
2127 const size_t groups_per_row = ctx->groups_per_row;
2128 double* const x = (double*)ccmallocmalloc(sizeof(double) * rows * n);
2129 double* const target = (double*)ccmallocmalloc(sizeof(double) * n * R); // Lane-major: target[l * R + r].
2130 double* const hx = (double*)ccmallocmalloc(sizeof(double) * rows * row_length);
2131 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);
2132 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);
2133 double max_abs[R], xhx[R], scale[R], stored_scale[R], sse[R], sum_qx[R], best_sse[R], best_scale[R];
2134 int has_best[R], start[R], step[R], ready[R], done[R];
2135 double e[32][R];
2136 size_t r, j, l;
2137 for (r = 0; r < rows; r++)
2138 {
2139 double* const xr = x + r * n;
2140 _ccv_nnc_8i_rowwise_packed_read_row(ctx->input, ctx->datatype, (row_begin + r) * row_length, row_length, n, xr);
2141 max_abs[r] = 0;
2142 for (j = 0; j < row_length; j++)
2143 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; })
;
2144 xhx[r] = 0;
2145 best_sse[r] = DBL_MAX1.7976931348623157e+308;
2146 best_scale[r] = 0;
2147 has_best[r] = 0;
2148 start[r] = 0;
2149 step[r] = 0;
2150 done[r] = 0;
2151 scale[r] = _ccv_nnc_8i_rowwise_x_start_scale(max_abs[r], 0, ctx->starts, ctx->datatype);
2152 }
2153 // hx = (hessian + ridge I) x, reading each Hessian row once for the chunk.
2154#if (defined HAVE_CBLAS1 || defined HAVE_ACCELERATE_FRAMEWORK)
2155 // hx[r][j] = sum_l hessian[j][l] x[r][l] for the whole chunk in one product.
2156 cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, (int)rows, (int)row_length, (int)row_length, 1, x, (int)n, fb->hessian64, (int)row_length, 0, hx, (int)row_length);
2157 for (r = 0; r < rows; r++)
2158 {
2159 const double* const xr = x + r * n;
2160 for (j = 0; j < row_length; j++)
2161 {
2162 const double v = hx[r * row_length + j] + fb->ridge * xr[j];
2163 hx[r * row_length + j] = v;
2164 xhx[r] += xr[j] * v;
2165 }
2166 }
2167#else
2168 for (j = 0; j < row_length; j++)
2169 {
2170 const float* const cj = fb->hessian + j * row_length;
2171 for (r = 0; r < rows; r++)
2172 {
2173 const double* const xr = x + r * n;
2174 double v = fb->ridge * xr[j];
2175 for (l = 0; l < row_length; l++)
2176 v += cj[l] * xr[l];
2177 hx[r * row_length + j] = v;
2178 xhx[r] += xr[j] * v;
2179 }
2180 }
2181#endif
2182 for (;;)
2183 {
2184 int any = 0;
2185 for (r = 0; r < rows; r++)
2186 {
2187 ready[r] = 0;
2188 while (!done[r])
2189 {
2190 stored_scale[r] = _ccv_nnc_8i_rowwise_packed_stored_scale(scale[r], ctx->datatype);
2191 if (stored_scale[r] > 0)
2192 {
2193 ready[r] = 1;
2194 any = 1;
2195 break;
2196 }
2197 if (++start[r] >= ctx->starts)
2198 done[r] = 1;
2199 else {
2200 step[r] = 0;
2201 scale[r] = _ccv_nnc_8i_rowwise_x_start_scale(max_abs[r], start[r], ctx->starts, ctx->datatype);
2202 }
2203 }
2204 sse[r] = 0;
2205 sum_qx[r] = 0;
2206 }
2207 if (!any)
2208 break;
2209 for (l = 0; l < n; l++)
2210 for (r = 0; r < R; r++)
2211 target[l * R + r] = (r < rows && ready[r]) ? x[r * n + l] : 0;
2212 size_t g;
2213 for (g = 0; g < groups_per_row; g++)
2214 {
2215 const size_t group_start = g * group_size;
2216 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; })
;
2217 const size_t next_group = group_start + group_size;
2218 memset(e, 0, sizeof(e));
2219 for (r = 0; r < rows; r++)
2220 {
2221 if (!ready[r])
2222 continue;
2223 double y[32] = {0};
2224 double w[32] = {0};
2225 for (j = 0; j < group_size; j++)
2226 {
2227 y[j] = target[(group_start + j) * R + r] / stored_scale[r];
2228 w[j] = fb->weights[group_start + j];
2229 }
2230 ccv_nnc_8i_rowwise_packed_group_t* const group = groups + r * groups_per_row + g;
2231 _ccv_nnc_8i_rowwise_packed_quant_group(ctx->codec, y, w, ctx->iq1_map, group);
2232 double res[32] = {0};
2233 for (j = group_start; j < group_end; j++)
2234 {
2235 const int q8 = group->q8[j - group_start];
2236 res[j - group_start] = target[j * R + r] - stored_scale[r] * q8;
2237 e[j - group_start][r] = x[r * n + j] - stored_scale[r] * q8;
2238 sum_qx[r] += q8 * hx[r * row_length + j];
2239 }
2240 // r_b D_b r_b^T = |r_b R_bb|^2.
2241 const double* const rbb = fb->rbb + g * group_size * group_size;
2242 size_t m;
2243 for (l = 0; l < group_size; l++)
2244 {
2245 double v = 0;
2246 for (m = 0; m <= l; m++)
2247 v += res[m] * rbb[m * group_size + l];
2248 sse[r] += v * v;
2249 }
2250 }
2251#if (defined HAVE_CBLAS1 || defined HAVE_ACCELERATE_FRAMEWORK)
2252 // target[l][r] += sum_j U[group_start + j][l] e[j][r] for every later lane l, as one product.
2253 if (next_group < n)
2254 cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans, (int)(n - next_group), R, (int)(group_end - group_start), 1, fb->u + group_start * n + next_group, (int)n, &e[0][0], R, 1, target + next_group * R, R);
2255#else
2256 // Later lanes in tiles that stay in cache across this group's feedback rows.
2257 size_t l0;
2258 for (l0 = next_group; l0 < n; l0 += 64)
2259 {
2260 const size_t l1 = ccv_min(l0 + 64, n)({ typeof (l0 + 64) _a = (l0 + 64); typeof (n) _b = (n); (_a <
_b) ? _a : _b; })
;
2261 for (j = 0; j < group_end - group_start; j++)
2262 {
2263 const double* const uj = fb->u + (group_start + j) * n;
2264 const double* const ej = e[j];
2265 for (l = l0; l < l1; l++)
2266 {
2267 const double u = uj[l];
2268 double* const t = target + l * R;
2269 for (r = 0; r < R; r++)
2270 t[r] += ej[r] * u;
2271 }
2272 }
2273 }
2274#endif
2275 }
2276 for (r = 0; r < rows; r++)
2277 {
2278 if (!ready[r])
2279 continue;
2280 // sse = e H e^T = x H x - 2 s q H x + s^2 q H q.
2281 const double s = stored_scale[r];
2282 const double sum_qq = (sse[r] - xhx[r] + 2 * s * sum_qx[r]) / (s * s);
2283 if (sse[r] < best_sse[r])
2284 {
2285 best_sse[r] = sse[r];
2286 best_scale[r] = s;
2287 has_best[r] = 1;
2288 memcpy(best_groups + r * groups_per_row, groups + r * groups_per_row, sizeof(ccv_nnc_8i_rowwise_packed_group_t) * groups_per_row);
2289 }
2290 int next_start = 1;
2291 if (sum_qq > 0 && sum_qx[r] > 0)
2292 {
2293 const double next_scale = sum_qx[r] / sum_qq;
2294 if (_ccv_nnc_8i_rowwise_packed_stored_scale(next_scale, ctx->datatype) != s && ++step[r] < CCV_NNC_8I_ROWWISE_X_REFINEMENT_STEPS)
2295 {
2296 scale[r] = next_scale;
2297 next_start = 0;
2298 }
2299 }
2300 if (next_start)
2301 {
2302 step[r] = 0;
2303 if (++start[r] >= ctx->starts)
2304 done[r] = 1;
2305 else
2306 scale[r] = _ccv_nnc_8i_rowwise_x_start_scale(max_abs[r], start[r], ctx->starts, ctx->datatype);
2307 }
2308 }
2309 }
2310 for (r = 0; r < rows; r++)
2311 _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);
2312 ccfreefree(best_groups);
2313 ccfreefree(groups);
2314 ccfreefree(hx);
2315 ccfreefree(target);
2316 ccfreefree(x);
2317}
2318
2319static 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)
2320{
2321 const int codec = format & CCV_NNC_QX_8I_ROWWISE_FORMAT_MASK;
2322 const size_t row_count = input_length / row_length;
2323 const size_t group_size = ccv_nnc_8i_rowwise_x_group_size(format);
2324 const int group_bits = ccv_nnc_8i_rowwise_x_group_bits(format);
2325 const size_t groups_per_row = (row_length + group_size - 1) / group_size;
2326 const size_t padded_row_length = groups_per_row * group_size;
2327 const size_t scale_offset = _ccv_nnc_8i_rowwise_packed_scale_offset(format, input_length, row_length);
2328 const size_t output_size = scale_offset + row_count * CCV_GET_DATA_TYPE_SIZE(datatype)_ccv_get_data_type_size[((datatype) & 0xFF000) >> 12
]
;
2329 if (output_length < output_size)
20
Assuming 'output_length' is >= 'output_size'
21
Taking false branch
2330 return 0;
2331 int16_t* iq1_map = 0;
2332 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
2333 if (starts
24.1
'starts' is not equal to 3
== 3)
25
Taking false branch
2334 {
2335 iq1_map = (int16_t*)ccmallocmalloc(sizeof(int16_t) * 6561);
2336 int i, j;
2337 for (i = 0; i < 6561; i++)
2338 iq1_map[i] = -1;
2339 for (i = 0; i < 2048; i++)
2340 {
2341 int code = 0;
2342 for (j = 0; j < 8; j++)
2343 code += ((ccv_nnc_8i_rowwise_packed_iq1_grid[i] >> (2 * j)) & 3) * ccv_nnc_8i_rowwise_packed_iq1_powers[j];
2344 iq1_map[code] = (int16_t)i;
2345 }
2346 }
2347 switch (codec)
26
'Default' branch taken. Execution continues on line 2365
2348 {
2349 case CCV_NNC_QX_8I_ROWWISE_IQ2_XXS:
2350 _ccv_nnc_8i_rowwise_packed_iq2xxs_candidates_init();
2351 break;
2352 case CCV_NNC_QX_8I_ROWWISE_IQ2_XS:
2353 _ccv_nnc_8i_rowwise_packed_iq2xs_candidates_init();
2354 break;
2355 case CCV_NNC_QX_8I_ROWWISE_IQ2_S:
2356 _ccv_nnc_8i_rowwise_packed_iq2s_init();
2357 break;
2358 case CCV_NNC_QX_8I_ROWWISE_IQ3_S:
2359 _ccv_nnc_8i_rowwise_packed_iq3s_init();
2360 break;
2361 case CCV_NNC_QX_8I_ROWWISE_IQ3_XXS:
2362 _ccv_nnc_8i_rowwise_packed_iq3xxs_candidates_init();
2363 break;
2364 }
2365 uint8_t* const u8 = (uint8_t*)output;
2366 uint8_t* const scales = u8 + scale_offset;
2367 memset(u8, 0, scale_offset);
2368 const size_t row_bits = groups_per_row * group_bits;
2369 size_t rows_per_chunk;
2370 switch (row_bits & 7)
27
Control jumps to the 'default' case at line 2382
2371 {
2372 case 0:
2373 rows_per_chunk = 1;
2374 break;
2375 case 4:
2376 rows_per_chunk = 2;
2377 break;
2378 case 2:
2379 case 6:
2380 rows_per_chunk = 4;
2381 break;
2382 default:
2383 rows_per_chunk = 8;
2384 break;
28
Execution continues on line 2386
2385 }
2386 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
2387 // Feedback chunks are a multiple of the packing chunk, so they stay byte aligned.
2388 if (hessian
29.1
'hessian' is non-null
)
30
Taking true branch
2389 rows_per_chunk = CCV_NNC_8I_ROWWISE_X_FEEDBACK_ROWS;
2390 const ccv_nnc_8i_rowwise_x_rows_t rows_data = {
2391 .input = input,
2392 .datatype = datatype,
2393 .format = format,
2394 .codec = codec,
2395 .starts = starts,
2396 .row_length = row_length,
2397 .row_count = row_count,
2398 .imatrix = imatrix,
2399 .imatrix_length = imatrix_length,
2400 .group_size = group_size,
2401 .groups_per_row = groups_per_row,
2402 .padded_row_length = padded_row_length,
2403 .iq1_map = iq1_map,
2404 .u8 = u8,
2405 .scales = scales,
2406 };
2407 const ccv_nnc_8i_rowwise_x_rows_t* const ctx = &rows_data;
2408 // Each Hessian slice is factored once and shared by its rows. Slices run one after another, so a
2409 // chunk that straddles two slices never writes its packed bytes concurrently.
2410 const size_t slices = hessian
30.1
'hessian' is non-null
? hessian_length / (row_length * row_length) : 1;
31
'?' condition is true
2411 const size_t rows_per_slice = row_count / slices;
2412 ccv_nnc_8i_rowwise_x_feedback_t feedback = {0};
2413 if (hessian
31.1
'hessian' is non-null
)
32
Taking true branch
2414 {
2415 feedback.u = (double*)ccmallocmalloc(sizeof(double) * padded_row_length * padded_row_length);
33
Storing uninitialized value
2416 feedback.rbb = (double*)ccmallocmalloc(sizeof(double) * padded_row_length * group_size);
2417 feedback.weights = (double*)ccmallocmalloc(sizeof(double) * padded_row_length);
2418#if (defined HAVE_CBLAS1 || defined HAVE_ACCELERATE_FRAMEWORK)
2419 feedback.hessian64 = (double*)ccmallocmalloc(sizeof(double) * row_length * row_length);
2420#endif
2421 }
2422 size_t slice;
2423 for (slice = 0; slice
33.1
'slice' is < 'slices'
< slices; slice++)
34
Loop condition is true. Entering loop body
2424 {
2425 const size_t row_begin = slice * rows_per_slice;
2426 const size_t row_end = row_begin + rows_per_slice;
2427 if (hessian
34.1
'hessian' is non-null
)
35
Taking true branch
2428 _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'
2429 const ccv_nnc_8i_rowwise_x_feedback_t* const fb = hessian ? &feedback : 0;
2430 const size_t first_chunk = row_begin / rows_per_chunk;
2431 const size_t row_chunks = (row_end + rows_per_chunk - 1) / rows_per_chunk - first_chunk;
2432#ifdef USE_DISPATCH
2433 dispatch_apply(row_chunks, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t chunk_idx) {
2434#else
2435 parallel_for(chunk_idx, (int)row_chunks){ int chunk_idx; for ((chunk_idx) = 0; (chunk_idx) < ((int
)row_chunks); (chunk_idx)++) {
{
2436#endif
2437 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; })
;
2438 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; }
)
;
2439 if (fb)
2440 _ccv_nnc_8i_rowwise_x_quantize_rows_feedback(ctx, fb, chunk_begin, chunk_end);
2441 else
2442 _ccv_nnc_8i_rowwise_x_quantize_rows(ctx, chunk_begin, chunk_end);
2443#ifdef USE_DISPATCH
2444 });
2445#else
2446 } parallel_endfor} }
2447#endif
2448 }
2449 if (hessian)
2450 {
2451 ccfreefree(feedback.weights);
2452 ccfreefree(feedback.rbb);
2453 ccfreefree(feedback.u);
2454 if (feedback.hessian64)
2455 ccfreefree(feedback.hessian64);
2456 }
2457 ccfreefree(iq1_map);
2458 return output_size;
2459}
2460
2461CCV_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)
2462{
2463 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
2464 ((format & CCV_NNC_QX_8I_ROWWISE_HADAMARD_256) && (row_length % 256 != 0 || hessian)))
4
Assuming the condition is false
2465 return 0;
2466 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", 2466, __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
2467 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", 2467, __extension__ __PRETTY_FUNCTION__
); }))
;
10
Assuming 'memory_type' is equal to CCV_TENSOR_CPU_MEMORY
11
Taking true branch
2468 const size_t row_count = input_length / row_length;
2469 if (!_ccv_nnc_8i_rowwise_imatrix_is_valid(imatrix, imatrix_length, row_length, row_count))
12
Taking false branch
2470 return 0;
2471 if (hessian)
13
Assuming 'hessian' is non-null
14
Taking true branch
2472 {
2473 const size_t matrix_length = row_length * row_length;
2474 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
2475 return 0;
2476 }
2477 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'
2478}
2479
2480void 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)
2481{
2482 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", 2482, __extension__ __PRETTY_FUNCTION__
); }))
;
2483 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", 2483, __extension__ __PRETTY_FUNCTION__
); }))
;
2484 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", 2484, __extension__ __PRETTY_FUNCTION__
); }))
;
2485 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", 2485
, __extension__ __PRETTY_FUNCTION__); }))
;
2486 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", 2486, __extension__ __PRETTY_FUNCTION__
); }))
;
2487 if (memory_type != CCV_TENSOR_CPU_MEMORY)
2488 {
2489#ifdef HAVE_CUDA1
2490 ccv_nnc_compat_dequantize_8i_rowwise_x_fp(input, datatype, input_length, row_length, format, output, output_length, 0);
2491#elif defined(HAVE_MPS)
2492 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", 2492, __extension__ __PRETTY_FUNCTION__
); }))
;
2493 ccv_nnc_mps_dequantize_8i_rowwise_x(input, datatype, input_length, row_length, format, output, output_length, 0);
2494#else
2495 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", 2495, __extension__ __PRETTY_FUNCTION__
); }))
;
2496#endif
2497 return;
2498 }
2499 const size_t row_count = output_length / row_length;
2500 const size_t group_size = ccv_nnc_8i_rowwise_x_group_size(format);
2501 const size_t groups_per_row = (row_length + group_size - 1) / group_size;
2502 const size_t scale_offset = _ccv_nnc_8i_rowwise_packed_scale_offset(format, output_length, row_length);
2503 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", 2503, __extension__ __PRETTY_FUNCTION__
); }))
;
2504 const uint8_t* const u8 = (const uint8_t*)input;
2505 const uint8_t* const scales = u8 + scale_offset;
2506 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2507 const double scale = _ccv_nnc_8i_rowwise_packed_load_scale(scales, datatype, i);
2508 if (format & CCV_NNC_QX_8I_ROWWISE_HADAMARD_256)
2509 {
2510 // Transform decoded integers before scaling / rounding to the destination
2511 // precision. H256 is its own inverse and acts on independent blocks.
2512 double block[256];
2513 size_t base;
2514 for (base = 0; base < row_length; base += 256)
2515 {
2516 size_t g;
2517 for (g = 0; g < 256 / group_size; g++)
2518 {
2519 int q8[32] = {0};
2520 _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);
2521 size_t j;
2522 for (j = 0; j < group_size; j++)
2523 block[g * group_size + j] = q8[j];
2524 }
2525 _ccv_nnc_8i_rowwise_hadamard_256(block, 256);
2526 size_t j;
2527 for (j = 0; j < 256; j++)
2528 _ccv_nnc_8i_rowwise_packed_write_value(output, datatype, (size_t)i * row_length + base + j, scale * block[j]);
2529 }
2530 } else {
2531 size_t g;
2532 for (g = 0; g < groups_per_row; g++)
2533 {
2534 int q8[32] = {0};
2535 _ccv_nnc_8i_rowwise_packed_decode_group(u8, (size_t)i * groups_per_row + g, format, q8);
2536 size_t j;
2537 for (j = 0; j < group_size; j++)
2538 {
2539 const size_t col = g * group_size + j;
2540 if (col < row_length)
2541 _ccv_nnc_8i_rowwise_packed_write_value(output, datatype, (size_t)i * row_length + col, scale * q8[j]);
2542 }
2543 }
2544 }
2545 } parallel_endfor} }
2546}
2547
2548static inline int _ccv_nnc_8i_rowwise_quantize(const double v, const double inv_scale)
2549{
2550 const int q = (int)lrint(v * inv_scale);
2551 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); }
)
;
2552}
2553
2554static 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)
2555{
2556 size_t j;
2557 double max_abs = 0;
2558 for (j = 0; j < row_length; j++)
2559 {
2560 float v;
2561 ccv_half_precision_to_float(row + j, &v, 1);
2562 max_abs = ccv_max(max_abs, fabs(v))({ typeof (max_abs) _a = (max_abs); typeof (fabs(v)) _b = (fabs
(v)); (_a > _b) ? _a : _b; })
;
2563 }
2564 if (max_abs == 0)
2565 {
2566 memset(q, 0, row_length);
2567 return 0;
2568 }
2569 double scale = max_abs / 127.;
2570 float best_scale = 0;
2571 double best_sse = DBL_MAX1.7976931348623157e+308;
2572 int k;
2573 for (k = 0; k < 8; k++)
2574 {
2575 // Round with the scale that will actually be stored, then refit scale by least squares.
2576 const float scale_f = (float)scale;
2577 uint16_t scale_h;
2578 float stored_scale;
2579 ccv_float_to_half_precision(&scale_f, &scale_h, 1);
2580 ccv_half_precision_to_float(&scale_h, &stored_scale, 1);
2581 if (!(stored_scale > 0))
2582 break;
2583 const double inv_scale = 1. / stored_scale;
2584 double sum_qx = 0;
2585 double sum_qq = 0;
2586 double sse = 0;
2587 for (j = 0; j < row_length; j++)
2588 {
2589 const double w = _ccv_nnc_8i_rowwise_weight(imatrix, j);
2590 float v_f;
2591 ccv_half_precision_to_float(row + j, &v_f, 1);
2592 const double v = v_f;
2593 const int qj = _ccv_nnc_8i_rowwise_quantize(v, inv_scale);
2594 const double d = v - stored_scale * qj;
2595 sse += w * d * d;
2596 sum_qx += w * qj * v;
2597 sum_qq += w * qj * qj;
2598 }
2599 if (sse < best_sse)
2600 {
2601 best_sse = sse;
2602 best_scale = stored_scale;
2603 }
2604 if (!(sum_qq > 0) || !(sum_qx > 0))
2605 break;
2606 const double next_scale = sum_qx / sum_qq;
2607 const float next_scale_f = (float)next_scale;
2608 uint16_t next_scale_h;
2609 float next_stored_scale;
2610 ccv_float_to_half_precision(&next_scale_f, &next_scale_h, 1);
2611 ccv_half_precision_to_float(&next_scale_h, &next_stored_scale, 1);
2612 if (next_stored_scale == stored_scale)
2613 break;
2614 scale = next_scale;
2615 }
2616 if (!(best_scale > 0))
2617 {
2618 memset(q, 0, row_length);
2619 return 0;
2620 }
2621 const double inv_scale = 1. / best_scale;
2622 for (j = 0; j < row_length; j++)
2623 {
2624 float v;
2625 ccv_half_precision_to_float(row + j, &v, 1);
2626 q[j] = (int8_t)_ccv_nnc_8i_rowwise_quantize(v, inv_scale);
2627 }
2628 return best_scale;
2629}
2630
2631static 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)
2632{
2633 size_t j;
2634 double max_abs = 0;
2635 for (j = 0; j < row_length; j++)
2636 {
2637 float v;
2638 ccv_bfloat_to_float(row + j, &v, 1);
2639 max_abs = ccv_max(max_abs, fabs(v))({ typeof (max_abs) _a = (max_abs); typeof (fabs(v)) _b = (fabs
(v)); (_a > _b) ? _a : _b; })
;
2640 }
2641 if (max_abs == 0)
2642 {
2643 memset(q, 0, row_length);
2644 return 0;
2645 }
2646 double scale = max_abs / 127.;
2647 float best_scale = 0;
2648 double best_sse = DBL_MAX1.7976931348623157e+308;
2649 int k;
2650 for (k = 0; k < 8; k++)
2651 {
2652 const float scale_f = (float)scale;
2653 uint16_t scale_bf;
2654 float stored_scale;
2655 ccv_float_to_bfloat(&scale_f, &scale_bf, 1);
2656 ccv_bfloat_to_float(&scale_bf, &stored_scale, 1);
2657 if (!(stored_scale > 0))
2658 break;
2659 const double inv_scale = 1. / stored_scale;
2660 double sum_qx = 0;
2661 double sum_qq = 0;
2662 double sse = 0;
2663 for (j = 0; j < row_length; j++)
2664 {
2665 const double w = _ccv_nnc_8i_rowwise_weight(imatrix, j);
2666 float v_f;
2667 ccv_bfloat_to_float(row + j, &v_f, 1);
2668 const double v = v_f;
2669 const int qj = _ccv_nnc_8i_rowwise_quantize(v, inv_scale);
2670 const double d = v - stored_scale * qj;
2671 sse += w * d * d;
2672 sum_qx += w * qj * v;
2673 sum_qq += w * qj * qj;
2674 }
2675 if (sse < best_sse)
2676 {
2677 best_sse = sse;
2678 best_scale = stored_scale;
2679 }
2680 if (!(sum_qq > 0) || !(sum_qx > 0))
2681 break;
2682 const double next_scale = sum_qx / sum_qq;
2683 const float next_scale_f = (float)next_scale;
2684 uint16_t next_scale_bf;
2685 float next_stored_scale;
2686 ccv_float_to_bfloat(&next_scale_f, &next_scale_bf, 1);
2687 ccv_bfloat_to_float(&next_scale_bf, &next_stored_scale, 1);
2688 if (next_stored_scale == stored_scale)
2689 break;
2690 scale = next_scale;
2691 }
2692 if (!(best_scale > 0))
2693 {
2694 memset(q, 0, row_length);
2695 return 0;
2696 }
2697 const double inv_scale = 1. / best_scale;
2698 for (j = 0; j < row_length; j++)
2699 {
2700 float v;
2701 ccv_bfloat_to_float(row + j, &v, 1);
2702 q[j] = (int8_t)_ccv_nnc_8i_rowwise_quantize(v, inv_scale);
2703 }
2704 return best_scale;
2705}
2706
2707static float _ccv_nnc_quantize_8i_rowwise_32f(const float* const row, const size_t row_length, const float* const imatrix, int8_t* const q)
2708{
2709 size_t j;
2710 double max_abs = 0;
2711 for (j = 0; j < row_length; j++)
2712 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; })
;
2713 if (max_abs == 0)
2714 {
2715 memset(q, 0, row_length);
2716 return 0;
2717 }
2718 double scale = max_abs / 127.;
2719 float best_scale = 0;
2720 double best_sse = DBL_MAX1.7976931348623157e+308;
2721 int k;
2722 for (k = 0; k < 8; k++)
2723 {
2724 const float stored_scale = (float)scale;
2725 if (!(stored_scale > 0))
2726 break;
2727 const double inv_scale = 1. / stored_scale;
2728 double sum_qx = 0;
2729 double sum_qq = 0;
2730 double sse = 0;
2731 for (j = 0; j < row_length; j++)
2732 {
2733 const double w = _ccv_nnc_8i_rowwise_weight(imatrix, j);
2734 const double v = row[j];
2735 const int qj = _ccv_nnc_8i_rowwise_quantize(v, inv_scale);
2736 const double d = v - stored_scale * qj;
2737 sse += w * d * d;
2738 sum_qx += w * qj * v;
2739 sum_qq += w * qj * qj;
2740 }
2741 if (sse < best_sse)
2742 {
2743 best_sse = sse;
2744 best_scale = stored_scale;
2745 }
2746 if (!(sum_qq > 0) || !(sum_qx > 0))
2747 break;
2748 const double next_scale = sum_qx / sum_qq;
2749 if ((float)next_scale == stored_scale)
2750 break;
2751 scale = next_scale;
2752 }
2753 if (!(best_scale > 0))
2754 {
2755 memset(q, 0, row_length);
2756 return 0;
2757 }
2758 const double inv_scale = 1. / best_scale;
2759 for (j = 0; j < row_length; j++)
2760 q[j] = (int8_t)_ccv_nnc_8i_rowwise_quantize(row[j], inv_scale);
2761 return best_scale;
2762}
2763
2764static double _ccv_nnc_quantize_8i_rowwise_64f(const double* const row, const size_t row_length, const float* const imatrix, int8_t* const q)
2765{
2766 size_t j;
2767 double max_abs = 0;
2768 for (j = 0; j < row_length; j++)
2769 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; })
;
2770 if (max_abs == 0)
2771 {
2772 memset(q, 0, row_length);
2773 return 0;
2774 }
2775 double scale = max_abs / 127.;
2776 double best_scale = 0;
2777 double best_sse = DBL_MAX1.7976931348623157e+308;
2778 int k;
2779 for (k = 0; k < 8; k++)
2780 {
2781 const double stored_scale = scale;
2782 if (!(stored_scale > 0))
2783 break;
2784 const double inv_scale = 1. / stored_scale;
2785 double sum_qx = 0;
2786 double sum_qq = 0;
2787 double sse = 0;
2788 for (j = 0; j < row_length; j++)
2789 {
2790 const double w = _ccv_nnc_8i_rowwise_weight(imatrix, j);
2791 const double v = row[j];
2792 const int qj = _ccv_nnc_8i_rowwise_quantize(v, inv_scale);
2793 const double d = v - stored_scale * qj;
2794 sse += w * d * d;
2795 sum_qx += w * qj * v;
2796 sum_qq += w * qj * qj;
2797 }
2798 if (sse < best_sse)
2799 {
2800 best_sse = sse;
2801 best_scale = stored_scale;
2802 }
2803 if (!(sum_qq > 0) || !(sum_qx > 0))
2804 break;
2805 const double next_scale = sum_qx / sum_qq;
2806 if (next_scale == stored_scale)
2807 break;
2808 scale = next_scale;
2809 }
2810 if (!(best_scale > 0))
2811 {
2812 memset(q, 0, row_length);
2813 return 0;
2814 }
2815 const double inv_scale = 1. / best_scale;
2816 for (j = 0; j < row_length; j++)
2817 q[j] = (int8_t)_ccv_nnc_8i_rowwise_quantize(row[j], inv_scale);
2818 return best_scale;
2819}
2820
2821CCV_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)
2822{
2823 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", 2823, __extension__ __PRETTY_FUNCTION__
); }))
;
2824 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", 2824, __extension__ __PRETTY_FUNCTION__
); }))
;
2825 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", 2825, __extension__ __PRETTY_FUNCTION__
); }))
;
2826 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", 2826
, __extension__ __PRETTY_FUNCTION__); }))
;
2827 const size_t row_count = input_length / row_length;
2828 if (!_ccv_nnc_8i_rowwise_imatrix_is_valid(imatrix, imatrix_length, row_length, row_count))
2829 return 0;
2830 const size_t scale_offset = (input_length + 127) & -128;
2831 const size_t scale_size = row_count * CCV_GET_DATA_TYPE_SIZE(datatype)_ccv_get_data_type_size[((datatype) & 0xFF000) >> 12
]
;
2832 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", 2832, __extension__ __PRETTY_FUNCTION__
); }))
;
2833 int8_t* const q = (int8_t*)output;
2834 uint8_t* const u8 = (uint8_t*)output;
2835 if (datatype == CCV_16F)
2836 {
2837 const uint16_t* const f16 = (const uint16_t*)input;
2838 uint16_t* const scales = (uint16_t*)(u8 + scale_offset);
2839 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2840 const size_t row_start = (size_t)i * row_length;
2841 const float* const row_imatrix = _ccv_nnc_8i_rowwise_imatrix_for_row(imatrix, imatrix_length, row_length, row_count, (size_t)i);
2842 const float scale_f = _ccv_nnc_quantize_8i_rowwise_16f(f16 + row_start, row_length, row_imatrix, q + row_start);
2843 ccv_float_to_half_precision(&scale_f, scales + i, 1);
2844 } parallel_endfor} }
2845 } else if (datatype == CCV_16BF) {
2846 const uint16_t* const bf16 = (const uint16_t*)input;
2847 uint16_t* const scales = (uint16_t*)(u8 + scale_offset);
2848 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2849 const size_t row_start = (size_t)i * row_length;
2850 const float* const row_imatrix = _ccv_nnc_8i_rowwise_imatrix_for_row(imatrix, imatrix_length, row_length, row_count, (size_t)i);
2851 const float scale_f = _ccv_nnc_quantize_8i_rowwise_16bf(bf16 + row_start, row_length, row_imatrix, q + row_start);
2852 ccv_float_to_bfloat(&scale_f, scales + i, 1);
2853 } parallel_endfor} }
2854 } else if (datatype == CCV_32F) {
2855 const float* const f32 = (const float*)input;
2856 float* const scales = (float*)(u8 + scale_offset);
2857 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2858 const size_t row_start = (size_t)i * row_length;
2859 const float* const row_imatrix = _ccv_nnc_8i_rowwise_imatrix_for_row(imatrix, imatrix_length, row_length, row_count, (size_t)i);
2860 scales[i] = _ccv_nnc_quantize_8i_rowwise_32f(f32 + row_start, row_length, row_imatrix, q + row_start);
2861 } parallel_endfor} }
2862 } else {
2863 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", 2863, __extension__ __PRETTY_FUNCTION__
); }))
;
2864 const double* const f64 = (const double*)input;
2865 double* const scales = (double*)(u8 + scale_offset);
2866 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2867 const size_t row_start = (size_t)i * row_length;
2868 const float* const row_imatrix = _ccv_nnc_8i_rowwise_imatrix_for_row(imatrix, imatrix_length, row_length, row_count, (size_t)i);
2869 scales[i] = _ccv_nnc_quantize_8i_rowwise_64f(f64 + row_start, row_length, row_imatrix, q + row_start);
2870 } parallel_endfor} }
2871 }
2872 return scale_offset + scale_size;
2873}
2874
2875void 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)
2876{
2877 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", 2877, __extension__ __PRETTY_FUNCTION__
); }))
;
2878 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", 2878, __extension__ __PRETTY_FUNCTION__
); }))
;
2879 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", 2879, __extension__ __PRETTY_FUNCTION__
); }))
;
2880 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", 2880
, __extension__ __PRETTY_FUNCTION__); }))
;
2881 if (memory_type != CCV_TENSOR_CPU_MEMORY)
2882 {
2883#ifdef HAVE_CUDA1
2884 ccv_nnc_compat_dequantize_8i_rowwise(input, datatype, input_length, row_length, output, output_length, 0);
2885#elif defined(HAVE_MPS)
2886 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", 2886, __extension__ __PRETTY_FUNCTION__
); }))
;
2887 ccv_nnc_mps_dequantize_8i_rowwise(input, datatype, input_length, row_length, output, output_length, 0);
2888#else
2889 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", 2889, __extension__ __PRETTY_FUNCTION__
); }))
;
2890#endif
2891 return;
2892 }
2893 const size_t row_count = output_length / row_length;
2894 const size_t scale_offset = (output_length + 127) & -128;
2895 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", 2895, __extension__ __PRETTY_FUNCTION__
); }))
;
2896 const int8_t* const q = (const int8_t*)input;
2897 const uint8_t* const u8 = (const uint8_t*)input;
2898 if (datatype == CCV_16F)
2899 {
2900 uint16_t* const f16 = (uint16_t*)output;
2901 const uint16_t* const scales = (const uint16_t*)(u8 + scale_offset);
2902 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2903 const size_t row_start = (size_t)i * row_length;
2904 float scale_f;
2905 ccv_half_precision_to_float(scales + i, &scale_f, 1);
2906 size_t j;
2907 for (j = 0; j < row_length; j++)
2908 {
2909 const float v = q[row_start + j] * scale_f;
2910 ccv_float_to_half_precision(&v, f16 + row_start + j, 1);
2911 }
2912 } parallel_endfor} }
2913 } else if (datatype == CCV_16BF) {
2914 uint16_t* const bf16 = (uint16_t*)output;
2915 const uint16_t* const scales = (const uint16_t*)(u8 + scale_offset);
2916 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2917 const size_t row_start = (size_t)i * row_length;
2918 float scale_f;
2919 ccv_bfloat_to_float(scales + i, &scale_f, 1);
2920 size_t j;
2921 for (j = 0; j < row_length; j++)
2922 {
2923 const float v = q[row_start + j] * scale_f;
2924 ccv_float_to_bfloat(&v, bf16 + row_start + j, 1);
2925 }
2926 } parallel_endfor} }
2927 } else if (datatype == CCV_32F) {
2928 float* const f32 = (float*)output;
2929 const float* const scales = (const float*)(u8 + scale_offset);
2930 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2931 const size_t row_start = (size_t)i * row_length;
2932 const float scale = scales[i];
2933 size_t j;
2934 for (j = 0; j < row_length; j++)
2935 f32[row_start + j] = q[row_start + j] * scale;
2936 } parallel_endfor} }
2937 } else {
2938 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", 2938, __extension__ __PRETTY_FUNCTION__
); }))
;
2939 double* const f64 = (double*)output;
2940 const double* const scales = (const double*)(u8 + scale_offset);
2941 parallel_for(i, (int)row_count){ int i; for ((i) = 0; (i) < ((int)row_count); (i)++) { {
2942 const size_t row_start = (size_t)i * row_length;
2943 const double scale = scales[i];
2944 size_t j;
2945 for (j = 0; j < row_length; j++)
2946 f64[row_start + j] = q[row_start + j] * scale;
2947 } parallel_endfor} }
2948 }
2949}