Householder reflection on the trailing elements of a vector. H = I - beta * [1, v]' * [1, v] H * x = [..., xnorm, 0, ..., 0] ..., j, j + 1, ..., n def house(x, j, eps): sigma = np.linalg.norm(x[(j + 1):]) v = np.zeros_like(x) v[(j + 1):] = x[(j + 1):] if sigma < eps: beta = 0 else: mu = sigma * np.sqrt((x[j]/sigma)**2 + 1) if x[j] <= 0: v[j] = x[j] - mu else: v[j] = -sigma / (x[j] + mu) * sigma
| 107 | // A[i, j:] * H = [sigma, 0, 0, ..., 0] |
| 108 | // |
| 109 | StatusOr<HouseHolderResult> HouseRow(XlaOp a, XlaOp i, XlaOp j, XlaOp eps, |
| 110 | PrecisionConfig::Precision precision) { |
| 111 | XlaBuilder* builder = a.builder(); |
| 112 | TF_ASSIGN_OR_RETURN(Shape a_shape, builder->GetShape(a)); |
| 113 | const int64 num_dims = a_shape.rank(); |
| 114 | const int64 n = ShapeUtil::GetDimension(a_shape, -1); |
| 115 | XlaOp zero = ScalarLike(i, 0); |
| 116 | XlaOp x = DynamicSliceInMinorDims(a, {i, zero}, {1, n}); |
| 117 | |
| 118 | const int64 num_batch_dims = num_dims - 2; |
| 119 | std::vector<int64> batch_dims(num_batch_dims); |
| 120 | for (int k = 0; k < num_batch_dims; ++k) { |
| 121 | batch_dims[k] = ShapeUtil::GetDimension(a_shape, k); |
| 122 | } |
| 123 | |
| 124 | TF_ASSIGN_OR_RETURN(Shape x_shape, builder->GetShape(x)); |
| 125 | auto idx = Iota(builder, ShapeUtil::MakeShape(S32, x_shape.dimensions()), |
| 126 | num_dims - 1); |
| 127 | auto zeros = ZerosLike(x); |
| 128 | auto v = Select(Gt(idx, j), x, zeros); |
| 129 | |
| 130 | auto one = ScalarLike(v, 1.0); |
| 131 | |
| 132 | auto sigma = |
| 133 | Sqrt(Reduce(Square(v), ScalarLike(v, 0.0), |
| 134 | CreateScalarAddComputation(x_shape.element_type(), builder), |
| 135 | {num_dims - 1})); |
| 136 | |
| 137 | std::vector<int64> broadcast_dims(num_dims - 1); |
| 138 | std::iota(broadcast_dims.begin(), broadcast_dims.end(), 0); |
| 139 | auto x_0j = DynamicSliceInMinorDims(x, {zero, j}, {1, 1}); |
| 140 | auto mu = Mul(sigma, Sqrt(Square(Div(x_0j, sigma, broadcast_dims)) + one), |
| 141 | broadcast_dims); |
| 142 | |
| 143 | auto v_0j = Select( |
| 144 | Le(x_0j, ScalarLike(x_0j, 0.0)), Sub(x_0j, mu), |
| 145 | -Mul(sigma, Div(sigma, Add(x_0j, mu), broadcast_dims), broadcast_dims)); |
| 146 | |
| 147 | auto beta = Div(ScalarLike(v_0j, 2.0), |
| 148 | (Square(Div(sigma, v_0j, broadcast_dims)) + one)); |
| 149 | |
| 150 | v = Select( |
| 151 | BroadcastInDim(Lt(sigma, eps), x_shape.dimensions(), broadcast_dims), v, |
| 152 | v / v_0j); |
| 153 | v = Select(Eq(idx, j), zeros + one, v); |
| 154 | |
| 155 | beta = Select(Lt(Add(sigma, ZerosLike(beta), broadcast_dims), eps), |
| 156 | ZerosLike(beta), beta); |
| 157 | |
| 158 | HouseHolderResult result; |
| 159 | result.v = v; |
| 160 | result.beta = beta; |
| 161 | result.a = Sub(a, Mul(beta, BatchDot(BatchDot(a, false, v, true, precision), |
| 162 | v, precision))); |
| 163 | |
| 164 | return result; |
| 165 | } |
| 166 |
nothing calls this directly
no test coverage detected