| 226 | } |
| 227 | |
| 228 | core::TensorValue graph_transpose( |
| 229 | core::ModuleBuildContext & ctx, |
| 230 | const core::TensorValue & input, |
| 231 | const std::array<int, core::kMaxTensorRank> & axes, |
| 232 | size_t rank) { |
| 233 | if (rank != input.shape.rank) { |
| 234 | throw std::runtime_error("DeepFilterNet2 transpose rank mismatch"); |
| 235 | } |
| 236 | core::TensorShape output_shape = {}; |
| 237 | output_shape.rank = rank; |
| 238 | std::array<bool, core::kMaxTensorRank> seen = {false, false, false, false}; |
| 239 | std::array<int, core::kMaxTensorRank> ggml_axes = {0, 1, 2, 3}; |
| 240 | for (size_t out_axis = 0; out_axis < rank; ++out_axis) { |
| 241 | const int in_axis = axes[out_axis]; |
| 242 | if (in_axis < 0 || in_axis >= static_cast<int>(rank) || seen[static_cast<size_t>(in_axis)]) { |
| 243 | throw std::runtime_error("DeepFilterNet2 transpose axes must be a permutation"); |
| 244 | } |
| 245 | seen[static_cast<size_t>(in_axis)] = true; |
| 246 | output_shape.dims[out_axis] = input.shape.dims[static_cast<size_t>(in_axis)]; |
| 247 | const int out_ggml_axis = core::logical_axis_to_ggml_axis(rank, static_cast<int>(out_axis)); |
| 248 | const int in_ggml_axis = core::logical_axis_to_ggml_axis(rank, in_axis); |
| 249 | ggml_axes[static_cast<size_t>(in_ggml_axis)] = out_ggml_axis; |
| 250 | } |
| 251 | return core::wrap_tensor( |
| 252 | ggml_permute(ctx.ggml, graph_contiguous(ctx, input).tensor, ggml_axes[0], ggml_axes[1], ggml_axes[2], ggml_axes[3]), |
| 253 | output_shape, |
| 254 | input.type); |
| 255 | } |
| 256 | |
| 257 | core::TensorValue graph_add(core::ModuleBuildContext & ctx, const core::TensorValue & lhs, const core::TensorValue & rhs) { |
| 258 | return modules::AddModule().build(ctx, lhs, rhs); |
no test coverage detected