/// <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); }
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); } }