| 158 | } |
| 159 | |
| 160 | TensorValue reshape_tensor(ModuleBuildContext & ctx, const TensorValue & value, const TensorShape & new_shape) { |
| 161 | if (!value.valid()) { |
| 162 | throw std::runtime_error("Cannot reshape an invalid tensor"); |
| 163 | } |
| 164 | if (value.shape.num_elements() != new_shape.num_elements()) { |
| 165 | throw std::runtime_error("Reshape element count mismatch"); |
| 166 | } |
| 167 | if (ctx.ggml == nullptr) { |
| 168 | throw std::runtime_error("ModuleBuildContext.ggml is null"); |
| 169 | } |
| 170 | |
| 171 | const auto ggml_dims = to_ggml_dims(new_shape); |
| 172 | ggml_tensor * reshaped = nullptr; |
| 173 | switch (new_shape.rank) { |
| 174 | case 1: |
| 175 | reshaped = ggml_reshape_1d(ctx.ggml, value.tensor, ggml_dims[0]); |
| 176 | break; |
| 177 | case 2: |
| 178 | reshaped = ggml_reshape_2d(ctx.ggml, value.tensor, ggml_dims[0], ggml_dims[1]); |
| 179 | break; |
| 180 | case 3: |
| 181 | reshaped = ggml_reshape_3d(ctx.ggml, value.tensor, ggml_dims[0], ggml_dims[1], ggml_dims[2]); |
| 182 | break; |
| 183 | case 4: |
| 184 | reshaped = ggml_reshape_4d(ctx.ggml, value.tensor, ggml_dims[0], ggml_dims[1], ggml_dims[2], ggml_dims[3]); |
| 185 | break; |
| 186 | default: |
| 187 | throw std::runtime_error("Unsupported reshape rank"); |
| 188 | } |
| 189 | |
| 190 | return wrap_tensor(reshaped, new_shape, value.type); |
| 191 | } |
| 192 | |
| 193 | bool has_backend_addressable_layout(const ggml_tensor * tensor) noexcept { |
| 194 | return tensor != nullptr && |