| 59 | OP_REQUIRES_OK(ctx, ctx->GetAttr("full_matrices", &full_matrices_)); |
| 60 | } |
| 61 | void Compile(XlaOpKernelContext* ctx) override { |
| 62 | const TensorShape input_shape = ctx->InputShape("input"); |
| 63 | int m = input_shape.dim_size(input_shape.dims() - 2); |
| 64 | int n = input_shape.dim_size(input_shape.dims() - 1); |
| 65 | // This is based on heuristics that approx log(n) sweep updates are needed. |
| 66 | // Note: the heuristics provides no theoretical guarantee, max_iter=100 and |
| 67 | // epsilon should be used to determine exit condition. |
| 68 | int max_iter = 2 * tensorflow::Log2Ceiling(std::max(m, n)); |
| 69 | auto result = xla::SVD(ctx->Input(0), max_iter, 1e-6); |
| 70 | ctx->SetOutput(0, result.d); |
| 71 | if (compute_uv_) { |
| 72 | int p = std::min(m, n); |
| 73 | if (!full_matrices_) { |
| 74 | if (p < m) { |
| 75 | result.u = xla::SliceInMinorDims(result.u, {0, 0}, {m, p}); |
| 76 | } |
| 77 | if (p < n) { |
| 78 | result.v = xla::SliceInMinorDims(result.v, {0, 0}, {n, p}); |
| 79 | } |
| 80 | } |
| 81 | ctx->SetOutput(1, result.u); |
| 82 | ctx->SetOutput(2, result.v); |
| 83 | } else { |
| 84 | ctx->SetOutput(1, xla::ScalarLike(ctx->Input(0), 0.0)); |
| 85 | ctx->SetOutput(2, xla::ScalarLike(ctx->Input(0), 0.0)); |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | private: |
| 90 | bool compute_uv_; |
nothing calls this directly
no test coverage detected