im2col: [N, IC, IH, IW] => [N, OH, OW, IC*KH*KW] a: [OC,IC, KH, KW] b: [N, IC, IH, IW] result: [N, OH, OW, IC*KH*KW]
| 4338 | // b: [N, IC, IH, IW] |
| 4339 | // result: [N, OH, OW, IC*KH*KW] |
| 4340 | struct ggml_tensor * ggml_im2col( |
| 4341 | struct ggml_context * ctx, |
| 4342 | struct ggml_tensor * a, |
| 4343 | struct ggml_tensor * b, |
| 4344 | int s0, |
| 4345 | int s1, |
| 4346 | int p0, |
| 4347 | int p1, |
| 4348 | int d0, |
| 4349 | int d1, |
| 4350 | bool is_2D, |
| 4351 | enum ggml_type dst_type) { |
| 4352 | if (is_2D) { |
| 4353 | GGML_ASSERT(a->ne[2] == b->ne[2]); |
| 4354 | } else { |
| 4355 | //GGML_ASSERT(b->ne[1] % a->ne[1] == 0); |
| 4356 | GGML_ASSERT(b->ne[1] == a->ne[1]); |
| 4357 | GGML_ASSERT(b->ne[3] == 1); |
| 4358 | } |
| 4359 | |
| 4360 | const int64_t OH = is_2D ? ggml_calc_conv_output_size(b->ne[1], a->ne[1], s1, p1, d1) : 0; |
| 4361 | const int64_t OW = ggml_calc_conv_output_size(b->ne[0], a->ne[0], s0, p0, d0); |
| 4362 | |
| 4363 | GGML_ASSERT((!is_2D || OH > 0) && "b too small compared to a"); |
| 4364 | GGML_ASSERT((OW > 0) && "b too small compared to a"); |
| 4365 | |
| 4366 | const int64_t ne[4] = { |
| 4367 | is_2D ? (a->ne[2] * a->ne[1] * a->ne[0]) : a->ne[1] * a->ne[0], |
| 4368 | OW, |
| 4369 | is_2D ? OH : b->ne[2], |
| 4370 | is_2D ? b->ne[3] : 1, |
| 4371 | }; |
| 4372 | |
| 4373 | struct ggml_tensor * result = ggml_new_tensor(ctx, dst_type, 4, ne); |
| 4374 | int32_t params[] = { s0, s1, p0, p1, d0, d1, (is_2D ? 1 : 0) }; |
| 4375 | ggml_set_op_params(result, params, sizeof(params)); |
| 4376 | |
| 4377 | result->op = GGML_OP_IM2COL; |
| 4378 | result->src[0] = a; |
| 4379 | result->src[1] = b; |
| 4380 | |
| 4381 | return result; |
| 4382 | } |
| 4383 | |
| 4384 | struct ggml_tensor * ggml_im2col_back( |
| 4385 | struct ggml_context * ctx, |