MKLのLAPACKでLU分解

MKLで逆行列を求めるには、行列を一度LU分解しておく必要がある。
ダウンロードしてきたMKLのC#のラッパーには、LAPACKのLU分解パッケージ"dgetrf"がなかったので、記載されていたものを参考に作成してみた。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security;
using System.Runtime.InteropServices;

namespace mkl
{
    public sealed class LAPACK
    {
        private LAPACK() { }

        /* Constants for LAPACK_JOB */
        public sealed class JOB
        {
            private JOB() { }
            public static int JobN = 201;      /* job ='N' */
            public static int JobV = 202;      /* job ='V' */
            public static int JobA = 203;      /* job ='A' */
            public static int JobS = 204;      /* job ='S' */
            public static int JobO = 205;      /* job ='O' */
        };


        // LAPACK dgetrf wrapper
        public static int dgetrf(int m, int n, double[] a, int lda,int[] ipiv)
        {
            int info = 0;
            //int[] ipiv = new int[Math.Min(m,n)];

            LAPACKNative.dgetrf(ref m, ref n, a, ref lda, ipiv, ref info);

            return info;
        }
    }

    /** LAPACK native declarations */
    [SuppressUnmanagedCodeSecurity]
    internal sealed class LAPACKNative
    {
        private LAPACKNative() { }

 
        // LAPACK native dgetrf declaration
        [DllImport("mkl_rt", CallingConvention = CallingConvention.Cdecl,
            ExactSpelling = true, SetLastError = false)]
        internal static extern void dgetrf(
            ref int m,                  //行列の行数(m)
            ref int n,                  //行列の列数(n)
            [In, Out] double[] a,       //行列へのポインタ
            ref int lda,                //行列の行数
            [In, Out] int[] ipiv,       //ピボット選択の添字を格納する長さ(min(m,n))の配列
            ref int info                //実行後,例外情報が格納
            );
    }
}

でもって、これを呼ぶプログラムを作ってみた。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using mkl;

namespace dgetri_test
{
    class test_dgetri
    {
        static void Main(string[] args)
        {
            Console.WriteLine("--- dgetrf test---");
            int info;
            double[] A = new double[] {3,1,4,3,2,4,6,6,6,};
            int m = 3, n = 3;
            int lda = m;
            int[] ipiv = new int[Math.Min(m, n)];
            
            //print the parameters
            printMatrix("Matrix A:",A, m, n);

            //compute
            info = LAPACK.dgetrf(m, n, A, lda, ipiv);

            //print result
            printMatrix("Matrix A on exit:",A,m,n);
            printVector("Vector P on exit:",ipiv,m);
            Console.WriteLine("info on exit:" + info);
            Console.WriteLine("TEST PASSED");
            Console.WriteLine();
        }

        /** Print the matrix X assuming row-major order of elements. */
        private static void printMatrix(String prompt, double[] X, int I, int J)
        {
            Console.WriteLine(prompt);
            for (int i = 0; i < I; i++)
            {
                for (int j = 0; j < J; j++)
                    Console.Write("\t" + X[i * J + j]);
                Console.WriteLine();
            }
        }
        /** Print the vector X */
        private static void printVector(string prompt, int[] X, int N)
        {
            Console.WriteLine(prompt);
            for (int n = 0; n < N; n++)
                Console.Write("\t" + X[n]);
            Console.WriteLine();
        }
    }
}


結果を見てみると、「下三角行列L」と、「上三角行列Uの対角成分以外」が格納されているようだ。しかもこの行列について、行列の積LUを計算すると適当な置換がかかっている。

dgetrfの呼出し方がおかしいのか、それともこういうもんなのか謎。