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