/// <summary>
        /// generalized multiplication, triple product.
        /// </summary>
        public void Multiply(double scale, MultidimensionalArray A, MultidimensionalArray B, MultidimensionalArray C, double thisscale, string Tindex, string Aindex, string Bindex, string Cindex)
        {
            // check arguments
            // ===============
            if (Tindex.Length != this.Dimension)
            {
                throw new ArgumentException();
            }
            if (Aindex.Length != A.Dimension)
            {
                throw new ArgumentException();
            }
            if (Bindex.Length != B.Dimension)
            {
                throw new ArgumentException();
            }
            if (Cindex.Length != C.Dimension)
            {
                throw new ArgumentException();
            }

            // determine indices for intermediate result
            // =========================================

            var _Aindex = Aindex.ToCharArray();
            var _Bindex = Bindex.ToCharArray();
            var _Cindex = Cindex.ToCharArray();
            var _Tindex = Tindex.ToCharArray();

            List <char> _Qindex  = new List <char>();
            List <int>  _Qlength = new List <int>();


            for (int i = 0; i < _Aindex.Length; i++)
            {
                char g = _Aindex[i];
                int  L = A.GetLength(i);

                if (Array.IndexOf <char>(_Tindex, g) >= 0 || Array.IndexOf <char>(_Cindex, g) >= 0)
                {
                    _Qindex.Add(g);
                    _Qlength.Add(L);
                }
            }

            for (int i = 0; i < _Bindex.Length; i++)
            {
                char g = _Bindex[i];
                int  L = B.GetLength(i);

                if (!_Qindex.Contains(g))
                {
                    if (Array.IndexOf <char>(_Tindex, g) >= 0 || Array.IndexOf <char>(_Cindex, g) >= 0)
                    {
                        _Qindex.Add(g);
                        _Qlength.Add(L);
                    }
                }
            }

            // execute multiplication
            // ======================

            // Q = A*B
            //var Q = MultidimensionalArray.Create(_Qlength.ToArray());
            int    iBuf;
            var    Q      = TempBuffer.GetTempMultidimensionalarray(out iBuf, _Qlength.ToArray());
            string Qindex = new string(_Qindex.ToArray());

            Q.Multiply(1.0, A, B, 0.0, Qindex, Aindex, Bindex);

            // this = scale*Q*C + this*thisscale
            this.Multiply(scale, Q, C, thisscale, Tindex, Qindex, Cindex);
            TempBuffer.FreeTempBuffer(iBuf);
        }
Beispiel #2
0
        static (double[] EigenVals, MultidimensionalArray EigenVect) EigenspaceSymmInternal(this IMatrix Inp, bool ComputeVectors)
        {
            if (Inp.NoOfCols != Inp.NoOfRows)
            {
                throw new ArgumentException("Not supported for non-symmetrical matrices.");
            }
            int N = Inp.NoOfRows;

            int JOBZ = ComputeVectors ? 'V' : 'N';
            // 'N':  Compute eigenvalues only;
            // 'V':  Compute eigenvalues and eigenvectors.

            int UPLO = 'L';

            // 'U':  Upper triangle of A is stored;
            // 'L':  Lower triangle of A is stored.

            unsafe {
                double[] InpBuffer             = TempBuffer.GetTempBuffer(out int RefInp, N * N);
                double[] Eigis                 = new double[N];
                MultidimensionalArray EigiVect = ComputeVectors ? MultidimensionalArray.Create(N, N) : null;

                fixed(double *pInp = InpBuffer, pEigis = Eigis)
                {
                    CopyToUnsafeBuffer(Inp, pInp, true);

                    int LDA = N;
                    int info;

                    // phase 1: work size estimation
                    double WorkSize;
                    int    LWORK = -1; // triggers estimation

                    LAPACK.F77_LAPACK.DSYEV_(ref JOBZ, ref UPLO, ref N, pInp, ref LDA, pEigis, &WorkSize, ref LWORK, out info);
                    if (info != 0)
                    {
                        TempBuffer.FreeTempBuffer(RefInp);
                        throw new ArithmeticException("LAPACK DSYEV (symmetrical matrix eigenvalues) returned info " + info);
                    }

                    LWORK = (int)WorkSize;

                    // phase 2: computation
                    double[] WorkBuffer = TempBuffer.GetTempBuffer(out int RefWork, LWORK * 1);
                    fixed(double *pWork = WorkBuffer)
                    {
                        LAPACK.F77_LAPACK.DSYEV_(ref JOBZ, ref UPLO, ref N, pInp, ref LDA, pEigis, pWork, ref LWORK, out info);
                        TempBuffer.FreeTempBuffer(RefWork);
                        if (info != 0)
                        {
                            TempBuffer.FreeTempBuffer(RefInp);
                            throw new ArithmeticException("LAPACK DSYEV (symmetrical matrix eigenvalues) returned info " + info);
                        }

                        if (EigiVect != null)
                        {
                            CopyFromUnsafeBuffer(EigiVect, pInp, true);
                        }
                    }
                }

                TempBuffer.FreeTempBuffer(RefInp);


                return(Eigis, EigiVect);
            }
        }