/// /// This file is part of ILNumerics Community Edition. /// /// ILNumerics Community Edition - high performance computing for applications. /// Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net /// /// ILNumerics Community Edition is free software: you can redistribute it and/or modify /// it under the terms of the GNU General Public License version 3 as published by /// the Free Software Foundation. /// /// ILNumerics Community Edition is distributed in the hope that it will be useful, /// but WITHOUT ANY WARRANTY; without even the implied warranty of /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /// GNU General Public License for more details. /// /// You should have received a copy of the GNU General Public License /// along with ILNumerics Community Edition. See the file License.txt in the root /// of your distribution package. If not, see . /// /// In addition this software uses the following components and/or licenses: /// /// ================================================================================= /// The Open Toolkit Library License /// /// Copyright (c) 2006 - 2009 the Open Toolkit library. /// /// Permission is hereby granted, free of charge, to any person obtaining a copy /// of this software and associated documentation files (the "Software"), to deal /// in the Software without restriction, including without limitation the rights to /// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of /// the Software, and to permit persons to whom the Software is furnished to do /// so, subject to the following conditions: /// /// The above copyright notice and this permission notice shall be included in all /// copies or substantial portions of the Software. /// /// ================================================================================= /// using System; using System.Collections.Generic; using System.Text; using ILNumerics.Storage; using ILNumerics.Misc; using ILNumerics.Exceptions; namespace ILNumerics { public partial class ILMath { /// /// Singular value decomposition /// /// Input matrix A /// Vector with min(M,N) singular values of A as column vector public static ILRetArray< double > svd(ILInArray< double > A) { return svd(A,null, null, false, false); } #region HYCALPER AUTO GENERATED CODE /// /// Singular value decomposition /// /// Input matrix A /// Vector with min(M,N) singular values of A as column vector public static ILRetArray< float > svd(ILInArray< float > A) { return svd(A,null, null, false, false); } /// /// Singular value decomposition /// /// Input matrix A /// Vector with min(M,N) singular values of A as column vector public static ILRetArray< float > svd(ILInArray< fcomplex > A) { return svd(A,null, null, false, false); } /// /// Singular value decomposition /// /// Input matrix A /// Vector with min(M,N) singular values of A as column vector public static ILRetArray< double > svd(ILInArray< complex > A) { return svd(A,null, null, false, false); } #endregion HYCALPER AUTO GENERATED CODE /// /// Singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix U. /// Setting this parameter to a non-null value signals the need of returning those values. /// Singluar values as diagonal matrix of same size and type as A public static ILRetArray< double > svd(ILInArray< double > A, ILOutArray< double > U) { return svd(A, U, null , false,false); } #region HYCALPER AUTO GENERATED CODE /// /// Singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix U. /// Setting this parameter to a non-null value signals the need of returning those values. /// Singluar values as diagonal matrix of same size and type as A public static ILRetArray< float > svd(ILInArray< float > A, ILOutArray< float > U) { return svd(A, U, null , false,false); } /// /// Singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix U. /// Setting this parameter to a non-null value signals the need of returning those values. /// Singluar values as diagonal matrix of same size and type as A public static ILRetArray< float > svd(ILInArray< fcomplex > A, ILOutArray< fcomplex > U) { return svd(A, U, null , false,false); } /// /// Singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix U. /// Setting this parameter to a non-null value signals the need of returning those values. /// Singluar values as diagonal matrix of same size and type as A public static ILRetArray< double > svd(ILInArray< complex > A, ILOutArray< complex > U) { return svd(A, U, null , false,false); } #endregion HYCALPER AUTO GENERATED CODE /// /// Singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix outU. /// Setting this parameter to a non-null value (e.g. 'empty') signals the need of returning those values. /// If true: return only first min(M,N) columns of outU will be /// of size [min(M,N),min(M,N)] /// Singluar values as diagonal matrix of same size and type as A public static ILRetArray< double > svd(ILInArray< double > A, ILOutArray< double > outU, bool small) { return svd(A, outU, null, small,false); } #region HYCALPER AUTO GENERATED CODE /// /// Singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix outU. /// Setting this parameter to a non-null value (e.g. 'empty') signals the need of returning those values. /// If true: return only first min(M,N) columns of outU will be /// of size [min(M,N),min(M,N)] /// Singluar values as diagonal matrix of same size and type as A public static ILRetArray< float > svd(ILInArray< float > A, ILOutArray< float > outU, bool small) { return svd(A, outU, null, small,false); } /// /// Singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix outU. /// Setting this parameter to a non-null value (e.g. 'empty') signals the need of returning those values. /// If true: return only first min(M,N) columns of outU will be /// of size [min(M,N),min(M,N)] /// Singluar values as diagonal matrix of same size and type as A public static ILRetArray< float > svd(ILInArray< fcomplex > A, ILOutArray< fcomplex > outU, bool small) { return svd(A, outU, null, small,false); } /// /// Singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix outU. /// Setting this parameter to a non-null value (e.g. 'empty') signals the need of returning those values. /// If true: return only first min(M,N) columns of outU will be /// of size [min(M,N),min(M,N)] /// Singluar values as diagonal matrix of same size and type as A public static ILRetArray< double > svd(ILInArray< complex > A, ILOutArray< complex > outU, bool small) { return svd(A, outU, null, small,false); } #endregion HYCALPER AUTO GENERATED CODE /// /// Singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix U. /// Setting this parameter to a non-null value signals the need of returning those values. /// [Output] Right singular vectors of X as rows of matrix V. /// This parameter must not be null. It might be an empty array on input. /// Singluar values as diagonal matrix of same size and type as A public static ILRetArray< double > svd(ILInArray< double > A, ILOutArray< double > outU, ILOutArray< double > outV) { return svd(A, outU, outV, false,false); } #region HYCALPER AUTO GENERATED CODE /// /// Singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix U. /// Setting this parameter to a non-null value signals the need of returning those values. /// [Output] Right singular vectors of X as rows of matrix V. /// This parameter must not be null. It might be an empty array on input. /// Singluar values as diagonal matrix of same size and type as A public static ILRetArray< float > svd(ILInArray< float > A, ILOutArray< float > outU, ILOutArray< float > outV) { return svd(A, outU, outV, false,false); } /// /// Singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix U. /// Setting this parameter to a non-null value signals the need of returning those values. /// [Output] Right singular vectors of X as rows of matrix V. /// This parameter must not be null. It might be an empty array on input. /// Singluar values as diagonal matrix of same size and type as A public static ILRetArray< float > svd(ILInArray< fcomplex > A, ILOutArray< fcomplex > outU, ILOutArray< fcomplex > outV) { return svd(A, outU, outV, false,false); } /// /// Singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix U. /// Setting this parameter to a non-null value signals the need of returning those values. /// [Output] Right singular vectors of X as rows of matrix V. /// This parameter must not be null. It might be an empty array on input. /// Singluar values as diagonal matrix of same size and type as A public static ILRetArray< double > svd(ILInArray< complex > A, ILOutArray< complex > outU, ILOutArray< complex > outV) { return svd(A, outU, outV, false,false); } #endregion HYCALPER AUTO GENERATED CODE /// /// singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix outU. /// Setting this parameter to a non-null value signals the need of returning those values. /// [Output] Right singular vectors of X as rows of matrix outV. /// This parameter must not be null. It might be an empty array on input. /// If true: return only first min(M,N) columns of outU and S (returned) will be /// of size [min(M,N),min(M,N)] /// If true: the matrix given will not be checked for infinte or NaN values. If such elements /// exist nevertheless, this may result in failing convergence or error. In worst case /// the function may hang inside the Lapack lib! Use with care! /// Singular values as diagonal matrix of same size and type as A public static ILRetArray< double> svd( ILInArray< double> A, ILOutArray< double> outU, ILOutArray< double> outV, bool small, bool discardFiniteTest ) { if (object.Equals(A,null)) throw new ILArgumentException("input matrix X must not be null"); using (ILScope.Enter(A)) { if (!A.IsMatrix) throw new ILArgumentSizeException("svd is defined for matrices only"); // early exit for small matrices if (A.Size[1] < 4 && A.Size[0] == A.Size[1]) { switch (A.Size[0]) { case 1: if (!Object.Equals(outU, null)) outU.a = ( double)1.0; if (!Object.Equals(outV, null)) outV.a = ( double)1.0; return abs(A); //case 2: // return -1; //case 3: // return -1; } } if (!discardFiniteTest && !allall(isfinite(A))) throw new ILArgumentException("svd: input must have only finite elements"); if (Lapack == null) throw new ILMathException("no Lapack package available"); // parameter evaluation int M = A.Size[0]; int N = A.Size[1]; int minMN = (M < N) ? M : N; int LDU = M; int LDVT = N; int LDA = M, lenDU = 0, lenVT = 0; double[] dS = ILMemoryPool.Pool.New< double>(minMN); char jobz = (small) ? 'S' : 'A'; double[] dU = null; double[] dVT = null; int info = 0; if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) { // need to return U and VT if (small) { lenDU = M * minMN; dU = ILMemoryPool.Pool.New< double>(lenDU); lenVT = N * minMN; dVT = ILMemoryPool.Pool.New< double>(lenVT); } else { lenDU = M * M; dU = ILMemoryPool.Pool.New< double>(lenDU); lenVT = N * N; dVT = ILMemoryPool.Pool.New< double>(lenVT); } } else { jobz = 'N'; } // must create copy of input ! double[] dInput = A.C.GetArrayForWrite(); /*!HC:lapack_dgesdd*/ Lapack.dgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info); if (info < 0) throw new ILArgumentException("the " + (-info).ToString() + "th argument to SVD was invalid"); if (info > 0) throw new ILArgumentException("svd was not converging"); ILArray< double> ret = empty(ILSize.Empty00); if (info == 0) { // success if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) { if (small) { ret.a = zeros< double>(new ILSize(minMN, minMN)); } else { ret.a = zeros< double>(new ILSize(M, N)); } for (int i = 0; i < minMN; i++) { ret.SetValue(dS[i], i, i); } ILMemoryPool.Pool.Free(dS); if (!Object.Equals(outU, null)) { outU.a = array< double>(dU, M, lenDU / M); } else { ILMemoryPool.Pool.Free(dU); } if (!Object.Equals(outV, null)) { outV.a = array< double>(dVT, N, lenVT / N).T; } else { ILMemoryPool.Pool.Free(dVT); } } else { ret.a = array< double>(dS,minMN, 1); } } return ret; } } #region HYCALPER AUTO GENERATED CODE /// /// singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix outU. /// Setting this parameter to a non-null value signals the need of returning those values. /// [Output] Right singular vectors of X as rows of matrix outV. /// This parameter must not be null. It might be an empty array on input. /// If true: return only first min(M,N) columns of outU and S (returned) will be /// of size [min(M,N),min(M,N)] /// If true: the matrix given will not be checked for infinte or NaN values. If such elements /// exist nevertheless, this may result in failing convergence or error. In worst case /// the function may hang inside the Lapack lib! Use with care! /// Singular values as diagonal matrix of same size and type as A public static ILRetArray< float> svd( ILInArray< float> A, ILOutArray< float> outU, ILOutArray< float> outV, bool small, bool discardFiniteTest ) { if (object.Equals(A,null)) throw new ILArgumentException("input matrix X must not be null"); using (ILScope.Enter(A)) { if (!A.IsMatrix) throw new ILArgumentSizeException("svd is defined for matrices only"); // early exit for small matrices if (A.Size[1] < 4 && A.Size[0] == A.Size[1]) { switch (A.Size[0]) { case 1: if (!Object.Equals(outU, null)) outU.a = ( float)1.0; if (!Object.Equals(outV, null)) outV.a = ( float)1.0; return abs(A); //case 2: // return -1; //case 3: // return -1; } } if (!discardFiniteTest && !allall(isfinite(A))) throw new ILArgumentException("svd: input must have only finite elements"); if (Lapack == null) throw new ILMathException("no Lapack package available"); // parameter evaluation int M = A.Size[0]; int N = A.Size[1]; int minMN = (M < N) ? M : N; int LDU = M; int LDVT = N; int LDA = M, lenDU = 0, lenVT = 0; float[] dS = ILMemoryPool.Pool.New< float>(minMN); char jobz = (small) ? 'S' : 'A'; float[] dU = null; float[] dVT = null; int info = 0; if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) { // need to return U and VT if (small) { lenDU = M * minMN; dU = ILMemoryPool.Pool.New< float>(lenDU); lenVT = N * minMN; dVT = ILMemoryPool.Pool.New< float>(lenVT); } else { lenDU = M * M; dU = ILMemoryPool.Pool.New< float>(lenDU); lenVT = N * N; dVT = ILMemoryPool.Pool.New< float>(lenVT); } } else { jobz = 'N'; } // must create copy of input ! float[] dInput = A.C.GetArrayForWrite(); Lapack.sgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info); if (info < 0) throw new ILArgumentException("the " + (-info).ToString() + "th argument to SVD was invalid"); if (info > 0) throw new ILArgumentException("svd was not converging"); ILArray< float> ret = empty(ILSize.Empty00); if (info == 0) { // success if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) { if (small) { ret.a = zeros< float>(new ILSize(minMN, minMN)); } else { ret.a = zeros< float>(new ILSize(M, N)); } for (int i = 0; i < minMN; i++) { ret.SetValue(dS[i], i, i); } ILMemoryPool.Pool.Free(dS); if (!Object.Equals(outU, null)) { outU.a = array< float>(dU, M, lenDU / M); } else { ILMemoryPool.Pool.Free(dU); } if (!Object.Equals(outV, null)) { outV.a = new ILRetArray (dVT,N,lenVT / N).T; } else { ILMemoryPool.Pool.Free(dVT); } } else { ret.a = array< float>(dS,minMN, 1); } } return ret; } } /// /// singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix outU. /// Setting this parameter to a non-null value signals the need of returning those values. /// [Output] Right singular vectors of X as rows of matrix outV. /// This parameter must not be null. It might be an empty array on input. /// If true: return only first min(M,N) columns of outU and S (returned) will be /// of size [min(M,N),min(M,N)] /// If true: the matrix given will not be checked for infinte or NaN values. If such elements /// exist nevertheless, this may result in failing convergence or error. In worst case /// the function may hang inside the Lapack lib! Use with care! /// Singular values as diagonal matrix of same size and type as A public static ILRetArray< float> svd( ILInArray< fcomplex> A, ILOutArray< fcomplex> outU, ILOutArray< fcomplex> outV, bool small, bool discardFiniteTest ) { if (object.Equals(A,null)) throw new ILArgumentException("input matrix X must not be null"); using (ILScope.Enter(A)) { if (!A.IsMatrix) throw new ILArgumentSizeException("svd is defined for matrices only"); // early exit for small matrices if (A.Size[1] < 4 && A.Size[0] == A.Size[1]) { switch (A.Size[0]) { case 1: if (!Object.Equals(outU, null)) outU.a = ( fcomplex)1.0; if (!Object.Equals(outV, null)) outV.a = ( fcomplex)1.0; return abs(A); //case 2: // return -1; //case 3: // return -1; } } if (!discardFiniteTest && !allall(isfinite(A))) throw new ILArgumentException("svd: input must have only finite elements"); if (Lapack == null) throw new ILMathException("no Lapack package available"); // parameter evaluation int M = A.Size[0]; int N = A.Size[1]; int minMN = (M < N) ? M : N; int LDU = M; int LDVT = N; int LDA = M, lenDU = 0, lenVT = 0; float[] dS = ILMemoryPool.Pool.New< float>(minMN); char jobz = (small) ? 'S' : 'A'; fcomplex[] dU = null; fcomplex[] dVT = null; int info = 0; if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) { // need to return U and VT if (small) { lenDU = M * minMN; dU = ILMemoryPool.Pool.New< fcomplex>(lenDU); lenVT = N * minMN; dVT = ILMemoryPool.Pool.New< fcomplex>(lenVT); } else { lenDU = M * M; dU = ILMemoryPool.Pool.New< fcomplex>(lenDU); lenVT = N * N; dVT = ILMemoryPool.Pool.New< fcomplex>(lenVT); } } else { jobz = 'N'; } // must create copy of input ! fcomplex[] dInput = A.C.GetArrayForWrite(); Lapack.cgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info); if (info < 0) throw new ILArgumentException("the " + (-info).ToString() + "th argument to SVD was invalid"); if (info > 0) throw new ILArgumentException("svd was not converging"); ILArray< float> ret = empty(ILSize.Empty00); if (info == 0) { // success if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) { if (small) { ret.a = zeros< float>(new ILSize(minMN, minMN)); } else { ret.a = zeros< float>(new ILSize(M, N)); } for (int i = 0; i < minMN; i++) { ret.SetValue(dS[i], i, i); } ILMemoryPool.Pool.Free(dS); if (!Object.Equals(outU, null)) { outU.a = array< fcomplex>(dU, M, lenDU / M); } else { ILMemoryPool.Pool.Free(dU); } if (!Object.Equals(outV, null)) { outV.a = conj(new ILRetArray (dVT,N,lenVT / N).T); } else { ILMemoryPool.Pool.Free(dVT); } } else { ret.a = array< float>(dS,minMN, 1); } } return ret; } } /// /// singular value decomposition /// /// Input matrix /// [Output] Left singular vectors of A as columns of matrix outU. /// Setting this parameter to a non-null value signals the need of returning those values. /// [Output] Right singular vectors of X as rows of matrix outV. /// This parameter must not be null. It might be an empty array on input. /// If true: return only first min(M,N) columns of outU and S (returned) will be /// of size [min(M,N),min(M,N)] /// If true: the matrix given will not be checked for infinte or NaN values. If such elements /// exist nevertheless, this may result in failing convergence or error. In worst case /// the function may hang inside the Lapack lib! Use with care! /// Singular values as diagonal matrix of same size and type as A public static ILRetArray< double> svd( ILInArray< complex> A, ILOutArray< complex> outU, ILOutArray< complex> outV, bool small, bool discardFiniteTest ) { if (object.Equals(A,null)) throw new ILArgumentException("input matrix X must not be null"); using (ILScope.Enter(A)) { if (!A.IsMatrix) throw new ILArgumentSizeException("svd is defined for matrices only"); // early exit for small matrices if (A.Size[1] < 4 && A.Size[0] == A.Size[1]) { switch (A.Size[0]) { case 1: if (!Object.Equals(outU, null)) outU.a = ( complex)1.0; if (!Object.Equals(outV, null)) outV.a = ( complex)1.0; return abs(A); //case 2: // return -1; //case 3: // return -1; } } if (!discardFiniteTest && !allall(isfinite(A))) throw new ILArgumentException("svd: input must have only finite elements"); if (Lapack == null) throw new ILMathException("no Lapack package available"); // parameter evaluation int M = A.Size[0]; int N = A.Size[1]; int minMN = (M < N) ? M : N; int LDU = M; int LDVT = N; int LDA = M, lenDU = 0, lenVT = 0; double[] dS = ILMemoryPool.Pool.New< double>(minMN); char jobz = (small) ? 'S' : 'A'; complex[] dU = null; complex[] dVT = null; int info = 0; if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) { // need to return U and VT if (small) { lenDU = M * minMN; dU = ILMemoryPool.Pool.New< complex>(lenDU); lenVT = N * minMN; dVT = ILMemoryPool.Pool.New< complex>(lenVT); } else { lenDU = M * M; dU = ILMemoryPool.Pool.New< complex>(lenDU); lenVT = N * N; dVT = ILMemoryPool.Pool.New< complex>(lenVT); } } else { jobz = 'N'; } // must create copy of input ! complex[] dInput = A.C.GetArrayForWrite(); Lapack.zgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info); if (info < 0) throw new ILArgumentException("the " + (-info).ToString() + "th argument to SVD was invalid"); if (info > 0) throw new ILArgumentException("svd was not converging"); ILArray< double> ret = empty(ILSize.Empty00); if (info == 0) { // success if (!Object.Equals(outU, null) || !Object.Equals(outV, null)) { if (small) { ret.a = zeros< double>(new ILSize(minMN, minMN)); } else { ret.a = zeros< double>(new ILSize(M, N)); } for (int i = 0; i < minMN; i++) { ret.SetValue(dS[i], i, i); } ILMemoryPool.Pool.Free(dS); if (!Object.Equals(outU, null)) { outU.a = array< complex>(dU, M, lenDU / M); } else { ILMemoryPool.Pool.Free(dU); } if (!Object.Equals(outV, null)) { outV.a = conj(new ILRetArray (dVT,N,lenVT / N).T); } else { ILMemoryPool.Pool.Free(dVT); } } else { ret.a = array< double>(dS,minMN, 1); } } return ret; } } #endregion HYCALPER AUTO GENERATED CODE } }