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