23#define CK_VISION_NOINLINE __attribute__((noinline))
24#elif defined(__GNUC__)
25#define CK_VISION_NOINLINE __attribute__((noinline))
27#define CK_VISION_NOINLINE
35 if (linear_idx < 0 || grid_h <= 0 || grid_w <= 0 || merge_size <= 0) {
40 for (
int y = 0; y < grid_h; y += merge_size) {
41 for (
int x = 0; x < grid_w; x += merge_size) {
42 for (
int dy = 0; dy < merge_size && y + dy < grid_h; ++dy) {
43 for (
int dx = 0; dx < merge_size && x + dx < grid_w; ++dx) {
44 if (index == linear_idx) {
45 return (y + dy) * grid_w + x + dx;
61 const int tile_y = y / merge_size;
62 const int tile_x = x / merge_size;
63 const int tile_height = grid_h - tile_y * merge_size < merge_size
64 ? grid_h - tile_y * merge_size : merge_size;
65 const int tile_width = grid_w - tile_x * merge_size < merge_size
66 ? grid_w - tile_x * merge_size : merge_size;
67 const int rows_before = tile_y * merge_size * grid_w;
68 const int tiles_before = tile_height * tile_x * merge_size;
69 const int within_tile = (y % merge_size) * tile_width + x % merge_size;
70 return rows_before + tiles_before + within_tile;
84 int C,
int H,
int W,
int P)
86 int num_patches_h = H / P;
87 int num_patches_w = W / P;
88 int patch_dim =
C * P * P;
91 for (
int ph = 0; ph < num_patches_h; ++ph) {
92 for (
int pw = 0; pw < num_patches_w; ++pw) {
94 int patch_idx = ph * num_patches_w + pw;
95 float *dst_patch = patches + (size_t)patch_idx * patch_dim;
98 for (
int c = 0; c <
C; ++c) {
99 for (
int py = 0; py < P; ++py) {
104 const float *src_row = image + (size_t)c * H * W + (
size_t)y * W + x;
107 float *dst_row = dst_patch + (size_t)c * P * P + (
size_t)py * P;
110 memcpy(dst_row, src_row, P *
sizeof(
float));
125 int C,
int H,
int W,
int P)
127 int num_patches_h = H / P;
128 int num_patches_w = W / P;
129 int patch_dim =
C * P * P;
132 memset(d_image, 0, (
size_t)
C * H * W *
sizeof(
float));
134 for (
int ph = 0; ph < num_patches_h; ++ph) {
135 for (
int pw = 0; pw < num_patches_w; ++pw) {
137 int patch_idx = ph * num_patches_w + pw;
138 const float *src_patch = d_patches + (size_t)patch_idx * patch_dim;
140 for (
int c = 0; c <
C; ++c) {
141 for (
int py = 0; py < P; ++py) {
145 float *dst_row = d_image + (size_t)c * H * W + (
size_t)y * W + x;
146 const float *src_row = src_patch + (size_t)c * P * P + (
size_t)py * P;
149 for (
int px = 0; px < P; ++px) {
150 dst_row[px] += src_row[px];
169 const float *position_embd,
174 if (x == NULL || position_embd == NULL || num_tokens <= 0 || embed_dim <= 0) {
177 const int limit = num_tokens < num_positions ? num_tokens : num_positions;
178 for (
int tok = 0; tok < limit; ++tok) {
179 float *dst = x + (size_t)tok * embed_dim;
180 const float *src = position_embd + (size_t)tok * embed_dim;
181 for (
int d = 0; d < embed_dim; ++d) {
188 const float *position_embd,
194 if (x == NULL || position_embd == NULL || num_tokens <= 0 || embed_dim <= 0 ||
195 num_positions <= 0 || start_position < 0 || start_position >= num_positions) {
198 const int available = num_positions - start_position;
199 const int limit = num_tokens < available ? num_tokens : available;
200 for (
int tok = 0; tok < limit; ++tok) {
201 float *dst = x + (size_t)tok * embed_dim;
202 const float *src = position_embd + (size_t)(start_position + tok) * embed_dim;
203 for (
int d = 0; d < embed_dim; ++d) {
210 const float *position_embd,
214 int source_grid_size)
216 if (x == NULL || position_embd == NULL || grid_h <= 0 || grid_w <= 0 || embed_dim <= 0) {
219 if (source_grid_size <= 0) {
220 source_grid_size = grid_w > grid_h ? grid_w : grid_h;
223 const size_t table_stride = (size_t) source_grid_size * (
size_t) embed_dim;
224 const float *table_x = position_embd;
225 const float *table_y = position_embd + table_stride;
227 for (
int y = 0; y < grid_h; ++y) {
228 const int yy = y < source_grid_size ? y : (source_grid_size - 1);
229 const float *row_y = table_y + (size_t) yy * (
size_t) embed_dim;
230 for (
int x_pos = 0; x_pos < grid_w; ++x_pos) {
231 const int xx = x_pos < source_grid_size ? x_pos : (source_grid_size - 1);
232 const float *row_x = table_x + (size_t) xx * (
size_t) embed_dim;
233 float *dst = x + ((size_t) y * (
size_t) grid_w + (size_t) x_pos) * (size_t) embed_dim;
234 for (
int d = 0; d < embed_dim; ++d) {
235 dst[d] += row_x[d] + row_y[d];
245#if defined(__clang__) || defined(__INTEL_LLVM_COMPILER)
246#pragma float_control(precise, on, push)
249 const float *position_embd,
254 int source_grid_size)
256 if (x == NULL || position_embd == NULL || grid_h <= 0 || grid_w <= 0 || embed_dim <= 0 || merge_size <= 0) {
260 if (source_grid_size <= 0) {
261 source_grid_size = grid_h == grid_w ? grid_h : (grid_h > grid_w ? grid_h : grid_w);
264 const int num_tokens = grid_h * grid_w;
265 const int source_tokens = source_grid_size * source_grid_size;
266 const int needs_resize = source_grid_size != grid_h || source_grid_size != grid_w;
269 for (
int tok = 0; tok < num_tokens; ++tok) {
271 if (flat < 0 || flat >= source_tokens) {
274 float *dst = x + (size_t) tok * (
size_t) embed_dim;
275 const float *src = position_embd + (size_t) flat * (
size_t) embed_dim;
276 for (
int d = 0; d < embed_dim; ++d) {
283 const float sf_x = (float) grid_w / (
float) source_grid_size;
284 const float sf_y = (float) grid_h / (
float) source_grid_size;
285 const float pixel_offset = 0.5f;
286 const float support_x = fmaxf(1.0f, 1.0f / sf_x);
287 const float support_y = fmaxf(1.0f, 1.0f / sf_y);
288 const float invscale_x = 1.0f / support_x;
289 const float invscale_y = 1.0f / support_y;
294 for (
int d = 0; d < embed_dim; ++d) {
295 for (
int dst_y = 0; dst_y < grid_h; ++dst_y) {
296 const float y_src = ((float) dst_y + pixel_offset) / sf_y;
297 int y_min = (int) (y_src - support_y + pixel_offset);
298 int y_max = (int) (y_src + support_y + pixel_offset);
299 if (y_min < 0) y_min = 0;
300 if (y_max > source_grid_size) y_max = source_grid_size;
302 for (
int dst_x = 0; dst_x < grid_w; ++dst_x) {
303 const float x_src = ((float) dst_x + pixel_offset) / sf_x;
304 int x_min = (int) (x_src - support_x + pixel_offset);
305 int x_max = (int) (x_src + support_x + pixel_offset);
306 if (x_min < 0) x_min = 0;
307 if (x_max > source_grid_size) x_max = source_grid_size;
309 float total_weight = 0.0f;
310 for (
int sy = y_min; sy < y_max; ++sy) {
311 const float wy_arg = ((float) sy - y_src + pixel_offset) * invscale_y;
312 const float wy = fmaxf(1.0f - fabsf(wy_arg), 0.0f);
316 for (
int sx = x_min; sx < x_max; ++sx) {
317 const float wx_arg = ((float) sx - x_src + pixel_offset) * invscale_x;
318 const float wx = fmaxf(1.0f - fabsf(wx_arg), 0.0f);
319 const float weight = wx * wy;
320 if (weight <= 0.0f) {
323 const float sample = position_embd[((size_t) sy * (
size_t) source_grid_size + (size_t) sx) * (size_t) embed_dim + (
size_t) d];
324 val = fmaf(sample, weight, val);
325 total_weight += weight;
328 if (total_weight > 0.0f) {
331 dst_y, dst_x, grid_h, grid_w, merge_size);
332 x[(size_t) tok * (
size_t) embed_dim + (size_t) d] += val;
338#if defined(__clang__) || defined(__INTEL_LLVM_COMPILER)
339#pragma float_control(pop)
343 const float *position_embd,
348 int source_grid_size)
350 if (x == NULL || position_embd == NULL || grid_h <= 0 || grid_w <= 0 ||
351 embed_dim <= 0 || merge_size <= 0 || source_grid_size <= 0) {
355 const float y_scale = grid_h > 1
356 ? (float)(source_grid_size - 1) / (float)(grid_h - 1)
358 const float x_scale = grid_w > 1
359 ? (float)(source_grid_size - 1) / (float)(grid_w - 1)
362 for (
int tok = 0; tok < grid_h * grid_w; ++tok) {
364 const int dst_y = row_major / grid_w;
365 const int dst_x = row_major % grid_w;
366 const float src_y = (float)dst_y * y_scale;
367 const float src_x = (float)dst_x * x_scale;
368 const int y0 = (int)src_y;
369 const int x0 = (int)src_x;
370 const int y1 = y0 + 1 < source_grid_size ? y0 + 1 : y0;
371 const int x1 = x0 + 1 < source_grid_size ? x0 + 1 : x0;
372 const float dy = src_y - (float)y0;
373 const float dx = src_x - (float)x0;
374 const float w00 = (1.0f - dy) * (1.0f - dx);
375 const float w01 = (1.0f - dy) * dx;
376 const float w10 = dy * (1.0f - dx);
377 const float w11 = dy * dx;
378 const float *p00 = position_embd + ((size_t)y0 * source_grid_size + x0) * embed_dim;
379 const float *p01 = position_embd + ((size_t)y0 * source_grid_size + x1) * embed_dim;
380 const float *p10 = position_embd + ((size_t)y1 * source_grid_size + x0) * embed_dim;
381 const float *p11 = position_embd + ((size_t)y1 * source_grid_size + x1) * embed_dim;
382 float *dst = x + (size_t)tok * embed_dim;
384 for (
int d = 0; d < embed_dim; ++d) {
385 const float pos = p00[d] * w00 + p01[d] * w01 + p10[d] * w10 + p11[d] * w11;
398 const float *position_embd,
403 int source_grid_size)
405 if (x == NULL || position_embd == NULL || grid_h <= 0 || grid_w <= 0 ||
406 embed_dim <= 0 || merge_size <= 0 || source_grid_size <= 0) {
410 for (
int tok = 0; tok < grid_h * grid_w; ++tok) {
412 const int dst_y = row_major / grid_w;
413 const int dst_x = row_major % grid_w;
415 const float src_y = grid_h > 1
416 ? (float)((
double)dst_y * (double)(source_grid_size - 1) / (double)(grid_h - 1))
418 const float src_x = grid_w > 1
419 ? (float)((
double)dst_x * (double)(source_grid_size - 1) / (double)(grid_w - 1))
421 const int y0 = (int)src_y;
422 const int x0 = (int)src_x;
423 const int y1 = y0 + 1 < source_grid_size ? y0 + 1 : y0;
424 const int x1 = x0 + 1 < source_grid_size ? x0 + 1 : x0;
425 const float dy = src_y - (float)y0;
426 const float dx = src_x - (float)x0;
431 const float *p00 = position_embd + ((size_t)y0 * source_grid_size + x0) * embed_dim;
432 const float *p01 = position_embd + ((size_t)y0 * source_grid_size + x1) * embed_dim;
433 const float *p10 = position_embd + ((size_t)y1 * source_grid_size + x0) * embed_dim;
434 const float *p11 = position_embd + ((size_t)y1 * source_grid_size + x1) * embed_dim;
435 float *dst = x + (size_t)tok * embed_dim;
437 for (
int d = 0; d < embed_dim; ++d) {
460 const float *position_embd,
465 int source_grid_size)
467 if (x == NULL || position_embd == NULL || grid_h <= 0 || grid_w <= 0 ||
468 embed_dim <= 0 || merge_size <= 0 || source_grid_size <= 0) {
472 for (
int tok = 0; tok < grid_h * grid_w; ++tok) {
474 const int dst_y = row_major / grid_w;
475 const int dst_x = row_major % grid_w;
476 const float src_y = grid_h > 1
477 ? (float)dst_y * (
float)(source_grid_size - 1) / (
float)(grid_h - 1)
479 const float src_x = grid_w > 1
480 ? (float)dst_x * (
float)(source_grid_size - 1) / (
float)(grid_w - 1)
482 const int y0 = (int)src_y;
483 const int x0 = (int)src_x;
484 const int y1 = y0 + 1 < source_grid_size ? y0 + 1 : y0;
485 const int x1 = x0 + 1 < source_grid_size ? x0 + 1 : x0;
486 const float y_distance0 = fabsf(src_y - (
float)y0);
487 const float y_distance1 = fabsf(src_y - (
float)y0 - 1.0f);
488 const float x_distance0 = fabsf(src_x - (
float)x0);
489 const float x_distance1 = fabsf(src_x - (
float)x0 - 1.0f);
490 const float wy0 = fmaxf(1.0f - y_distance0, 0.0f);
491 const float wy1 = fmaxf(1.0f - y_distance1, 0.0f);
492 const float wx0 = fmaxf(1.0f - x_distance0, 0.0f);
493 const float wx1 = fmaxf(1.0f - x_distance1, 0.0f);
494 const float w00 = wy0 * wx0;
495 const float w01 = wy0 * wx1;
496 const float w10 = wy1 * wx0;
497 const float w11 = wy1 * wx1;
498 const float *p00 = position_embd + ((size_t)y0 * source_grid_size + x0) * embed_dim;
499 const float *p01 = position_embd + ((size_t)y0 * source_grid_size + x1) * embed_dim;
500 const float *p10 = position_embd + ((size_t)y1 * source_grid_size + x0) * embed_dim;
501 const float *p11 = position_embd + ((size_t)y1 * source_grid_size + x1) * embed_dim;
502 float *dst = x + (size_t)tok * embed_dim;
504 for (
int d = 0; d < embed_dim; ++d) {
506 volatile float v00 = p00[d] * w00;
507 volatile float v01 = p01[d] * w01;
508 volatile float v10 = p10[d] * w10;
509 volatile float v11 = p11[d] * w11;
510 volatile float pos01 = v00 + v01;
511 volatile float pos012 = pos01 + v10;
512 const float pos = pos012 + v11;
534 if (!positions || grid_h <= 0 || grid_w <= 0 || merge_size <= 0) {
538 const int num_tokens = grid_h * grid_w;
541 for (
int y = 0; y < grid_h; y += merge_size) {
542 for (
int x = 0; x < grid_w; x += merge_size) {
543 for (
int dy = 0; dy < merge_size; ++dy) {
544 for (
int dx = 0; dx < merge_size; ++dx) {
545 const int yy = y + dy;
546 const int xx = x + dx;
547 if (yy >= grid_h || xx >= grid_w || ptr >= num_tokens) {
551 positions[num_tokens + ptr] = xx;
552 positions[2 * num_tokens + ptr] = yy;
553 positions[3 * num_tokens + ptr] = xx;
560 for (; ptr < num_tokens; ++ptr) {
562 positions[num_tokens + ptr] = 0;
563 positions[2 * num_tokens + ptr] = 0;
564 positions[3 * num_tokens + ptr] = 0;
583 if (input == NULL || output == NULL || grid_h <= 0 || grid_w <= 0 || embed_dim <= 0) {
587 const int merged_h = grid_h / 2;
588 const int merged_w = grid_w / 2;
589 const size_t token_stride = (size_t)embed_dim;
590 const size_t merged_stride = (size_t)embed_dim * 4;
592 for (
int mh = 0; mh < merged_h; ++mh) {
593 for (
int mw = 0; mw < merged_w; ++mw) {
594 const int y0 = mh * 2;
595 const int x0 = mw * 2;
596 const int in_idx00 = y0 * grid_w + x0;
597 const int in_idx01 = in_idx00 + 1;
598 const int in_idx10 = in_idx00 + grid_w;
599 const int in_idx11 = in_idx10 + 1;
600 const int out_idx = mh * merged_w + mw;
602 const float *src00 = input + (size_t)in_idx00 * token_stride;
603 const float *src01 = input + (size_t)in_idx01 * token_stride;
604 const float *src10 = input + (size_t)in_idx10 * token_stride;
605 const float *src11 = input + (size_t)in_idx11 * token_stride;
606 float *dst = output + (size_t)out_idx * merged_stride;
608 memcpy(dst + 0 * embed_dim, src00, (
size_t)embed_dim *
sizeof(
float));
609 memcpy(dst + 1 * embed_dim, src01, (
size_t)embed_dim *
sizeof(
float));
610 memcpy(dst + 2 * embed_dim, src10, (
size_t)embed_dim *
sizeof(
float));
611 memcpy(dst + 3 * embed_dim, src11, (
size_t)embed_dim *
sizeof(
float));
623 if (input == NULL || output == NULL || grid_h <= 0 || grid_w <= 0 || embed_dim <= 0 || merge_size <= 0) {
627 const size_t num_tokens = (size_t) grid_h * (
size_t) grid_w;
628 const size_t merge_factor = (size_t) merge_size * (
size_t) merge_size;
629 const size_t merged_tokens = num_tokens / merge_factor;
630 memcpy(output, input, merged_tokens * (
size_t) embed_dim * merge_factor *
sizeof(
float));
640 if (input == NULL || output == NULL || tokens <= 0 || dim <= 0)
return;
641 if (eps <= 0.0f) eps = 1.0e-6f;
642 for (
int t = 0; t < tokens; ++t) {
643 const float *src = input + (size_t)t * (
size_t)dim;
644 float *dst = output + (size_t)t * (
size_t)dim;
646 for (
int i = 0; i < dim; ++i) {
647 const float v = src[i] * scale;
648 ss += (double)v * (
double)v;
650 const float inv_rms = 1.0f / sqrtf((
float)(ss / (
double)dim) + eps);
651 for (
int i = 0; i < dim; ++i) {
652 dst[i] = (src[i] * scale) * inv_rms;
664 if (input == NULL || output == NULL || grid_h <= 0 || grid_w <= 0 || embed_dim <= 0 || merge_size <= 0) {
668 const int out_h = grid_h / merge_size;
669 const int out_w = grid_w / merge_size;
670 if (out_h <= 0 || out_w <= 0) {
674 const float inv_area = 1.0f / (float)(merge_size * merge_size);
675 for (
int oy = 0; oy < out_h; ++oy) {
676 for (
int ox = 0; ox < out_w; ++ox) {
677 float *dst = output + ((size_t)oy * (
size_t)out_w + (size_t)ox) * (size_t)embed_dim;
678 memset(dst, 0, (
size_t)embed_dim *
sizeof(
float));
679 for (
int dy = 0; dy < merge_size; ++dy) {
680 const int iy = oy * merge_size + dy;
681 for (
int dx = 0; dx < merge_size; ++dx) {
682 const int ix = ox * merge_size + dx;
683 const float *src = input + ((size_t)iy * (
size_t)grid_w + (size_t)ix) * (size_t)embed_dim;
684 for (
int c = 0; c < embed_dim; ++c) {
689 for (
int c = 0; c < embed_dim; ++c) {
701 if (!x || !bias || rows <= 0 || dim <= 0) {
705 for (
int r = 0; r < rows; ++r) {
706 float *row = x + ((size_t) r * (
size_t) dim);
707 for (
int c = 0; c < dim; ++c) {
717 if (!a || !b || n == 0) {
721 for (
size_t i = 0; i < n; ++i) {
733 if (!main_inout || !aux_scratch || grid_h <= 0 || grid_w <= 0 || embed_dim <= 0 || merge_size <= 0) {
737 const int num_tokens = grid_h * grid_w;
738 const size_t total_elems = (size_t) num_tokens * (
size_t) embed_dim;
740 for (
size_t i = 0; i < total_elems; ++i) {
741 main_inout[i] += aux_scratch[i];
744 for (
int tok = 0; tok < num_tokens; ++tok) {
746 const float *src_main = main_inout + (size_t) src_tok * (
size_t) embed_dim;
747 float *dst = aux_scratch + (size_t) tok * (
size_t) embed_dim;
748 for (
int d = 0; d < embed_dim; ++d) {
749 dst[d] = src_main[d];
753 memcpy(main_inout, aux_scratch, total_elems *
sizeof(
float));
757 const float *branch_input,
761 int branch_slice_dim,
762 int num_branch_slices)
764 if (!main_input || !branch_input || !output || rows <= 0 || main_dim <= 0 ||
765 branch_slice_dim < 0 || num_branch_slices < 0) {
769 const int branch_dim = branch_slice_dim * num_branch_slices;
770 const size_t main_bytes = (size_t) main_dim *
sizeof(
float);
771 const size_t branch_bytes = (size_t) branch_dim *
sizeof(
float);
772 const size_t out_stride = (size_t) (main_dim + branch_dim);
774 for (
int r = 0; r < rows; ++r) {
775 const float *src_main = main_input + ((size_t) r * (
size_t) main_dim);
776 const float *src_branch = branch_input + ((size_t) r * (
size_t) branch_dim);
777 float *dst = output + ((size_t) r * out_stride);
778 memcpy(dst, src_main, main_bytes);
779 memcpy(dst + main_dim, src_branch, branch_bytes);
788 int dst_feature_offset)
790 if (!src || !dst || rows <= 0 || src_dim <= 0 || dst_dim <= 0 || dst_feature_offset < 0) {
793 if (dst_feature_offset + src_dim > dst_dim) {
797 for (
int row = 0; row < rows; ++row) {
798 const float *src_row = src + (size_t) row * (
size_t) src_dim;
799 float *dst_row = dst + (size_t) row * (
size_t) dst_dim + (size_t) dst_feature_offset;
800 memcpy(dst_row, src_row, (
size_t) src_dim *
sizeof(
float));
805 const float *branch_input,
809 int branch_slice_dim,
810 int num_branch_slices)
812 if (!main_input || !output || rows <= 0 || main_dim < 0 || branch_slice_dim < 0 || num_branch_slices < 0) {
816 const int branch_total_dim = branch_slice_dim * num_branch_slices;
817 const int out_dim = main_dim + branch_total_dim;
819 const int in_place_expand = (main_input == output) && (out_dim > main_dim);
820 const int row_start = in_place_expand ? rows - 1 : 0;
821 const int row_end = in_place_expand ? -1 : rows;
822 const int row_step = in_place_expand ? -1 : 1;
824 for (
int row = row_start; row != row_end; row += row_step) {
825 const float *src_main = main_input + (size_t) row * (
size_t) main_dim;
826 float *dst_row = output + (size_t) row * (
size_t) out_dim;
829 memmove(dst_row, src_main, (
size_t) main_dim *
sizeof(
float));
832 for (
int slice = 0; slice < num_branch_slices; ++slice) {
833 const float *src_branch = branch_input
834 + (size_t) slice * (
size_t) rows * (size_t) branch_slice_dim
835 + (
size_t) row * (size_t) branch_slice_dim;
836 float *dst_branch = dst_row + (size_t) main_dim + (
size_t) slice * (size_t) branch_slice_dim;
837 if (branch_slice_dim > 0) {
838 memcpy(dst_branch, src_branch, (
size_t) branch_slice_dim *
sizeof(
float));
static uint16_t float_to_bf16(float f)
static float bf16_to_float(uint16_t v)
void add_stream_reorder_2d(float *main_inout, float *aux_scratch, int grid_h, int grid_w, int embed_dim, int merge_size)
void position_embeddings_add_gemma4v_xy(float *x, const float *position_embd, int grid_h, int grid_w, int embed_dim, int source_grid_size)
static int tile_order_index_2d(int linear_idx, int grid_h, int grid_w, int merge_size)
static int tile_order_linear_index_2d(int y, int x, int grid_h, int grid_w, int merge_size)
void spatial_merge_2x2(const float *input, float *output, int grid_h, int grid_w, int embed_dim)
void position_embeddings_add_tiled_2d_align_corners(float *x, const float *position_embd, int grid_h, int grid_w, int embed_dim, int merge_size, int source_grid_size)
void position_embeddings_add_tiled_2d(float *x, const float *position_embd, int grid_h, int grid_w, int embed_dim, int merge_size, int source_grid_size)
void patch2im(const float *d_patches, float *d_image, int C, int H, int W, int P)
void position_embeddings_add_tiled_2d_align_corners_bf16(float *x, const float *position_embd, int grid_h, int grid_w, int embed_dim, int merge_size, int source_grid_size)
void position_embeddings_add_tiled_2d_align_corners_fp32_interp_bf16(float *x, const float *position_embd, int grid_h, int grid_w, int embed_dim, int merge_size, int source_grid_size)
void feature_slice_copy(const float *src, float *dst, int rows, int src_dim, int dst_dim, int dst_feature_offset)
void spatial_merge_contiguous_tiled(const float *input, float *output, int grid_h, int grid_w, int embed_dim, int merge_size)
void im2patch(const float *image, float *patches, int C, int H, int W, int P)
void gemma4_vision_projector_prep_forward(const float *input, float *output, int tokens, int dim, float scale, float eps)
void feature_concat_2way(const float *main_input, const float *branch_input, float *output, int rows, int main_dim, int branch_slice_dim, int num_branch_slices)
void spatial_average_pool_contiguous(const float *input, float *output, int grid_h, int grid_w, int embed_dim, int merge_size)
void feature_concat(const float *main_input, const float *branch_input, float *output, int rows, int main_dim, int branch_slice_dim, int num_branch_slices)
void position_embeddings_add_at_offset(float *x, const float *position_embd, int num_tokens, int embed_dim, int num_positions, int start_position)
void add_stream_inplace(float *a, const float *b, size_t n)
void rowwise_bias_add(float *x, const float *bias, int rows, int dim)
#define CK_VISION_NOINLINE
void position_embeddings_add(float *x, const float *position_embd, int num_tokens, int embed_dim, int num_positions)
void vision_position_ids_2d_merge(int32_t *positions, int grid_h, int grid_w, int merge_size)