diff --git a/src/common_fc.cpp b/src/common_fc.cpp
index 470e8a4e59b4419678cbd30bb048977a8c0059ae..16b4ecd4667c5b35d1a61e4b860c5845e64f78b8 100644
--- a/src/common_fc.cpp
+++ b/src/common_fc.cpp
@@ -8,10 +8,51 @@ CCommon_Fc::~CCommon_Fc(){}
 
 Eigen::MatrixXd CCommon_Fc::CalcPinv(const Eigen::MatrixXd& a, double epsilon)
 {
-  Eigen::JacobiSVD<Eigen::MatrixXd> svdd(a, Eigen::ComputeThinU | Eigen::ComputeThinV);
-  double tolerance = epsilon * std::max(a.cols(), a.rows()) *svdd.singularValues().array().abs()(0);
-  Eigen::MatrixXd mpinv = svdd.matrixV() *  (svdd.singularValues().array().abs() > tolerance).select(svdd.singularValues().array().inverse(), 0).matrix().asDiagonal() * svdd.matrixU().adjoint();
-  return mpinv;
+  // Eigen::JacobiSVD<Eigen::MatrixXd> svdd(a, Eigen::ComputeThinU | Eigen::ComputeThinV);
+  // double tolerance = epsilon * std::max(a.cols(), a.rows()) *svdd.singularValues().array().abs()(0);
+  // Eigen::MatrixXd mpinv = svdd.matrixV() *  (svdd.singularValues().array().abs() > tolerance).select(svdd.singularValues().array().inverse(), 0).matrix().asDiagonal() * svdd.matrixU().adjoint();
+  // return mpinv;
+
+// see : http://en.wikipedia.org/wiki/Moore-Penrose_pseudoinverse#The_general_case_and_the_SVD_method
+
+const Eigen::MatrixXd* m;
+Eigen::MatrixXd t;
+Eigen::MatrixXd m_pinv;
+
+// transpose so SVD decomp can work...
+if ( a.rows()<a.cols() )
+{
+  t = a.transpose();
+  m = &t;
+} 
+else 
+  m = &a;
+
+// SVD
+//JacobiSVD<Eigen::MatrixXd> svd = m->jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV);
+Eigen::JacobiSVD<Eigen::MatrixXd> svd = m->jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV);
+Eigen::MatrixXd vSingular = svd.singularValues();
+// Build a diagonal matrix with the Inverted Singular values
+// The pseudo inverted singular matrix is easy to compute :
+// is formed by replacing every nonzero entry by its reciprocal (inversing).
+Eigen::MatrixXd vPseudoInvertedSingular(svd.matrixV().cols(),1);
+for (int iRow =0; iRow<vSingular.rows(); iRow++) 
+{
+  if ( fabs(vSingular(iRow))<=epsilon )
+    vPseudoInvertedSingular(iRow,0)=0.;
+  else 
+    vPseudoInvertedSingular(iRow,0)=1./vSingular(iRow);
+}
+// A little optimization here
+Eigen::MatrixXd mAdjointU = svd.matrixU().adjoint().block(0,0,vSingular.rows(),svd.matrixU().adjoint().cols());
+// Pseudo-Inversion : V * S * U'
+m_pinv = (svd.matrixV() *  vPseudoInvertedSingular.asDiagonal()) * mAdjointU  ;
+
+// transpose back if necessary
+if ( a.rows()<a.cols() )
+  return m_pinv.transpose();
+
+return m_pinv;
 }