///
/// 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 {
///
/// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
///
/// Input matrix. Size [m x n]
/// Triangular matrices L and U composed into a single matrix as returned from LAPACK function ?getrf. Size [m x n]
/// The matrix returned is composed out of the lower triangular matrix L with unit diagonal and the strict upper triangular matrix U.
///
/// :'''''''|
/// |1 \ |
/// | 1 \ R |
/// | 1 \ |
/// | L 1 \ |
/// | 1 \|
/// '''''''''
///
/// This overload is mainly needed for further operations via Lapack libraries. If you need the
/// L and U matrices directly, you'd better use one of the overloaded versions
///
/// or instead.
/// The matrix L will be a solid ILArray.
/// lu uses the Lapack function ?getrf.
///
///
///
/// if input A is not a matrix.
public static ILRetArray< double > lu(ILInArray A) {
ILArray< double > U = null;
ILArray< double > P = null;
return lu(A, U, P);
}
///
/// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
///
/// Input matrix to be decomposed. Size [m x n]
/// [Output] Reference to U. On return this will be the strict upper triangular matrix of size [min(m,n) x n]. Must not be null on input.
/// Lower triangular matrix L of size [m x min(m,n)]
/// A is decomposed into L and U, so that ILMath.multiply (L,U) will result in A.
/// L will only be a permuted version of a true triangular matrix. I.e. the rows of L will be permuted in order
/// to fullfill ILMath.multiply(L,U) == A
///
/// //we construct a matrix X:
/// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
/// // now X.ToString() will give something like:
/// // {<Double> 63238509 [3x3] Ref(2)
/// //(:,:)
/// // 1,00000 2,00000 3,00000
/// // 4,00000 4,00000 4,00000
/// // 5,00000 6,00000 7,00000
/// //}
/// // construct reference on U and call the decomposition
/// ILArray<double> U = new ILArray<double>.empty();
/// ILArray<double> L = ILMath.lu(X, ref U);
///
/// // L.ToString() is now:
/// // {<Double> 19634871 [3x3] Phys.
/// //(:,:)
/// // 0,20000 -1,00000 1,00000
/// // 0,80000 1,00000 0,00000
/// // 1,00000 0,00000 0,00000
/// //}
/// // and U is now:
/// //{<Double> 22584602 [3x3] Phys.
/// //(:,:)
/// // 5,00000 6,00000 7,00000
/// // 0,00000 -0,80000 -1,60000
/// // 0,00000 0,00000 0,00000
/// //}
///
/// Pay attention to the structure of L. In the example above the first and third row are exchanged. This permutation reflects the pivoting done during the decomposition inside the Lapack function ?getrf.
/// In order to access the permutation of L, one can use the overloaded version which returns the permuation matrix P also.
/// All of the matrices U and L returned will be solid ILArrays.
/// lu uses the Lapack function ?getrf.
///
///
///
/// if input A is not a matrix.
public static ILRetArray< double> lu(ILInArray A, ILOutArray U) {
return lu(A,U,null);
}
///
/// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also.
///
/// Input matrix. Size [m x n]
/// [Output] Reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.
/// [Output] Reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.
/// Lower triangular matrix L of size [m x min(m,n)]
/// A is decomposed into L and U, so that the equation
/// ILMath.multiply(L,U) == ILMath.multiply(P,A)
/// will hold except for round off error.
/// L and U will be true lower triangular matrices.
///
/// //Let's construct a matrix X:
/// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
/// // now X.ToString() will give something like:
/// // {<Double> 63238509 [3x3] Ref(2)
/// //(:,:)
/// // 1,00000 2,00000 3,00000
/// // 4,00000 4,00000 4,00000
/// // 5,00000 6,00000 7,00000
/// //}
/// // construct references on U and P and call the decomposition
/// ILArray<double> U = new ILArray<double>.empty();
/// ILArray<double> P = new ILArray<double>.empty();
/// ILArray<double> L = ILMath.lu(X, ref U, ref P);
///
/// // L.ToString() is now:
/// // {<Double> 19634871 [3x3] Phys.
/// //(:,:)
/// // 1,00000 0,00000 0,00000
/// // 0,80000 1,00000 0,00000
/// // 0,20000 -1,00000 1,00000
/// //}
/// // U is now:
/// //{<Double> 22584602 [3x3] Phys.
/// //(:,:)
/// // 5,00000 6,00000 7,00000
/// // 0,00000 -0,80000 -1,60000
/// // 0,00000 0,00000 0,00000
/// //}
/// // and P is:
/// //{<Double> 2192437 [3x3] Phys.
/// //(:,:)
/// // 0,00000 0,00000 1,00000
/// // 0,00000 1,00000 0,00000
/// // 1,00000 0,00000 0,00000
/// //}
///
/// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
///
/// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
/// // will give:
/// //{<Double> 59192235 [3x3] Phys.
/// //(:,:)
/// // 0,00000 0,00000 0,00000
/// // 0,00000 0,00000 0,00000
/// // 0,00000 0,00000 0,00000
/// //}
///
///
/// lu uses the Lapack function ?getrf.
/// All of the matrices U,L,P returned will be solid ILArrays.
///
///
///
/// if input A is not a matrix.
public static ILRetArray< double> lu(ILInArray A, ILOutArray U
, ILOutArray< double> P) {
using (ILScope.Enter(A)) {
if (!A.IsMatrix)
throw new ILArgumentSizeException("lu is defined for matrices only!");
int m = A.Size[0], n = A.Size[1], info = 0, minMN = (m < n) ? m : n;
ILArray< double> L = A.C;
int[] pivInd = ILMemoryPool.Pool.New(minMN);
/*!HC:lapack_*getrf*/
Lapack.dgetrf(m, n, L.GetArrayForWrite(), m, pivInd, ref info);
if (info < 0) {
ILMemoryPool.Pool.Free(pivInd);
throw new ILArgumentException("invalid parameter");
//} else if (info > 0) {
// // singular diagonal entry found
} else {
// completed successfuly
if (!Object.Equals(U, null)) {
if (!Object.Equals(P, null)) {
pivInd = perm2indicesForward(pivInd);
U.a = copyUpperTriangle(L, minMN, n);
L.a = copyLowerTriangle(L, m, minMN, 1);
P.a = zeros< double>(new ILSize(minMN, minMN));
// construct permutation matrix P
for (int r = 0; r < m; r++) {
P[r, pivInd[r]] = 1.0;
}
} else {
pivInd = perm2indicesBackward(pivInd);
U.a = copyUpperTriangle(L, minMN, n);
L.a = copyLowerTrianglePerm< double>(L, m, minMN, 1, pivInd);
}
}
}
ILMemoryPool.Pool.Free(pivInd);
return L;
}
}
#region HYCALPER AUTO GENERATED CODE
///
/// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
///
/// Input matrix. Size [m x n]
/// Triangular matrices L and U composed into a single matrix as returned from LAPACK function ?getrf. Size [m x n]
/// The matrix returned is composed out of the lower triangular matrix L with unit diagonal and the strict upper triangular matrix U.
///
/// :'''''''|
/// |1 \ |
/// | 1 \ R |
/// | 1 \ |
/// | L 1 \ |
/// | 1 \|
/// '''''''''
///
/// This overload is mainly needed for further operations via Lapack libraries. If you need the
/// L and U matrices directly, you'd better use one of the overloaded versions
///
/// or instead.
/// The matrix L will be a solid ILArray.
/// lu uses the Lapack function ?getrf.
///
///
///
/// if input A is not a matrix.
public static ILRetArray< float > lu(ILInArray A) {
ILArray< float > U = null;
ILArray< float > P = null;
return lu(A, U, P);
}
///
/// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
///
/// Input matrix to be decomposed. Size [m x n]
/// [Output] Reference to U. On return this will be the strict upper triangular matrix of size [min(m,n) x n]. Must not be null on input.
/// Lower triangular matrix L of size [m x min(m,n)]
/// A is decomposed into L and U, so that ILMath.multiply (L,U) will result in A.
/// L will only be a permuted version of a true triangular matrix. I.e. the rows of L will be permuted in order
/// to fullfill ILMath.multiply(L,U) == A
///
/// //we construct a matrix X:
/// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
/// // now X.ToString() will give something like:
/// // {<Double> 63238509 [3x3] Ref(2)
/// //(:,:)
/// // 1,00000 2,00000 3,00000
/// // 4,00000 4,00000 4,00000
/// // 5,00000 6,00000 7,00000
/// //}
/// // construct reference on U and call the decomposition
/// ILArray<double> U = new ILArray<double>.empty();
/// ILArray<double> L = ILMath.lu(X, ref U);
///
/// // L.ToString() is now:
/// // {<Double> 19634871 [3x3] Phys.
/// //(:,:)
/// // 0,20000 -1,00000 1,00000
/// // 0,80000 1,00000 0,00000
/// // 1,00000 0,00000 0,00000
/// //}
/// // and U is now:
/// //{<Double> 22584602 [3x3] Phys.
/// //(:,:)
/// // 5,00000 6,00000 7,00000
/// // 0,00000 -0,80000 -1,60000
/// // 0,00000 0,00000 0,00000
/// //}
///
/// Pay attention to the structure of L. In the example above the first and third row are exchanged. This permutation reflects the pivoting done during the decomposition inside the Lapack function ?getrf.
/// In order to access the permutation of L, one can use the overloaded version which returns the permuation matrix P also.
/// All of the matrices U and L returned will be solid ILArrays.
/// lu uses the Lapack function ?getrf.
///
///
///
/// if input A is not a matrix.
public static ILRetArray< float> lu(ILInArray A, ILOutArray U) {
return lu(A,U,null);
}
///
/// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also.
///
/// Input matrix. Size [m x n]
/// [Output] Reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.
/// [Output] Reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.
/// Lower triangular matrix L of size [m x min(m,n)]
/// A is decomposed into L and U, so that the equation
/// ILMath.multiply(L,U) == ILMath.multiply(P,A)
/// will hold except for round off error.
/// L and U will be true lower triangular matrices.
///
/// //Let's construct a matrix X:
/// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
/// // now X.ToString() will give something like:
/// // {<Double> 63238509 [3x3] Ref(2)
/// //(:,:)
/// // 1,00000 2,00000 3,00000
/// // 4,00000 4,00000 4,00000
/// // 5,00000 6,00000 7,00000
/// //}
/// // construct references on U and P and call the decomposition
/// ILArray<double> U = new ILArray<double>.empty();
/// ILArray<double> P = new ILArray<double>.empty();
/// ILArray<double> L = ILMath.lu(X, ref U, ref P);
///
/// // L.ToString() is now:
/// // {<Double> 19634871 [3x3] Phys.
/// //(:,:)
/// // 1,00000 0,00000 0,00000
/// // 0,80000 1,00000 0,00000
/// // 0,20000 -1,00000 1,00000
/// //}
/// // U is now:
/// //{<Double> 22584602 [3x3] Phys.
/// //(:,:)
/// // 5,00000 6,00000 7,00000
/// // 0,00000 -0,80000 -1,60000
/// // 0,00000 0,00000 0,00000
/// //}
/// // and P is:
/// //{<Double> 2192437 [3x3] Phys.
/// //(:,:)
/// // 0,00000 0,00000 1,00000
/// // 0,00000 1,00000 0,00000
/// // 1,00000 0,00000 0,00000
/// //}
///
/// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
///
/// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
/// // will give:
/// //{<Double> 59192235 [3x3] Phys.
/// //(:,:)
/// // 0,00000 0,00000 0,00000
/// // 0,00000 0,00000 0,00000
/// // 0,00000 0,00000 0,00000
/// //}
///
///
/// lu uses the Lapack function ?getrf.
/// All of the matrices U,L,P returned will be solid ILArrays.
///
///
///
/// if input A is not a matrix.
public static ILRetArray< float> lu(ILInArray A, ILOutArray U
, ILOutArray< float> P) {
using (ILScope.Enter(A)) {
if (!A.IsMatrix)
throw new ILArgumentSizeException("lu is defined for matrices only!");
int m = A.Size[0], n = A.Size[1], info = 0, minMN = (m < n) ? m : n;
ILArray< float> L = A.C;
int[] pivInd = ILMemoryPool.Pool.New(minMN);
Lapack.sgetrf(m, n, L.GetArrayForWrite(), m, pivInd, ref info);
if (info < 0) {
ILMemoryPool.Pool.Free(pivInd);
throw new ILArgumentException("invalid parameter");
//} else if (info > 0) {
// // singular diagonal entry found
} else {
// completed successfuly
if (!Object.Equals(U, null)) {
if (!Object.Equals(P, null)) {
pivInd = perm2indicesForward(pivInd);
U.a = copyUpperTriangle(L, minMN, n);
L.a = copyLowerTriangle(L, m, minMN, 1.0f);
P.a = zeros< float>(new ILSize(minMN, minMN));
// construct permutation matrix P
for (int r = 0; r < m; r++) {
P[r, pivInd[r]] = 1.0f;
}
} else {
pivInd = perm2indicesBackward(pivInd);
U.a = copyUpperTriangle(L, minMN, n);
L.a = copyLowerTrianglePerm< float>(L, m, minMN, 1.0f, pivInd);
}
}
}
ILMemoryPool.Pool.Free(pivInd);
return L;
}
}
///
/// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
///
/// Input matrix. Size [m x n]
/// Triangular matrices L and U composed into a single matrix as returned from LAPACK function ?getrf. Size [m x n]
/// The matrix returned is composed out of the lower triangular matrix L with unit diagonal and the strict upper triangular matrix U.
///
/// :'''''''|
/// |1 \ |
/// | 1 \ R |
/// | 1 \ |
/// | L 1 \ |
/// | 1 \|
/// '''''''''
///
/// This overload is mainly needed for further operations via Lapack libraries. If you need the
/// L and U matrices directly, you'd better use one of the overloaded versions
///
/// or instead.
/// The matrix L will be a solid ILArray.
/// lu uses the Lapack function ?getrf.
///
///
///
/// if input A is not a matrix.
public static ILRetArray< fcomplex > lu(ILInArray A) {
ILArray< fcomplex > U = null;
ILArray< fcomplex > P = null;
return lu(A, U, P);
}
///
/// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
///
/// Input matrix to be decomposed. Size [m x n]
/// [Output] Reference to U. On return this will be the strict upper triangular matrix of size [min(m,n) x n]. Must not be null on input.
/// Lower triangular matrix L of size [m x min(m,n)]
/// A is decomposed into L and U, so that ILMath.multiply (L,U) will result in A.
/// L will only be a permuted version of a true triangular matrix. I.e. the rows of L will be permuted in order
/// to fullfill ILMath.multiply(L,U) == A
///
/// //we construct a matrix X:
/// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
/// // now X.ToString() will give something like:
/// // {<Double> 63238509 [3x3] Ref(2)
/// //(:,:)
/// // 1,00000 2,00000 3,00000
/// // 4,00000 4,00000 4,00000
/// // 5,00000 6,00000 7,00000
/// //}
/// // construct reference on U and call the decomposition
/// ILArray<double> U = new ILArray<double>.empty();
/// ILArray<double> L = ILMath.lu(X, ref U);
///
/// // L.ToString() is now:
/// // {<Double> 19634871 [3x3] Phys.
/// //(:,:)
/// // 0,20000 -1,00000 1,00000
/// // 0,80000 1,00000 0,00000
/// // 1,00000 0,00000 0,00000
/// //}
/// // and U is now:
/// //{<Double> 22584602 [3x3] Phys.
/// //(:,:)
/// // 5,00000 6,00000 7,00000
/// // 0,00000 -0,80000 -1,60000
/// // 0,00000 0,00000 0,00000
/// //}
///
/// Pay attention to the structure of L. In the example above the first and third row are exchanged. This permutation reflects the pivoting done during the decomposition inside the Lapack function ?getrf.
/// In order to access the permutation of L, one can use the overloaded version which returns the permuation matrix P also.
/// All of the matrices U and L returned will be solid ILArrays.
/// lu uses the Lapack function ?getrf.
///
///
///
/// if input A is not a matrix.
public static ILRetArray< fcomplex> lu(ILInArray A, ILOutArray U) {
return lu(A,U,null);
}
///
/// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also.
///
/// Input matrix. Size [m x n]
/// [Output] Reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.
/// [Output] Reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.
/// Lower triangular matrix L of size [m x min(m,n)]
/// A is decomposed into L and U, so that the equation
/// ILMath.multiply(L,U) == ILMath.multiply(P,A)
/// will hold except for round off error.
/// L and U will be true lower triangular matrices.
///
/// //Let's construct a matrix X:
/// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
/// // now X.ToString() will give something like:
/// // {<Double> 63238509 [3x3] Ref(2)
/// //(:,:)
/// // 1,00000 2,00000 3,00000
/// // 4,00000 4,00000 4,00000
/// // 5,00000 6,00000 7,00000
/// //}
/// // construct references on U and P and call the decomposition
/// ILArray<double> U = new ILArray<double>.empty();
/// ILArray<double> P = new ILArray<double>.empty();
/// ILArray<double> L = ILMath.lu(X, ref U, ref P);
///
/// // L.ToString() is now:
/// // {<Double> 19634871 [3x3] Phys.
/// //(:,:)
/// // 1,00000 0,00000 0,00000
/// // 0,80000 1,00000 0,00000
/// // 0,20000 -1,00000 1,00000
/// //}
/// // U is now:
/// //{<Double> 22584602 [3x3] Phys.
/// //(:,:)
/// // 5,00000 6,00000 7,00000
/// // 0,00000 -0,80000 -1,60000
/// // 0,00000 0,00000 0,00000
/// //}
/// // and P is:
/// //{<Double> 2192437 [3x3] Phys.
/// //(:,:)
/// // 0,00000 0,00000 1,00000
/// // 0,00000 1,00000 0,00000
/// // 1,00000 0,00000 0,00000
/// //}
///
/// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
///
/// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
/// // will give:
/// //{<Double> 59192235 [3x3] Phys.
/// //(:,:)
/// // 0,00000 0,00000 0,00000
/// // 0,00000 0,00000 0,00000
/// // 0,00000 0,00000 0,00000
/// //}
///
///
/// lu uses the Lapack function ?getrf.
/// All of the matrices U,L,P returned will be solid ILArrays.
///
///
///
/// if input A is not a matrix.
public static ILRetArray< fcomplex> lu(ILInArray A, ILOutArray U
, ILOutArray< fcomplex> P) {
using (ILScope.Enter(A)) {
if (!A.IsMatrix)
throw new ILArgumentSizeException("lu is defined for matrices only!");
int m = A.Size[0], n = A.Size[1], info = 0, minMN = (m < n) ? m : n;
ILArray< fcomplex> L = A.C;
int[] pivInd = ILMemoryPool.Pool.New(minMN);
Lapack.cgetrf(m, n, L.GetArrayForWrite(), m, pivInd, ref info);
if (info < 0) {
ILMemoryPool.Pool.Free(pivInd);
throw new ILArgumentException("invalid parameter");
//} else if (info > 0) {
// // singular diagonal entry found
} else {
// completed successfuly
if (!Object.Equals(U, null)) {
if (!Object.Equals(P, null)) {
pivInd = perm2indicesForward(pivInd);
U.a = copyUpperTriangle(L, minMN, n);
L.a = copyLowerTriangle(L, m, minMN, new fcomplex(1.0f,0.0f));
P.a = zeros< fcomplex>(new ILSize(minMN, minMN));
// construct permutation matrix P
for (int r = 0; r < m; r++) {
P[r, pivInd[r]] = new fcomplex(1.0f,0.0f);
}
} else {
pivInd = perm2indicesBackward(pivInd);
U.a = copyUpperTriangle(L, minMN, n);
L.a = copyLowerTrianglePerm< fcomplex>(L, m, minMN, new fcomplex(1.0f,0.0f), pivInd);
}
}
}
ILMemoryPool.Pool.Free(pivInd);
return L;
}
}
///
/// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
///
/// Input matrix. Size [m x n]
/// Triangular matrices L and U composed into a single matrix as returned from LAPACK function ?getrf. Size [m x n]
/// The matrix returned is composed out of the lower triangular matrix L with unit diagonal and the strict upper triangular matrix U.
///
/// :'''''''|
/// |1 \ |
/// | 1 \ R |
/// | 1 \ |
/// | L 1 \ |
/// | 1 \|
/// '''''''''
///
/// This overload is mainly needed for further operations via Lapack libraries. If you need the
/// L and U matrices directly, you'd better use one of the overloaded versions
///
/// or instead.
/// The matrix L will be a solid ILArray.
/// lu uses the Lapack function ?getrf.
///
///
///
/// if input A is not a matrix.
public static ILRetArray< complex > lu(ILInArray A) {
ILArray< complex > U = null;
ILArray< complex > P = null;
return lu(A, U, P);
}
///
/// LU matrix decomposition. Decompose general matrix A into strictly upper part and lower part.
///
/// Input matrix to be decomposed. Size [m x n]
/// [Output] Reference to U. On return this will be the strict upper triangular matrix of size [min(m,n) x n]. Must not be null on input.
/// Lower triangular matrix L of size [m x min(m,n)]
/// A is decomposed into L and U, so that ILMath.multiply (L,U) will result in A.
/// L will only be a permuted version of a true triangular matrix. I.e. the rows of L will be permuted in order
/// to fullfill ILMath.multiply(L,U) == A
///
/// //we construct a matrix X:
/// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
/// // now X.ToString() will give something like:
/// // {<Double> 63238509 [3x3] Ref(2)
/// //(:,:)
/// // 1,00000 2,00000 3,00000
/// // 4,00000 4,00000 4,00000
/// // 5,00000 6,00000 7,00000
/// //}
/// // construct reference on U and call the decomposition
/// ILArray<double> U = new ILArray<double>.empty();
/// ILArray<double> L = ILMath.lu(X, ref U);
///
/// // L.ToString() is now:
/// // {<Double> 19634871 [3x3] Phys.
/// //(:,:)
/// // 0,20000 -1,00000 1,00000
/// // 0,80000 1,00000 0,00000
/// // 1,00000 0,00000 0,00000
/// //}
/// // and U is now:
/// //{<Double> 22584602 [3x3] Phys.
/// //(:,:)
/// // 5,00000 6,00000 7,00000
/// // 0,00000 -0,80000 -1,60000
/// // 0,00000 0,00000 0,00000
/// //}
///
/// Pay attention to the structure of L. In the example above the first and third row are exchanged. This permutation reflects the pivoting done during the decomposition inside the Lapack function ?getrf.
/// In order to access the permutation of L, one can use the overloaded version which returns the permuation matrix P also.
/// All of the matrices U and L returned will be solid ILArrays.
/// lu uses the Lapack function ?getrf.
///
///
///
/// if input A is not a matrix.
public static ILRetArray< complex> lu(ILInArray A, ILOutArray U) {
return lu(A,U,null);
}
///
/// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also.
///
/// Input matrix. Size [m x n]
/// [Output] Reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.
/// [Output] Reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.
/// Lower triangular matrix L of size [m x min(m,n)]
/// A is decomposed into L and U, so that the equation
/// ILMath.multiply(L,U) == ILMath.multiply(P,A)
/// will hold except for round off error.
/// L and U will be true lower triangular matrices.
///
/// //Let's construct a matrix X:
/// ILArray<double> X = new ILArray<double>(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
/// // now X.ToString() will give something like:
/// // {<Double> 63238509 [3x3] Ref(2)
/// //(:,:)
/// // 1,00000 2,00000 3,00000
/// // 4,00000 4,00000 4,00000
/// // 5,00000 6,00000 7,00000
/// //}
/// // construct references on U and P and call the decomposition
/// ILArray<double> U = new ILArray<double>.empty();
/// ILArray<double> P = new ILArray<double>.empty();
/// ILArray<double> L = ILMath.lu(X, ref U, ref P);
///
/// // L.ToString() is now:
/// // {<Double> 19634871 [3x3] Phys.
/// //(:,:)
/// // 1,00000 0,00000 0,00000
/// // 0,80000 1,00000 0,00000
/// // 0,20000 -1,00000 1,00000
/// //}
/// // U is now:
/// //{<Double> 22584602 [3x3] Phys.
/// //(:,:)
/// // 5,00000 6,00000 7,00000
/// // 0,00000 -0,80000 -1,60000
/// // 0,00000 0,00000 0,00000
/// //}
/// // and P is:
/// //{<Double> 2192437 [3x3] Phys.
/// //(:,:)
/// // 0,00000 0,00000 1,00000
/// // 0,00000 1,00000 0,00000
/// // 1,00000 0,00000 0,00000
/// //}
///
/// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
///
/// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
/// // will give:
/// //{<Double> 59192235 [3x3] Phys.
/// //(:,:)
/// // 0,00000 0,00000 0,00000
/// // 0,00000 0,00000 0,00000
/// // 0,00000 0,00000 0,00000
/// //}
///
///
/// lu uses the Lapack function ?getrf.
/// All of the matrices U,L,P returned will be solid ILArrays.
///
///
///
/// if input A is not a matrix.
public static ILRetArray< complex> lu(ILInArray A, ILOutArray U
, ILOutArray< complex> P) {
using (ILScope.Enter(A)) {
if (!A.IsMatrix)
throw new ILArgumentSizeException("lu is defined for matrices only!");
int m = A.Size[0], n = A.Size[1], info = 0, minMN = (m < n) ? m : n;
ILArray< complex> L = A.C;
int[] pivInd = ILMemoryPool.Pool.New(minMN);
Lapack.zgetrf(m, n, L.GetArrayForWrite(), m, pivInd, ref info);
if (info < 0) {
ILMemoryPool.Pool.Free(pivInd);
throw new ILArgumentException("invalid parameter");
//} else if (info > 0) {
// // singular diagonal entry found
} else {
// completed successfuly
if (!Object.Equals(U, null)) {
if (!Object.Equals(P, null)) {
pivInd = perm2indicesForward(pivInd);
U.a = copyUpperTriangle(L, minMN, n);
L.a = copyLowerTriangle(L, m, minMN, new complex(1.0,0.0));
P.a = zeros< complex>(new ILSize(minMN, minMN));
// construct permutation matrix P
for (int r = 0; r < m; r++) {
P[r, pivInd[r]] = new complex(1.0,0.0);
}
} else {
pivInd = perm2indicesBackward(pivInd);
U.a = copyUpperTriangle(L, minMN, n);
L.a = copyLowerTrianglePerm< complex>(L, m, minMN, new complex(1.0,0.0), pivInd);
}
}
}
ILMemoryPool.Pool.Free(pivInd);
return L;
}
}
#endregion HYCALPER AUTO GENERATED CODE
///
/// Copy upper triangle from PHYSICAL array A
///
/// Arbitrary inner type
/// PHYSICAL ILArray
/// Number of rows
/// Number of columns
/// Newly created physical array with the upper triangle of A
/// No checks are made for m,n fit inside A!
internal static ILRetArray copyUpperTriangle(ILInArray A, int m, int n) {
using (ILScope.Enter(A)) {
T[] arr = ILMemoryPool.Pool.New(m * n);
for (int r = 0; r < m; r++) {
for (int c = r; c < n; c++) {
arr[r + c * m] = A.GetValue(r, c);
}
}
return new ILRetArray(arr, m, n);
}
}
///
/// Copy upper triangle from system array A
///
/// Arbitrary inner type
/// System array, size (m x n), column wise ordered
/// Number of rows
/// Number of columns
/// Number of rows in output matrix
/// Newly created physical array with the upper triangle of A
/// No checks are made for m,n fit inside A! copies the main diagonal also.
/// the array returned will be of size (min(m,n) x n)
private static ILRetArray copyUpperTriangle(T[] arrIn, int arrInM, int arrInN, int outM) {
T[] arrOu = ILMemoryPool.Pool.New(outM * arrInN);
for (int c = 0; c < arrInN; c++) {
for (int r = 0; r <= c && r < outM; r++) {
arrOu[c * outM + r] = arrIn[c * arrInM + r];
}
}
return new ILRetArray (arrOu,outM,arrInN);
}
///
/// Copy lower triangle from PHYSICAL array A, set diagonal to val
///
/// Arbitrary inner type
/// PHYSICAL ILArray
/// Number of rows
/// Number of columns
/// Value for diagonal entries
/// Newly created physical array with the lower triangle of A
/// No checks are made for m,n fit inside A!
private static ILRetArray copyLowerTriangle(ILInArray A, int m, int n, T val) {
using (ILScope.Enter(A)) {
T[] arr = ILMemoryPool.Pool.New(m * n);
for (int r = 0; r < m; r++) {
for (int c = r + 1; c-- > 0; ) {
arr[r + m * c] = A.GetValue(r, c);
}
arr[r + m * r] = val;
}
return new ILRetArray(arr, m, n);
}
}
///
/// Copy lower triangle from PHYSICAL array A, set diagonal to val, permuted version
///
/// Arbitrary inner type
/// PHYSICAL ILArray
/// Number of rows
/// Number of columns
/// Mapping for rows, must be converted fom LAPACK version to single indices
/// Value for diagonal entries
/// Newly created physical array with the lower triangle of A
/// No checks are made for m,n fit inside A!
private static ILRetArray copyLowerTrianglePerm(ILInArray A, int m, int n, T val, int[] perm) {
using (ILScope.Enter(A)) {
T[] arr = ILMemoryPool.Pool.New(m * n);
int trueRow;
for (int r = 0; r < perm.Length; r++) {
trueRow = perm[r];
for (int c = 0; c < trueRow; c++) {
arr[r + c * m] = A.GetValue(trueRow, c);
}
arr[r + m * trueRow] = val;
}
return new ILRetArray(arr, m, n);
}
}
///
/// Relabel permutation indices from LAPACK ?getrf
///
/// Lapack pivoting permutation array
/// Index mapping for direct addressing the rows
/// Exchange the row labels in the same manner as LAPACK did for pivoting
private static int[] perm2indicesForward(int[] perm) {
int [] ret = ILMemoryPool.Pool.New(perm.Length);
for (int i = 0; i < ret.Length; i++) {
ret[i] = i;
}
int tmp;
for (int i = 0; i < ret.Length; i++) {
if (perm[i] != i+1) {
tmp = ret[perm[i]-1];
ret[perm[i]-1] = i;
ret[i] = tmp;
}
}
return ret;
}
///
/// Relabel permutation indices from LAPACK ?getrf - backward version
///
/// Lapack pivoting permutation array
/// Index mapping for direct addressing the rows
/// Exchange the row labels in the same manner as LAPACK did for pivoting, but backwards
private static int[] perm2indicesBackward(int[] perm) {
int [] ret = ILMemoryPool.Pool.New(perm.Length);
for (int i = 0; i < ret.Length; i++) {
ret[i] = i;
}
int tmp;
for (int i = ret.Length - 1; i-->0;) {
if (perm[i] != i+1) {
tmp = ret[perm[i]-1];
ret[perm[i]-1] = i;
ret[i] = tmp;
}
}
return ret;
}
}
}