void Householder<T>::evalHHmatrixData(const NDArray<T>& x, NDArray<T>& tail, T& coeff, T& normX) { // input validation if(!x.isVector() && !x.isScalar()) throw "ops::helpers::Householder::evalHHmatrixData method: input array must be vector or scalar!"; if(!x.isScalar() && x.lengthOf() != tail.lengthOf() + 1) throw "ops::helpers::Householder::evalHHmatrixData method: input tail vector must have length less than unity compared to input x vector!"; normX = x.template reduceNumber<simdOps::Norm2<T>>(); const T min = DataTypeUtils::min<T>(); if(normX*normX - x(0)*x(0) <= min) { normX = x(0); coeff = (T)0.; tail = (T)0.; } else { if(x(0) >= (T)0.) normX = -normX; // choose opposite sign to lessen roundoff error T u0 = x(0) - normX; coeff = -u0 / normX; if(x.isRowVector()) tail.assign(x({{}, {1, -1}}) / u0); else tail.assign(x({{1, -1}, {}}) / u0); } }
NDArray<T> Householder<T>::evalHHmatrix(const NDArray<T>& x) { // input validation if(!x.isVector() && !x.isScalar()) throw "ops::helpers::Householder::evalHHmatrix method: input array must be vector or scalar!"; NDArray<T> w((int)x.lengthOf(), 1, x.ordering(), x.getWorkspace()); // column-vector NDArray<T> wT(1, (int)x.lengthOf(), x.ordering(), x.getWorkspace()); // row-vector (transposed w) T coeff; T normX = x.template reduceNumber<simdOps::Norm2<T>>(); const T min = DataTypeUtils::min<T>(); if(normX*normX - x(0)*x(0) <= min) { normX = x(0); coeff = (T)0.; w = (T)0.; } else { if(x(0) >= (T)0.) normX = -normX; // choose opposite sign to lessen roundoff error T u0 = x(0) - normX; coeff = -u0 / normX; w.assign(x / u0); } w(0) = (T)1.; wT.assign(&w); NDArray<T> identity((int)x.lengthOf(), (int)x.lengthOf(), x.ordering(), x.getWorkspace()); identity.setIdentity(); // identity matrix return identity - mmul(w, wT) * coeff; }