/// <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);
            }
        }
예제 #2
0
        /// <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);
                }
            }
예제 #4
0
        /// <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];
            }
        }
예제 #5
0
        /// <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;
            }
        }
예제 #6
0
        /// <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;
            }
            }
        }