001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005package org.jblas;
006
007import org.jblas.exceptions.LapackConvergenceException;
008
009import static org.jblas.util.Functions.min;
010
011/**
012 *
013 */
014public class Singular {
015
016    /**
017     * Compute a singular-value decomposition of A.
018     *
019     * @return A DoubleMatrix[3] array of U, S, V such that A = U * diag(S) * V'
020     */
021    public static DoubleMatrix[] fullSVD(DoubleMatrix A) {
022        int m = A.rows;
023        int n = A.columns;
024
025        DoubleMatrix U = new DoubleMatrix(m, m);
026        DoubleMatrix S = new DoubleMatrix(min(m, n));
027        DoubleMatrix V = new DoubleMatrix(n, n);
028
029        int info = NativeBlas.dgesvd('A', 'A', m, n, A.dup().data, 0, m, S.data, 0, U.data, 0, m, V.data, 0, n);
030
031        if (info > 0) {
032          throw new LapackConvergenceException("GESVD", info + " superdiagonals of an intermediate bidiagonal form failed to converge.");
033        }
034
035        return new DoubleMatrix[]{U, S, V.transpose()};
036    }
037
038    /**
039     * Compute a singular-value decomposition of A (sparse variant).
040     * Sparse means that the matrices U and V are not square but
041     * only have as many columns (or rows) as necessary.
042     * 
043     * @param A
044     * @return A DoubleMatrix[3] array of U, S, V such that A = U * diag(S) * V'
045     */
046    public static DoubleMatrix[] sparseSVD(DoubleMatrix A) {
047        int m = A.rows;
048        int n = A.columns;
049
050        DoubleMatrix U = new DoubleMatrix(m, min(m, n));
051        DoubleMatrix S = new DoubleMatrix(min(m, n));
052        DoubleMatrix V = new DoubleMatrix(min(m, n), n);
053
054        int info = NativeBlas.dgesvd('S', 'S', m, n, A.dup().data, 0, m, S.data, 0, U.data, 0, m, V.data, 0, min(m, n));
055
056        if (info > 0) {
057          throw new LapackConvergenceException("GESVD", info + " superdiagonals of an intermediate bidiagonal form failed to converge.");
058        }
059
060        return new DoubleMatrix[]{U, S, V.transpose()};
061    }
062
063  /**
064   * Compute a singular-value decomposition of A (sparse variant).
065   * Sparse means that the matrices U and V are not square but only have
066   * as many columns (or rows) as necessary.
067   *
068   * @param A
069   * @return A ComplexDoubleMatrix[3] array of U, S, V such that A = U * diag(S) * V*
070   */
071    public static ComplexDoubleMatrix[] sparseSVD(ComplexDoubleMatrix A) {
072        int m = A.rows;
073        int n = A.columns;
074
075        ComplexDoubleMatrix U = new ComplexDoubleMatrix(m, min(m, n));
076        DoubleMatrix S = new DoubleMatrix(min(m, n));
077        ComplexDoubleMatrix V = new ComplexDoubleMatrix(min(m, n), n);
078
079        double[] rwork = new double[5*min(m,n)];
080
081        int info = NativeBlas.zgesvd('S', 'S', m, n, A.dup().data, 0, m, S.data, 0, U.data, 0, m, V.data, 0, min(m, n), rwork, 0);
082
083        if (info > 0) {
084          throw new LapackConvergenceException("GESVD", info + " superdiagonals of an intermediate bidiagonal form failed to converge.");
085        }
086
087        return new ComplexDoubleMatrix[]{U, new ComplexDoubleMatrix(S), V.hermitian()};
088    }
089
090    /**
091     * Compute a singular-value decomposition of A.
092     *
093     * @return A ComplexDoubleMatrix[3] array of U, S, V such that A = U * diag(S) * V'
094     */
095    public static ComplexDoubleMatrix[] fullSVD(ComplexDoubleMatrix A) {
096      int m = A.rows;
097      int n = A.columns;
098
099      ComplexDoubleMatrix U = new ComplexDoubleMatrix(m, m);
100      DoubleMatrix S = new DoubleMatrix(min(m, n));
101      ComplexDoubleMatrix V = new ComplexDoubleMatrix(n, n);
102
103      double[] rwork = new double[5*min(m,n)];
104
105      int info = NativeBlas.zgesvd('A', 'A', m, n, A.dup().data, 0, m, S.data, 0, U.data, 0, m, V.data, 0, n, rwork, 0);
106
107      if (info > 0) {
108        throw new LapackConvergenceException("GESVD", info + " superdiagonals of an intermediate bidiagonal form failed to converge.");
109      }
110
111      return new ComplexDoubleMatrix[]{U, new ComplexDoubleMatrix(S), V.hermitian()};
112    }
113
114    /**
115     * Compute the singular values of a matrix.
116     *
117     * @param A DoubleMatrix of dimension m * n
118     * @return A min(m, n) vector of singular values.
119     */
120    public static DoubleMatrix SVDValues(DoubleMatrix A) {
121        int m = A.rows;
122        int n = A.columns;
123        DoubleMatrix S = new DoubleMatrix(min(m, n));
124
125        int info = NativeBlas.dgesvd('N', 'N', m, n, A.dup().data, 0, m, S.data, 0, null, 0, 1, null, 0, 1);
126
127        if (info > 0) {
128          throw new LapackConvergenceException("GESVD", info + " superdiagonals of an intermediate bidiagonal form failed to converge.");
129        }
130
131        return S;
132    }
133
134    /**
135     * Compute the singular values of a complex matrix.
136     *
137     * @param A ComplexDoubleMatrix of dimension m * n
138     * @return A real-valued (!) min(m, n) vector of singular values.
139     */
140    public static DoubleMatrix SVDValues(ComplexDoubleMatrix A) {
141        int m = A.rows;
142        int n = A.columns;
143        DoubleMatrix S = new DoubleMatrix(min(m, n));
144        double[] rwork = new double[5*min(m,n)];
145
146        int info = NativeBlas.zgesvd('N', 'N', m, n, A.dup().data, 0, m, S.data, 0, null, 0, 1, null, 0, min(m,n), rwork, 0);
147
148        if (info > 0) {
149          throw new LapackConvergenceException("GESVD", info + " superdiagonals of an intermediate bidiagonal form failed to converge.");
150        }
151
152        return S;
153    }
154
155    //BEGIN
156  // The code below has been automatically generated.
157  // DO NOT EDIT!
158
159    /**
160     * Compute a singular-value decomposition of A.
161     *
162     * @return A FloatMatrix[3] array of U, S, V such that A = U * diag(S) * V'
163     */
164    public static FloatMatrix[] fullSVD(FloatMatrix A) {
165        int m = A.rows;
166        int n = A.columns;
167
168        FloatMatrix U = new FloatMatrix(m, m);
169        FloatMatrix S = new FloatMatrix(min(m, n));
170        FloatMatrix V = new FloatMatrix(n, n);
171
172        int info = NativeBlas.sgesvd('A', 'A', m, n, A.dup().data, 0, m, S.data, 0, U.data, 0, m, V.data, 0, n);
173
174        if (info > 0) {
175          throw new LapackConvergenceException("GESVD", info + " superdiagonals of an intermediate bidiagonal form failed to converge.");
176        }
177
178        return new FloatMatrix[]{U, S, V.transpose()};
179    }
180
181    /**
182     * Compute a singular-value decomposition of A (sparse variant).
183     * Sparse means that the matrices U and V are not square but
184     * only have as many columns (or rows) as necessary.
185     * 
186     * @param A
187     * @return A FloatMatrix[3] array of U, S, V such that A = U * diag(S) * V'
188     */
189    public static FloatMatrix[] sparseSVD(FloatMatrix A) {
190        int m = A.rows;
191        int n = A.columns;
192
193        FloatMatrix U = new FloatMatrix(m, min(m, n));
194        FloatMatrix S = new FloatMatrix(min(m, n));
195        FloatMatrix V = new FloatMatrix(min(m, n), n);
196
197        int info = NativeBlas.sgesvd('S', 'S', m, n, A.dup().data, 0, m, S.data, 0, U.data, 0, m, V.data, 0, min(m, n));
198
199        if (info > 0) {
200          throw new LapackConvergenceException("GESVD", info + " superdiagonals of an intermediate bidiagonal form failed to converge.");
201        }
202
203        return new FloatMatrix[]{U, S, V.transpose()};
204    }
205
206  /**
207   * Compute a singular-value decomposition of A (sparse variant).
208   * Sparse means that the matrices U and V are not square but only have
209   * as many columns (or rows) as necessary.
210   *
211   * @param A
212   * @return A ComplexFloatMatrix[3] array of U, S, V such that A = U * diag(S) * V*
213   */
214    public static ComplexFloatMatrix[] sparseSVD(ComplexFloatMatrix A) {
215        int m = A.rows;
216        int n = A.columns;
217
218        ComplexFloatMatrix U = new ComplexFloatMatrix(m, min(m, n));
219        FloatMatrix S = new FloatMatrix(min(m, n));
220        ComplexFloatMatrix V = new ComplexFloatMatrix(min(m, n), n);
221
222        float[] rwork = new float[5*min(m,n)];
223
224        int info = NativeBlas.cgesvd('S', 'S', m, n, A.dup().data, 0, m, S.data, 0, U.data, 0, m, V.data, 0, min(m, n), rwork, 0);
225
226        if (info > 0) {
227          throw new LapackConvergenceException("GESVD", info + " superdiagonals of an intermediate bidiagonal form failed to converge.");
228        }
229
230        return new ComplexFloatMatrix[]{U, new ComplexFloatMatrix(S), V.hermitian()};
231    }
232
233    /**
234     * Compute a singular-value decomposition of A.
235     *
236     * @return A ComplexFloatMatrix[3] array of U, S, V such that A = U * diag(S) * V'
237     */
238    public static ComplexFloatMatrix[] fullSVD(ComplexFloatMatrix A) {
239      int m = A.rows;
240      int n = A.columns;
241
242      ComplexFloatMatrix U = new ComplexFloatMatrix(m, m);
243      FloatMatrix S = new FloatMatrix(min(m, n));
244      ComplexFloatMatrix V = new ComplexFloatMatrix(n, n);
245
246      float[] rwork = new float[5*min(m,n)];
247
248      int info = NativeBlas.cgesvd('A', 'A', m, n, A.dup().data, 0, m, S.data, 0, U.data, 0, m, V.data, 0, n, rwork, 0);
249
250      if (info > 0) {
251        throw new LapackConvergenceException("GESVD", info + " superdiagonals of an intermediate bidiagonal form failed to converge.");
252      }
253
254      return new ComplexFloatMatrix[]{U, new ComplexFloatMatrix(S), V.hermitian()};
255    }
256
257    /**
258     * Compute the singular values of a matrix.
259     *
260     * @param A FloatMatrix of dimension m * n
261     * @return A min(m, n) vector of singular values.
262     */
263    public static FloatMatrix SVDValues(FloatMatrix A) {
264        int m = A.rows;
265        int n = A.columns;
266        FloatMatrix S = new FloatMatrix(min(m, n));
267
268        int info = NativeBlas.sgesvd('N', 'N', m, n, A.dup().data, 0, m, S.data, 0, null, 0, 1, null, 0, 1);
269
270        if (info > 0) {
271          throw new LapackConvergenceException("GESVD", info + " superdiagonals of an intermediate bidiagonal form failed to converge.");
272        }
273
274        return S;
275    }
276
277    /**
278     * Compute the singular values of a complex matrix.
279     *
280     * @param A ComplexFloatMatrix of dimension m * n
281     * @return A real-valued (!) min(m, n) vector of singular values.
282     */
283    public static FloatMatrix SVDValues(ComplexFloatMatrix A) {
284        int m = A.rows;
285        int n = A.columns;
286        FloatMatrix S = new FloatMatrix(min(m, n));
287        float[] rwork = new float[5*min(m,n)];
288
289        int info = NativeBlas.cgesvd('N', 'N', m, n, A.dup().data, 0, m, S.data, 0, null, 0, 1, null, 0, min(m,n), rwork, 0);
290
291        if (info > 0) {
292          throw new LapackConvergenceException("GESVD", info + " superdiagonals of an intermediate bidiagonal form failed to converge.");
293        }
294
295        return S;
296    }
297
298    //END
299}