Create a diagonal / batch diagonal matrix with 'input' on the diagonal.
| 31 | |
| 32 | // Create a diagonal / batch diagonal matrix with 'input' on the diagonal. |
| 33 | xla::XlaOp CreateDiagonal(xla::XlaOp input, int64 last_dim_size, |
| 34 | absl::Span<const int64> other_dims) { |
| 35 | xla::XlaBuilder* builder = input.builder(); |
| 36 | // Create two matrices that have the following forms, and compare them: |
| 37 | // |
| 38 | // [[0, 0, 0, 0] [[0, 1, 2, 3] |
| 39 | // [1, 1, 1, 1] [0, 1, 2, 3] |
| 40 | // [2, 2, 2, 2] [0, 1, 2, 3] |
| 41 | // [3, 3, 3, 3]] [0, 1, 2, 3]] |
| 42 | // |
| 43 | // This produces a predicate matrix of the right size, with "true" on the |
| 44 | // diagonal. |
| 45 | xla::XlaOp iota = xla::Iota(builder, xla::S32, last_dim_size); |
| 46 | xla::XlaOp iota_broadcast = xla::Broadcast(iota, {last_dim_size}); |
| 47 | xla::XlaOp mask = xla::Eq(iota_broadcast, iota, {0}); |
| 48 | |
| 49 | // If this is a batched diagonal, broadcast the mask across the other |
| 50 | // dimensions. |
| 51 | if (!other_dims.empty()) { |
| 52 | mask = xla::Broadcast(mask, other_dims); |
| 53 | } |
| 54 | |
| 55 | // Broadcast the input, and then use the mask computed above to select the |
| 56 | // diagonal: |
| 57 | // e.g, in 2D: |
| 58 | // [[t, f, f] [[1, 1, 1] [[0, 0, 0] [[1, 0, 0] |
| 59 | // select( [f, t, f] , [4, 4, 4] , [0, 0, 0] ) = [0, 4, 0] |
| 60 | // [f, f, t]] [9, 9, 9]] [0, 0, 0]] [0, 0, 9]] |
| 61 | // |
| 62 | std::vector<int64> out_dim_sizes(other_dims.begin(), other_dims.end()); |
| 63 | out_dim_sizes.push_back(last_dim_size); |
| 64 | out_dim_sizes.push_back(last_dim_size); |
| 65 | |
| 66 | // Broadcast into the second to last dimension. |
| 67 | std::vector<int64> broadcast_dimensions(other_dims.size() + 1); |
| 68 | absl::c_iota(broadcast_dimensions, 0); |
| 69 | ++broadcast_dimensions.back(); |
| 70 | xla::XlaOp input_broadcast = |
| 71 | xla::BroadcastInDim(input, out_dim_sizes, broadcast_dimensions); |
| 72 | return xla::Select(mask, input_broadcast, xla::ZerosLike(input_broadcast)); |
| 73 | } |
| 74 | |
| 75 | class DiagOp : public XlaOpKernel { |
| 76 | public: |
no test coverage detected