/** {@inheritDoc} */
  public RealMatrix getU() throws InvalidMatrixException {

    if (cachedU == null) {

      if (m >= n) {
        // the tridiagonal matrix is Bt.B, where B is upper bidiagonal
        final double[][] eData = eigenDecomposition.getV().getData();
        final double[][] iData = new double[m][];
        double[] ei1 = eData[0];
        iData[0] = ei1;
        for (int i = 0; i < n - 1; ++i) {
          // compute B.E.S^(-1) where E is the eigenvectors matrix
          // we reuse the array from matrix E to store the result
          final double mi = mainBidiagonal[i];
          final double si = secondaryBidiagonal[i];
          final double[] ei0 = ei1;
          ei1 = eData[i + 1];
          iData[i + 1] = ei1;
          for (int j = 0; j < n; ++j) {
            ei0[j] = (mi * ei0[j] + si * ei1[j]) / singularValues[j];
          }
        }
        // last row
        final double lastMain = mainBidiagonal[n - 1];
        for (int j = 0; j < n; ++j) {
          ei1[j] *= lastMain / singularValues[j];
        }
        for (int i = n; i < m; ++i) {
          iData[i] = new double[n];
        }
        cachedU = transformer.getU().multiply(MatrixUtils.createRealMatrix(iData));
      } else {
        // the tridiagonal matrix is B.Bt, where B is lower bidiagonal
        cachedU = transformer.getU().multiply(eigenDecomposition.getV());
      }
    }

    // return the cached matrix
    return cachedU;
  }