protected void computeU( int k) {
        u.reshape(m,1, false);
        double u[] = this.u.data;

        // find the largest value in this column
        // this is used to normalize the column and mitigate overflow/underflow
        double max = 0;

        for( int i = k; i < m; i++ ) {
            // copy the householder vector to vector outside of the matrix to reduce caching issues
            // big improvement on larger matrices and a relatively small performance hit on small matrices.
            double val = u[i] = B.get(i,k);
            val = Math.abs(val);
            if( val > max )
                max = val;
        }

        if( max > 0 ) {
            // -------- set up the reflector Q_k

            double tau = 0;
            // normalize to reduce overflow/underflow
            // and compute tau for the reflector
            for( int i = k; i < m; i++ ) {
                double val = u[i] /= max;
                tau += val*val;
            }

            tau = Math.sqrt(tau);

            if( u[k] < 0 )
                tau = -tau;

            // write the reflector into the lower left column of the matrix
            double nu = u[k] + tau;
            u[k] = 1.0;

            for( int i = k+1; i < m; i++ ) {
                u[i] /= nu;
            }

            SimpleMatrix Q_k = SimpleMatrix.wrap(SpecializedOps.createReflector(this.u,nu/tau));
            U = U.mult(Q_k);
            B = Q_k.mult(B);
        }
    }