bool pinv_damped(const MatrixD &A, MatrixD *invA, Scalar lambda_max, Scalar eps) {

  //A (m x n) usually comes from a redundant task jacobian, therfore we consider m<n
  int m = A.rows() - 1;
  VectorD sigma;  //vector of singular values
  Scalar lambda2;
  int r = 0;

  JacobiSVD<MatrixD> svd_A(A.transpose(), ComputeThinU | ComputeThinV);
  sigma = svd_A.singularValues();
  if (((m > 0) && (sigma(m) > eps)) || ((m == 0) && (A.array().abs() > eps).any())) {
    for (int i = 0; i <= m; i++) {
      sigma(i) = 1.0 / sigma(i);
    }
    (*invA) = svd_A.matrixU() * sigma.asDiagonal() * svd_A.matrixV().transpose();
    return true;
  } else {
    lambda2 = (1 - (sigma(m) / eps) * (sigma(m) / eps)) * lambda_max * lambda_max;
    for (int i = 0; i <= m; i++) {
      if (sigma(i) > EPSQ)
        r++;
      sigma(i) = (sigma(i) / (sigma(i) * sigma(i) + lambda2));
    }
    //only U till the rank
    MatrixD subU = svd_A.matrixU().block(0, 0, A.cols(), r);
    MatrixD subV = svd_A.matrixV().block(0, 0, A.rows(), r);

    (*invA) = subU * sigma.asDiagonal() * subV.transpose();
    return false;
  }

}
bool pinv_QR_Z(const MatrixD &A, const MatrixD &Z0, MatrixD *invA, MatrixD *Z, Scalar lambda_max, Scalar eps) {
  VectorD sigma;  //vector of singular values
  Scalar lambda2;

  MatrixD AZ0t = (A * Z0).transpose();
  HouseholderQR < MatrixD > qr = AZ0t.householderQr();

  int m = A.rows();
  int p = Z0.cols();

  MatrixD Rt = MatrixD::Zero(m, m);
  bool invertible;
  MatrixD hR = (MatrixD) qr.matrixQR();
  MatrixD Y = ((MatrixD) qr.householderQ()).leftCols(m);

  //take the useful part of R
  for (int i = 0; i < m; i++) {
    for (int j = 0; j <= i; j++)
      Rt(i, j) = hR(j, i);
  }

  FullPivLU < MatrixD > invRt(Rt);
  invertible = fabs(invRt.determinant()) > eps;

  if (invertible) {
    *invA = Z0 * Y * invRt.inverse();
    *Z = Z0 * (((MatrixD) qr.householderQ()).rightCols(p - m));
    return true;
  } else {
    MatrixD R = MatrixD::Zero(m, m);
    //take the useful part of R
    for (int i = 0; i < m; i++) {
      for (int j = i; j < m; j++)  // TODO: is starting at i correct?
        R(i, j) = hR(i, j);
    }

    //perform the SVD of R
    JacobiSVD<MatrixD> svd_R(R, ComputeThinU | ComputeThinV);
    sigma = svd_R.singularValues();
    lambda2 = (1 - (sigma(m - 1) / eps) * (sigma(m - 1) / eps)) * lambda_max * lambda_max;
    for (int i = 0; i < m; i++) {
      sigma(i) = sigma(i) / (sigma(i) * sigma(i) + lambda2);
    }
    (*invA) = Z0 * Y * svd_R.matrixU() * sigma.asDiagonal() * svd_R.matrixV().transpose();

    *Z = Z0 * (((MatrixD) qr.householderQ()).rightCols(p - m));
    return false;
  }

}
bool pinv(const MatrixD &A, MatrixD *invA, Scalar eps) {

  //A (m x n) usually comes from a redundant task jacobian, therfore we consider m<n
  int m = A.rows() - 1;
  VectorD sigma;  //vector of singular values

  JacobiSVD<MatrixD> svd_A(A.transpose(), ComputeThinU | ComputeThinV);
  sigma = svd_A.singularValues();
  if (((m > 0) && (sigma(m) > eps)) || ((m == 0) && (A.array().abs() > eps).any())) {
    for (int i = 0; i <= m; i++) {
      sigma(i) = 1.0 / sigma(i);
    }
    (*invA) = svd_A.matrixU() * sigma.asDiagonal() * svd_A.matrixV().transpose();
    return true;
  } else {
    return false;
  }
}