@@ -14,18 +14,40 @@ import breeze.macros.expand
1414 * Solving A^T (AX-B) = 0 for X yields
1515 * A^T AX = A^T B
1616 * => X = (A^T A)^(-1) A^T B
17+ *
18+ * @param v: Matrix to be pseudo-inverted
19+ * @param rcond: Cutoff for small singular values. Singular values less than or equal to rcond * largest_singular_value
20+ * are set to zero. Default: 1e-15. To deactivate this option, set rcond to zero.
1721 */
1822object pinv extends UFunc with pinvLowPrio {
1923
24+ private val DEFAULT_RCOND = 1e-15f
25+
2026 @ expand
2127 @ expand.valify
2228 implicit def pinvFromSVD [@ expand.args(Float , Double ) T ]: Impl [DenseMatrix [T ], DenseMatrix [T ]] = {
2329 new Impl [DenseMatrix [T ], DenseMatrix [T ]] {
24- // http://en.wikipedia.org/wiki/Singular_value_decomposition#Applications_of_the_SVD
30+ // No rcond passed as parameter, use default value
2531 override def apply (v : DenseMatrix [T ]): DenseMatrix [T ] = {
32+ val rcond : T = DEFAULT_RCOND
33+ pinv(v, rcond)
34+ }
35+ }
36+ }
37+
38+
39+ @ expand
40+ @ expand.valify
41+ implicit def pinvFromSVDRcond [@ expand.args(Float , Double ) T ]: Impl2 [DenseMatrix [T ], T , DenseMatrix [T ]] = {
42+ new Impl2 [DenseMatrix [T ], T , DenseMatrix [T ]] {
43+ // http://en.wikipedia.org/wiki/Singular_value_decomposition#Applications_of_the_SVD
44+ override def apply (v : DenseMatrix [T ], rcond : T ): DenseMatrix [T ] = {
45+ require(rcond >= 0 , " rcond must be non-negative" )
46+
2647 val svd .SVD (s, svs, d) = svd(v)
48+ val cutoff = max(svs) * rcond
2749 val vi = svs.map { v =>
28- if (v == 0.0 ) 0 else 1 / v
50+ if (v <= cutoff ) 0 else 1 / v
2951 }
3052
3153 val svDiag = DenseMatrix .tabulate[T ](s.cols, d.rows) { (i, j) =>
@@ -58,12 +80,12 @@ trait pinvLowPrio { self: pinv.type =>
5880 * @return
5981 */
6082 implicit def implFromTransposeAndSolve [T , TransT , MulRes , Result ](
61- implicit numericT : T => NumericOps [T ],
62- trans : CanTranspose [T , TransT ],
63- numericTrans : TransT => NumericOps [TransT ],
64- mul : OpMulMatrix .Impl2 [TransT , T , MulRes ],
65- numericMulRes : MulRes => NumericOps [MulRes ],
66- solve : OpSolveMatrixBy .Impl2 [MulRes , TransT , Result ]): Impl [T , Result ] = {
83+ implicit numericT : T => NumericOps [T ],
84+ trans : CanTranspose [T , TransT ],
85+ numericTrans : TransT => NumericOps [TransT ],
86+ mul : OpMulMatrix .Impl2 [TransT , T , MulRes ],
87+ numericMulRes : MulRes => NumericOps [MulRes ],
88+ solve : OpSolveMatrixBy .Impl2 [MulRes , TransT , Result ]): Impl [T , Result ] = {
6789 new Impl [T , Result ] {
6890 def apply (X : T ): Result = {
6991 (X .t * X ) \ X .t
0 commit comments