| 8338 | // ggml_compute_forward_repeat |
| 8339 | |
| 8340 | static void ggml_compute_forward_repeat_f32( |
| 8341 | const struct ggml_compute_params * params, |
| 8342 | const struct ggml_tensor * src0, |
| 8343 | struct ggml_tensor * dst) { |
| 8344 | GGML_ASSERT(params->ith == 0); |
| 8345 | GGML_ASSERT(ggml_can_repeat(src0, dst)); |
| 8346 | |
| 8347 | if (params->type == GGML_TASK_INIT || params->type == GGML_TASK_FINALIZE) { |
| 8348 | return; |
| 8349 | } |
| 8350 | |
| 8351 | GGML_TENSOR_UNARY_OP_LOCALS |
| 8352 | |
| 8353 | // guaranteed to be an integer due to the check in ggml_can_repeat |
| 8354 | const int nr0 = (int)(ne0/ne00); |
| 8355 | const int nr1 = (int)(ne1/ne01); |
| 8356 | const int nr2 = (int)(ne2/ne02); |
| 8357 | const int nr3 = (int)(ne3/ne03); |
| 8358 | |
| 8359 | // TODO: support for transposed / permuted tensors |
| 8360 | GGML_ASSERT(nb0 == sizeof(float)); |
| 8361 | GGML_ASSERT(nb00 == sizeof(float)); |
| 8362 | |
| 8363 | // TODO: maybe this is not optimal? |
| 8364 | for (int i3 = 0; i3 < nr3; i3++) { |
| 8365 | for (int k3 = 0; k3 < ne03; k3++) { |
| 8366 | for (int i2 = 0; i2 < nr2; i2++) { |
| 8367 | for (int k2 = 0; k2 < ne02; k2++) { |
| 8368 | for (int i1 = 0; i1 < nr1; i1++) { |
| 8369 | for (int k1 = 0; k1 < ne01; k1++) { |
| 8370 | for (int i0 = 0; i0 < nr0; i0++) { |
| 8371 | ggml_vec_cpy_f32(ne00, |
| 8372 | (float *) ((char *) dst->data + (i3*ne03 + k3)*nb3 + (i2*ne02 + k2)*nb2 + (i1*ne01 + k1)*nb1 + (i0*ne00)*nb0), |
| 8373 | (float *) ((char *) src0->data + ( k3)*nb03 + ( k2)*nb02 + ( k1)*nb01)); |
| 8374 | } |
| 8375 | } |
| 8376 | } |
| 8377 | } |
| 8378 | } |
| 8379 | } |
| 8380 | } |
| 8381 | } |
| 8382 | |
| 8383 | static void ggml_compute_forward_repeat_f16( |
| 8384 | const struct ggml_compute_params * params, |
no test coverage detected