#include "../node_context.h" #include "../op_table.h" #include "../utils.h" #include #include #include #include #include #include namespace ov { namespace frontend { namespace ggml { namespace op { // GGML DIAG takes a 1D vector (ne0, 1, ne2, ne3) and produces a diagonal matrix // of shape (ne0, ne0, ne2, ne3). // In OV layout (ggml [ne0, ne1, ne2, ne3] → OV [ne3, ne2, ne1, ne0]): // input: [ne3, ne2, 1, ne0] // output: [ne3, ne2, ne0, ne0] // The diagonal: output[..., i, j] = input[..., 0, j] if i == j, else 0. OutputVector translate_diag(const NodeContext & context) { num_inputs_check(context, 1, 1); auto x = context.get_input(0); // OV shape: [ne3, ne2, 1, ne0] auto out_shape = context.get_output_shape().to_shape(); int64_t n = static_cast(out_shape[3]); // ne0 // Build index range [0, 1, ..., n-1] auto start = ov::op::v0::Constant::create(ov::element::i64, {}, {int64_t(0)}); auto stop = ov::op::v0::Constant::create(ov::element::i64, {}, {n}); auto step = ov::op::v0::Constant::create(ov::element::i64, {}, {int64_t(1)}); auto range = std::make_shared(start, stop, step, ov::element::i64); // col_idx shape [1, 1, 1, n] auto col_shape = ov::op::v0::Constant::create(ov::element::i64, {4}, std::vector{1, 1, 1, n}); auto col_idx = std::make_shared(range, col_shape, false); // row_idx shape [1, 1, n, 1] auto row_shape = ov::op::v0::Constant::create(ov::element::i64, {4}, std::vector{1, 1, n, 1}); auto row_idx = std::make_shared(range, row_shape, false); // mask: true where col == row (diagonal) auto mask = std::make_shared(col_idx, row_idx); // Broadcast input from [ne3, ne2, 1, ne0] to [ne3, ne2, ne0, ne0] via select auto zero = ov::op::v0::Constant::create(ov::element::f32, {}, {0.0f}); auto res = std::make_shared(mask, x, zero); return rename_outputs_with_suffix({res}, context.get_name()); } } // namespace op } // namespace ggml } // namespace frontend } // namespace ov