GCC Code Coverage Report


Directory: src/
File: src/pg/vec16_pg.c
Date: 2026-09-30 11:11:31
Exec Total Coverage
Lines: 221 236 93.6%
Functions: 42 43 97.7%
Branches: 84 142 59.2%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2026 Tiger Data, Inc.
3 * Licensed under the PostgreSQL License. See LICENSE for details.
4 *
5 * vec16_pg.c - PostgreSQL functions for the vec16 type
6 *
7 * Type I/O, distance functions, comparison operators, casts.
8 * Distance functions convert to float32 then delegate to SIMD core.
9 */
10
11 #include <postgres.h>
12
13 #include <catalog/pg_type.h>
14 #include <fmgr.h>
15 #include <lib/stringinfo.h>
16 #include <libpq/pqformat.h>
17 #include <utils/array.h>
18 #include <utils/float.h>
19
20 #include "algo/distance.h"
21 #include "support_pg.h"
22
23 /* Stack threshold for float32 conversion buffers (4 KB = 1024 floats) */
24 #define VEC16_STACK_DIM 1024
25
26 /* ----------------------------------------------------------------
27 * Helper: convert vec16 to Vec32Ref with float32 buffer.
28 * Uses stack allocation for small dims, palloc for large.
29 * ---------------------------------------------------------------- */
30
31 #define HALFVEC_TO_FLOAT(hv, buf_name, ref_name) \
32 float buf_name##_stack[VEC16_STACK_DIM]; \
33 float *buf_name = ((hv)->dim <= VEC16_STACK_DIM) \
34 ? buf_name##_stack \
35 : (float *)palloc((hv)->dim * sizeof(float)); \
36 vs_half_to_float_array((hv)->x, buf_name, (hv)->dim); \
37 Vec32Ref ref_name = {.data = buf_name, .dim = (Dimension)(hv)->dim}
38
39 #define HALFVEC_FREE_BUF(hv, buf_name) \
40 do \
41 { \
42 if ((hv)->dim > VEC16_STACK_DIM) \
43 pfree(buf_name); \
44 } while (0)
45
46 /* ----------------------------------------------------------------
47 * Type I/O
48 * ---------------------------------------------------------------- */
49
50 17 PG_FUNCTION_INFO_V1(vs_vec16_in);
51
52 Datum
53 4377 vs_vec16_in(PG_FUNCTION_ARGS)
54 {
55 4377 char *str = PG_GETARG_CSTRING(0);
56 4377 int32 typmod = PG_GETARG_INT32(2);
57 4377 float values[VEC32_MAX_DIM];
58 4377 int dim = 0;
59 4377 char *p = str;
60
61
3/4
✓ Branch 0 taken 4381 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4377 times.
4381 while (*p && (*p == ' ' || *p == '\t'))
62 4 p++;
63
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4376 times.
4377 if (*p != '[')
64
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ereport(ERROR,
65 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
66 errmsg("vec16 must start with \"[\"")));
67 4376 p++;
68
69
1/2
✓ Branch 0 taken 81297 times.
✗ Branch 1 not taken.
81297 while (*p)
70 {
71
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 81297 times.
81306 while (*p == ' ' || *p == '\t')
72 9 p++;
73
2/2
✓ Branch 0 taken 76923 times.
✓ Branch 1 taken 4374 times.
81297 if (*p == ']')
74 break;
75
76
2/2
✓ Branch 0 taken 72548 times.
✓ Branch 1 taken 4375 times.
76923 if (dim > 0)
77 {
78
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 72547 times.
72548 if (*p != ',')
79
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ereport(ERROR,
80 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
81 errmsg("expected \",\" or \"]\" in vec16")));
82 72547 p++;
83
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 72547 times.
72551 while (*p == ' ' || *p == '\t')
84 4 p++;
85 }
86
87
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72547 times.
72547 if (dim >= VEC32_MAX_DIM)
88 ✗ ereport(ERROR,
89 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
90 errmsg("vec16 cannot have more than %d dimensions",
91 VEC32_MAX_DIM)));
92
93 76922 char *end;
94 76922 errno = 0;
95 76922 float val = strtof(p, &end);
96
3/4
✓ Branch 0 taken 76921 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 76921 times.
76922 if (end == p || errno == ERANGE)
97
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ereport(ERROR,
98 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
99 errmsg("invalid input syntax for type vec16: \"%s\"",
100 str)));
101
102 76921 vs_pg_check_value_finite(val);
103 76921 values[dim++] = val;
104 76921 p = end;
105 }
106
107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4374 times.
4374 if (*p != ']')
108 ✗ ereport(ERROR,
109 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
110 errmsg("vec16 must end with \"]\"")));
111 4374 p++;
112
113
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4374 times.
4378 while (*p == ' ' || *p == '\t')
114 4 p++;
115
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4373 times.
4374 if (*p != '\0')
116
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ereport(ERROR,
117 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
118 errmsg("unexpected characters after \"]\" in vec16")));
119
120
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4372 times.
4373 if (dim < 1)
121
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ereport(ERROR,
122 (errcode(ERRCODE_DATA_EXCEPTION),
123 errmsg("vec16 must have at least 1 dimension")));
124
125 4372 vs_pg_check_expected_dim(dim, typmod);
126
127 4372 Vec16 *result = vs_pg_vec16_alloc(dim);
128 4372 vs_float_to_half_array(values, result->x, dim);
129
130 4372 PG_RETURN_VEC16_P(result);
131 }
132
133 11 PG_FUNCTION_INFO_V1(vs_vec16_out);
134
135 Datum
136 19 vs_vec16_out(PG_FUNCTION_ARGS)
137 {
138 19 Vec16 *v = PG_GETARG_VEC16_P(0);
139 19 StringInfoData buf;
140
141 19 initStringInfo(&buf);
142 19 appendStringInfoChar(&buf, '[');
143
144
2/2
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 19 times.
74 for (int i = 0; i < v->dim; i++)
145 {
146
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 19 times.
55 if (i > 0)
147 36 appendStringInfoChar(&buf, ',');
148 55 appendStringInfo(&buf, "%g", vs_half_to_float(v->x[i]));
149 }
150
151 19 appendStringInfoChar(&buf, ']');
152
153 19 PG_RETURN_CSTRING(buf.data);
154 }
155
156 16 PG_FUNCTION_INFO_V1(vs_vec16_typmod_in);
157
158 Datum
159 22 vs_vec16_typmod_in(PG_FUNCTION_ARGS)
160 {
161 22 ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
162 22 int n;
163 22 int32 *tl = ArrayGetIntegerTypmods(ta, &n);
164
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (n != 1)
166 ✗ ereport(ERROR,
167 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
168 errmsg("invalid type modifier")));
169
170 22 int dim = tl[0];
171
172 22 vs_pg_check_dim_valid(dim);
173
174 22 PG_RETURN_INT32(dim);
175 }
176
177 /* ----------------------------------------------------------------
178 * Distance functions
179 * ---------------------------------------------------------------- */
180
181 19 PG_FUNCTION_INFO_V1(vs_vec16_l2_distance);
182
183 Datum
184 1323 vs_vec16_l2_distance(PG_FUNCTION_ARGS)
185 {
186 1323 Vec16 *a = PG_GETARG_VEC16_P(0);
187 1323 Vec16 *b = PG_GETARG_VEC16_P(1);
188
189 1323 vs_pg_check_dims_match(a->dim, b->dim);
190
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1322 times.
1322 HALFVEC_TO_FLOAT(a, buf_a, ra);
192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1322 times.
1322 HALFVEC_TO_FLOAT(b, buf_b, rb);
193
194 1322 double res = sqrt((double)vs_distance_l2(ra, rb));
195
196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1322 times.
1322 HALFVEC_FREE_BUF(a, buf_a);
197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1322 times.
1322 HALFVEC_FREE_BUF(b, buf_b);
198
199 1322 PG_RETURN_FLOAT8(res);
200 }
201
202 9 PG_FUNCTION_INFO_V1(vs_vec16_inner_product);
203
204 Datum
205 1 vs_vec16_inner_product(PG_FUNCTION_ARGS)
206 {
207 1 Vec16 *a = PG_GETARG_VEC16_P(0);
208 1 Vec16 *b = PG_GETARG_VEC16_P(1);
209
210 1 vs_pg_check_dims_match(a->dim, b->dim);
211
212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 HALFVEC_TO_FLOAT(a, buf_a, ra);
213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 HALFVEC_TO_FLOAT(b, buf_b, rb);
214
215 1 double res = (double)(-vs_distance_ip(ra, rb));
216
217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 HALFVEC_FREE_BUF(a, buf_a);
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 HALFVEC_FREE_BUF(b, buf_b);
219
220 1 PG_RETURN_FLOAT8(res);
221 }
222
223 10 PG_FUNCTION_INFO_V1(vs_vec16_cosine_distance);
224
225 Datum
226 3 vs_vec16_cosine_distance(PG_FUNCTION_ARGS)
227 {
228 3 Vec16 *a = PG_GETARG_VEC16_P(0);
229 3 Vec16 *b = PG_GETARG_VEC16_P(1);
230
231 3 vs_pg_check_dims_match(a->dim, b->dim);
232
233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 HALFVEC_TO_FLOAT(a, buf_a, ra);
234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 HALFVEC_TO_FLOAT(b, buf_b, rb);
235
236 3 double res = (double)vs_distance_cosine(ra, rb);
237
238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 HALFVEC_FREE_BUF(a, buf_a);
239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 HALFVEC_FREE_BUF(b, buf_b);
240
241 3 PG_RETURN_FLOAT8(res);
242 }
243
244 /* Private distance functions for operators */
245
246 8 PG_FUNCTION_INFO_V1(vs_vec16_l2_squared_distance);
247
248 Datum
249 ✗ vs_vec16_l2_squared_distance(PG_FUNCTION_ARGS)
250 {
251 ✗ Vec16 *a = PG_GETARG_VEC16_P(0);
252 ✗ Vec16 *b = PG_GETARG_VEC16_P(1);
253
254 ✗ vs_pg_check_dims_match(a->dim, b->dim);
255
256 ✗ HALFVEC_TO_FLOAT(a, buf_a, ra);
257 ✗ HALFVEC_TO_FLOAT(b, buf_b, rb);
258
259 ✗ double res = (double)vs_distance_l2(ra, rb);
260
261 ✗ HALFVEC_FREE_BUF(a, buf_a);
262 ✗ HALFVEC_FREE_BUF(b, buf_b);
263
264 ✗ PG_RETURN_FLOAT8(res);
265 }
266
267 9 PG_FUNCTION_INFO_V1(vs_vec16_negative_inner_product);
268
269 Datum
270 1 vs_vec16_negative_inner_product(PG_FUNCTION_ARGS)
271 {
272 1 Vec16 *a = PG_GETARG_VEC16_P(0);
273 1 Vec16 *b = PG_GETARG_VEC16_P(1);
274
275 1 vs_pg_check_dims_match(a->dim, b->dim);
276
277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 HALFVEC_TO_FLOAT(a, buf_a, ra);
278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 HALFVEC_TO_FLOAT(b, buf_b, rb);
279
280 1 double res = (double)vs_distance_ip(ra, rb);
281
282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 HALFVEC_FREE_BUF(a, buf_a);
283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 HALFVEC_FREE_BUF(b, buf_b);
284
285 1 PG_RETURN_FLOAT8(res);
286 }
287
288 /* ----------------------------------------------------------------
289 * Comparison functions (for btree opclass)
290 * ---------------------------------------------------------------- */
291
292 static int
293 44111 vec16_cmp_internal(Vec16 *a, Vec16 *b)
294 {
295 44111 int min_dim = (a->dim < b->dim) ? a->dim : b->dim;
296
297
2/2
✓ Branch 0 taken 63921 times.
✓ Branch 1 taken 3 times.
63924 for (int i = 0; i < min_dim; i++)
298 {
299 63921 float fa = vs_half_to_float(a->x[i]);
300 63921 float fb = vs_half_to_float(b->x[i]);
301
2/2
✓ Branch 0 taken 21116 times.
✓ Branch 1 taken 42805 times.
63921 if (fa < fb)
302 return -1;
303
2/2
✓ Branch 0 taken 22992 times.
✓ Branch 1 taken 19813 times.
42805 if (fa > fb)
304 return 1;
305 }
306
307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (a->dim < b->dim)
308 return -1;
309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (a->dim > b->dim)
310 return 1;
311
312 return 0;
313 }
314
315 12 PG_FUNCTION_INFO_V1(vs_vec16_cmp);
316
317 Datum
318 44105 vs_vec16_cmp(PG_FUNCTION_ARGS)
319 {
320 44105 Vec16 *a = PG_GETARG_VEC16_P(0);
321 44105 Vec16 *b = PG_GETARG_VEC16_P(1);
322 44105 PG_RETURN_INT32(vec16_cmp_internal(a, b));
323 }
324
325 9 PG_FUNCTION_INFO_V1(vs_vec16_lt);
326
327 Datum
328 1 vs_vec16_lt(PG_FUNCTION_ARGS)
329 {
330 1 Vec16 *a = PG_GETARG_VEC16_P(0);
331 1 Vec16 *b = PG_GETARG_VEC16_P(1);
332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 PG_RETURN_BOOL(vec16_cmp_internal(a, b) < 0);
333 }
334
335 9 PG_FUNCTION_INFO_V1(vs_vec16_le);
336
337 Datum
338 1 vs_vec16_le(PG_FUNCTION_ARGS)
339 {
340 1 Vec16 *a = PG_GETARG_VEC16_P(0);
341 1 Vec16 *b = PG_GETARG_VEC16_P(1);
342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 PG_RETURN_BOOL(vec16_cmp_internal(a, b) <= 0);
343 }
344
345 9 PG_FUNCTION_INFO_V1(vs_vec16_eq);
346
347 Datum
348 1 vs_vec16_eq(PG_FUNCTION_ARGS)
349 {
350 1 Vec16 *a = PG_GETARG_VEC16_P(0);
351 1 Vec16 *b = PG_GETARG_VEC16_P(1);
352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 PG_RETURN_BOOL(vec16_cmp_internal(a, b) == 0);
353 }
354
355 9 PG_FUNCTION_INFO_V1(vs_vec16_ne);
356
357 Datum
358 1 vs_vec16_ne(PG_FUNCTION_ARGS)
359 {
360 1 Vec16 *a = PG_GETARG_VEC16_P(0);
361 1 Vec16 *b = PG_GETARG_VEC16_P(1);
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 PG_RETURN_BOOL(vec16_cmp_internal(a, b) != 0);
363 }
364
365 9 PG_FUNCTION_INFO_V1(vs_vec16_ge);
366
367 Datum
368 1 vs_vec16_ge(PG_FUNCTION_ARGS)
369 {
370 1 Vec16 *a = PG_GETARG_VEC16_P(0);
371 1 Vec16 *b = PG_GETARG_VEC16_P(1);
372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 PG_RETURN_BOOL(vec16_cmp_internal(a, b) >= 0);
373 }
374
375 9 PG_FUNCTION_INFO_V1(vs_vec16_gt);
376
377 Datum
378 1 vs_vec16_gt(PG_FUNCTION_ARGS)
379 {
380 1 Vec16 *a = PG_GETARG_VEC16_P(0);
381 1 Vec16 *b = PG_GETARG_VEC16_P(1);
382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 PG_RETURN_BOOL(vec16_cmp_internal(a, b) > 0);
383 }
384
385 /* ----------------------------------------------------------------
386 * Utility functions
387 * ---------------------------------------------------------------- */
388
389 9 PG_FUNCTION_INFO_V1(vs_vec16_dims);
390
391 Datum
392 1 vs_vec16_dims(PG_FUNCTION_ARGS)
393 {
394 1 Vec16 *v = PG_GETARG_VEC16_P(0);
395 1 PG_RETURN_INT32(v->dim);
396 }
397
398 9 PG_FUNCTION_INFO_V1(vs_vec16_norm);
399
400 Datum
401 1 vs_vec16_norm(PG_FUNCTION_ARGS)
402 {
403 1 Vec16 *v = PG_GETARG_VEC16_P(0);
404 1 double res = 0.0;
405
406
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
3 for (int i = 0; i < v->dim; i++)
407 {
408 2 double val = (double)vs_half_to_float(v->x[i]);
409 2 res += val * val;
410 }
411
412 1 PG_RETURN_FLOAT8(sqrt(res));
413 }
414
415 /* ----------------------------------------------------------------
416 * Cast functions
417 * ---------------------------------------------------------------- */
418
419 16 PG_FUNCTION_INFO_V1(vs_vec16);
420
421 Datum
422 4261 vs_vec16(PG_FUNCTION_ARGS)
423 {
424 4261 Vec16 *v = PG_GETARG_VEC16_P(0);
425 4261 int32 typmod = PG_GETARG_INT32(1);
426
427 4261 vs_pg_check_expected_dim(v->dim, typmod);
428
429 4260 PG_RETURN_VEC16_P(v);
430 }
431
432 9 PG_FUNCTION_INFO_V1(vs_vec16_to_vec32);
433
434 Datum
435 1 vs_vec16_to_vec32(PG_FUNCTION_ARGS)
436 {
437 1 Vec16 *hv = PG_GETARG_VEC16_P(0);
438 1 int32 typmod = PG_GETARG_INT32(1);
439
440 1 vs_pg_check_expected_dim(hv->dim, typmod);
441
442 1 Vec32 *result = vs_pg_vec32_alloc(hv->dim);
443 1 vs_half_to_float_array(hv->x, result->x, hv->dim);
444
445 1 PG_RETURN_VEC32_P(result);
446 }
447
448 9 PG_FUNCTION_INFO_V1(vs_vec32_to_vec16);
449
450 Datum
451 1 vs_vec32_to_vec16(PG_FUNCTION_ARGS)
452 {
453 1 Vec32 *v = PG_GETARG_VEC32_P(0);
454 1 int32 typmod = PG_GETARG_INT32(1);
455
456 1 vs_pg_check_expected_dim(v->dim, typmod);
457
458 1 Vec16 *result = vs_pg_vec16_alloc(v->dim);
459 1 vs_float_to_half_array(v->x, result->x, v->dim);
460
461 1 PG_RETURN_VEC16_P(result);
462 }
463
464 20 PG_FUNCTION_INFO_V1(vs_array_to_vec16);
465
466 Datum
467 64 vs_array_to_vec16(PG_FUNCTION_ARGS)
468 {
469 64 ArrayType *arr = PG_GETARG_ARRAYTYPE_P(0);
470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 int32 typmod = PG_GETARG_INT32(1);
471 64 Oid elemtype;
472 64 int ndims;
473 64 int *dims;
474 64 int dim;
475 64 Datum *elems;
476 64 bool *nulls;
477 64 int nelems;
478
479 64 elemtype = ARR_ELEMTYPE(arr);
480 64 ndims = ARR_NDIM(arr);
481
482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (ndims > 1)
483 ✗ ereport(ERROR,
484 (errcode(ERRCODE_DATA_EXCEPTION),
485 errmsg("array must be 1-D")));
486
487
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 63 times.
64 if (ndims == 0)
488
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ereport(ERROR,
489 (errcode(ERRCODE_DATA_EXCEPTION),
490 errmsg("array must not be empty")));
491
492 63 dims = ARR_DIMS(arr);
493 63 dim = dims[0];
494
495 63 vs_pg_check_dim_valid(dim);
496 63 vs_pg_check_expected_dim(dim, typmod);
497
498 /*
499 * Only the two element types the SQL overloads declare. Deriving the
500 * element shape from "not float4" would hand deconstruct_array the
501 * wrong length for any other type.
502 */
503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (elemtype != FLOAT4OID && elemtype != FLOAT8OID)
504 ✗ ereport(ERROR,
505 (errcode(ERRCODE_DATATYPE_MISMATCH),
506 errmsg("unsupported array element type")));
507
508
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 32 times.
94 deconstruct_array(
509 arr,
510 elemtype,
511 (elemtype == FLOAT4OID) ? sizeof(float4) : sizeof(float8),
512 (elemtype == FLOAT4OID) ? true : FLOAT8PASSBYVAL,
513 (elemtype == FLOAT4OID) ? TYPALIGN_INT : TYPALIGN_DOUBLE,
514 &elems,
515 &nulls,
516 &nelems);
517
518 /* Convert via float32 intermediate */
519 63 float *floats = (float *)palloc(dim * sizeof(float));
520
2/2
✓ Branch 1 taken 488 times.
✓ Branch 2 taken 62 times.
550 for (int i = 0; i < dim; i++)
521 {
522
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 487 times.
488 if (nulls[i])
523
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ereport(ERROR,
524 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
525 errmsg("array must not contain nulls")));
526
527
2/2
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 243 times.
487 if (elemtype == FLOAT4OID)
528 244 floats[i] = DatumGetFloat4(elems[i]);
529 else
530 243 floats[i] = (float)DatumGetFloat8(elems[i]);
531
532 487 vs_pg_check_value_finite(floats[i]);
533 }
534
535 62 Vec16 *result = vs_pg_vec16_alloc(dim);
536 62 vs_float_to_half_array(floats, result->x, dim);
537
538 62 pfree(floats);
539
540 62 PG_RETURN_VEC16_P(result);
541 }
542