/// <summary> /// computes the inner product of this array and another array <paramref name="other"/>. /// </summary> /// <param name="other"> /// must be of the same size a this array /// </param> /// <returns></returns> public double InnerProduct(MultidimensionalArray other) { if (this.Dimension != other.Dimension) { throw new ArgumentException("mismatch in number of dimensions"); } int D = this.Dimension; for (int k = 0; k < D; k++) { if (this.GetLength(k) != other.GetLength(k)) { throw new ArgumentException("mismatch in dimension " + k); } } if (this.IsContinious && other.IsContinious) { unsafe { fixed(double *pStorageThis = this.m_Storage, pStorageOther = other.m_Storage) { return(BLAS.ddot(this.Length, pStorageThis, 1, pStorageOther, 1)); } } } else { double acc = 0; this.ApplyAll(delegate(int[] index, ref double entry) { acc += entry * other[index]; }); return(acc); } }
/// <summary> /// Writes the components of this vector to an array with arbitrary dimensions /// </summary> /// <param name="mda">data origin</param> /// <param name="IndexOffset">the index into <paramref name="mda"/>, where to start writing data</param> /// <param name="DestDim">the dimension from which to take the vector entries</param> public void WriteTo(int DestDim, MultidimensionalArray mda, params int[] IndexOffset) { #if DEBUG if (mda.Dimension != IndexOffset.Length) { throw new ArgumentException("Expecting an array of dimension equal to length of IndexOffset."); } ; if (mda.GetLength(DestDim) != Dim) { throw new ArgumentException("Destination dimension has mismatching length."); } #endif mda[IndexOffset] = x; if (Dim > 1) { IndexOffset[DestDim]++; mda[IndexOffset] = y; } if (Dim > 2) { IndexOffset[DestDim]++; mda[IndexOffset] = z; } }
unsafe internal void GetCyclesAndRanks(int *cycRunA, int *cycRunB, int *lenSum, int *cycSumA, int *cycSumB, MultidimensionalArray A, MultidimensionalArray B) { #if DEBUG for (int i = 0; i < NoOfSumCycles; i++) { Debug.Assert(cycSumA[i] == 0); Debug.Assert(cycSumB[i] == 0); } for (int i = 0; i < DT; i++) { Debug.Assert(cycRunA[i] == 0); Debug.Assert(cycRunB[i] == 0); } #endif for (int i = 0; i < RunACount; i++) { int shift = i << 2; uint mask = ((uint)(0xf)) << shift; int rnkA = (int)((RunRankAStore & mask) >> shift); int runA = (int)((RunLoopAStore & mask) >> shift); Debug.Assert(runA >= 0 && runA < DT); cycRunA[runA] += A.GetCycle(rnkA); } for (int i = 0; i < RunBCount; i++) { int shift = i << 2; uint mask = ((uint)(0xf)) << shift; int rnkB = (int)((RunRankBStore & mask) >> shift); int runB = (int)((RunLoopBStore & mask) >> shift); Debug.Assert(runB >= 0 && runB < DT); cycRunB[runB] += B.GetCycle(rnkB); } for (int i = 0; i < SumACount; i++) { int shift = i << 2; uint mask = ((uint)(0xf)) << shift; int rnkA = (int)((SumRankAStore & mask) >> shift); int sumA = (int)((SumLoopAStore & mask) >> shift); Debug.Assert(sumA >= 0 && sumA < NoOfSumCycles); cycSumA[sumA] += A.GetCycle(rnkA); lenSum[sumA] = A.GetLength(rnkA); } for (int i = 0; i < SumBCount; i++) { int shift = i << 2; uint mask = ((uint)(0xf)) << shift; int rnkB = (int)((SumRankBStore & mask) >> shift); int sumB = (int)((SumLoopBStore & mask) >> shift); Debug.Assert(sumB >= 0 && sumB < NoOfSumCycles); cycSumB[sumB] += B.GetCycle(rnkB); } }
/// <summary> /// Initializes this from the third dimension of a 3D array /// </summary> /// <param name="mda">data origin</param> /// <param name="i1">index into 1st dimension of <paramref name="mda"/></param> /// <param name="i2">index into 2nd dimension of <paramref name="mda"/></param> public void SetFrom(MultidimensionalArray mda, int i1, int i2) { #if DEBUG if (mda.Dimension != 3) { throw new ArgumentException("Expecting a 3D-array."); } ; if (mda.GetLength(2) != Dim) { throw new ArgumentException("Second dimension mismatch."); } #endif x = mda[i1, i2, 0]; if (Dim > 1) { y = mda[i1, i2, 1]; } if (Dim > 2) { z = mda[i1, i2, 2]; } }
/// <summary> /// Writes the components of this vector to a 3D array /// </summary> /// <param name="mda">data origin</param> /// <param name="i1">index into 1st dimension of <paramref name="mda"/></param> /// <param name="i2">index into 2nd dimension of <paramref name="mda"/></param> public void WriteTo(MultidimensionalArray mda, int i1, int i2) { #if DEBUG if (mda.Dimension != 3) { throw new ArgumentException("Expecting a 3D-array."); } ; if (mda.GetLength(2) != Dim) { throw new ArgumentException("Second dimension mismatch."); } #endif mda[i1, i2, 0] = x; if (Dim > 1) { mda[i1, i2, 1] = y; } if (Dim > 2) { mda[i1, i2, 2] = z; } }
/// <summary> /// Initializes this from an array with arbitrary dimensions /// </summary> /// <param name="mda">data origin</param> /// <param name="IndexOffset">the index into <paramref name="mda"/>, where to start reading data</param> /// <param name="OriginDim">the dimension from which to take the vector entries</param> public void SetFrom(int OriginDim, MultidimensionalArray mda, params int[] IndexOffset) { #if DEBUG if (mda.Dimension != IndexOffset.Length) { throw new ArgumentException("Expecting an array of dimension equal to length of IndexOffset."); } if (mda.GetLength(OriginDim) != Dim) { throw new ArgumentException("Origin dimension has mismatching length."); } #endif x = mda[IndexOffset]; if (Dim > 1) { IndexOffset[OriginDim]++; y = mda[IndexOffset]; } if (Dim > 2) { IndexOffset[OriginDim]++; z = mda[IndexOffset]; } }
internal void CheckArgs(MultidimensionalArray T, MultidimensionalArray A, MultidimensionalArray B) { if (T.Dimension != DT) { throw new ArgumentException("Wrong dimension of result array."); } if (A.Dimension != DA) { throw new ArgumentException("Wrong dimension of array A."); } if (B.Dimension != DB) { throw new ArgumentException("Wrong dimension of array B."); } for (int i = 0; i < RunACount; i++) { int shift = i << 2; uint mask = ((uint)(0xf)) << shift; int rnkA = (int)((RunRankAStore & mask) >> shift); int sumA = (int)((RunLoopAStore & mask) >> shift); Debug.Assert(sumA >= 0 && sumA < DT); if ((T.GetLength(sumA) != A.GetLength(rnkA)) && (iTrafoIdx != sumA)) { throw new ArgumentException(string.Format("Wrong length of {0}-th rank of array A.", rnkA)); } } for (int i = 0; i < RunBCount; i++) { int shift = i << 2; uint mask = ((uint)(0xf)) << shift; int rnkB = (int)((RunRankBStore & mask) >> shift); int sumB = (int)((RunLoopBStore & mask) >> shift); Debug.Assert(sumB >= 0 && sumB < DT); if ((T.GetLength(sumB) != B.GetLength(rnkB)) && (iTrafoIdx != sumB)) { throw new ArgumentException(string.Format("Wrong length of {0}-th rank of array B.", rnkB)); } } int[] lenSum = new int[NoOfSumCycles]; for (int i = 0; i < SumACount; i++) { int shift = i << 2; uint mask = ((uint)(0xf)) << shift; int rnkA = (int)((SumRankAStore & mask) >> shift); int sumA = (int)((SumLoopAStore & mask) >> shift); Debug.Assert(sumA >= 0 && sumA < NoOfSumCycles); lenSum[sumA] = A.GetLength(rnkA); } for (int i = 0; i < SumBCount; i++) { int shift = i << 2; uint mask = ((uint)(0xf)) << shift; int rnkB = (int)((SumRankBStore & mask) >> shift); int sumB = (int)((SumLoopBStore & mask) >> shift); Debug.Assert(sumB >= 0 && sumB < NoOfSumCycles); if (B.GetLength(rnkB) != lenSum[sumB]) { throw new ArgumentException(string.Format("Wrong length of {0}-th rank of array B.", rnkB)); } } }
/// <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); }
/// <summary> /// adds <paramref name="other"/>*<paramref name="scl"/> to this array /// overwriting this array; this array must have the same dimension as /// <paramref name="other"/> and the length of each dimension must match. /// </summary> /// <param name="other"></param> /// <param name="scl"> /// scaling of <paramref name="other"/> during accumulation /// </param> public void Acc(double scl, MultidimensionalArray other) { if (m_LockedForever) { throw new ApplicationException("illegal call - object is locked."); } if (this.Dimension != other.Dimension) { throw new ArgumentException("mismatch in number of dimensions.", "other"); } if (other.m_Dimension != this.m_Dimension) { throw new ArgumentException("Number of dimensions must be equal."); } for (int i = this.m_Dimension - 1; i >= 0; i--) { if (other.GetLength(i) != this.GetLength(i)) { throw new ArgumentException("Mismatch in dimension " + i); } } // Optimized accumulation for continuous pieces of memory if (this.IsContinious && other.IsContinious) { int[] index = new int[Dimension]; int thisOffset = this.Index(index); int otherOffset = other.Index(index); unsafe { fixed(double *pThis = &this.Storage[thisOffset], pOther = &other.Storage[otherOffset]) { //for (int i = 0; i < this.Length; i++) { // *(pThis + i) += scl * *(pOther + i); //} BLAS.daxpy(this.Length, scl, pOther, 1, pThis, 1); } } return; } // Standard versions switch (this.Dimension) { case 2: { int L0 = this.GetLength(0); int L1 = this.GetLength(1); for (int i0 = 0; i0 < L0; i0++) { for (int i1 = 0; i1 < L1; i1++) { int ind_this = this.Index(i0, i1); int ind_othr = other.Index(i0, i1); this.m_Storage[ind_this] += other.m_Storage[ind_othr] * scl; } } return; } default: { double[] other_stor = other.m_Storage; ApplyAll(delegate(int[] idx, ref double entry) { int ind_other = other.Index(idx); entry += scl * other_stor[ind_other]; }); return; } } }