Пример #1
0
        /// <summary>
        /// Swap the first m*n elements within a given array so that, for any
        /// non-negative i and j less than m and n respectively, dst[i*n+j] == src[j*m+i]
        /// </summary>
        /// <typeparam name="T">Elements of the array are this type</typeparam>
        /// <param name="src">The source elements of the transpose. Must contain at least m*n elements.</param>
        /// <param name="dst">Where to write the transpose. Note that dst cannot be the same as src. Must contain at least m*n elements.</param>
        /// <param name="m">The major index.</param>
        /// <param name="n">The minor index. Elements are currently stored in "m" blocks of "n" items.</param>
        public static void Transpose <T>(T[] src, T[] dst, int m, int n)
        {
            Contracts.AssertValue(src);
            Contracts.AssertValue(dst);
            Contracts.Assert(src != dst, "Transpose in place not supported");
            Contracts.Assert(src.Length <= m * n);
            Contracts.Assert(dst.Length <= m * n);

            MadeObjectPool <T[]> workPool = new MadeObjectPool <T[]>(() => new T[_block * _block]);
            int isteps = (m - 1) / _block + 1;
            int jsteps = (n - 1) / _block + 1;
            IEnumerable <int> jenum = Enumerable.Range(0, jsteps).Select(j => j * _block);
            IEnumerable <int> ienum = Enumerable.Range(0, isteps).Select(i => i * _block);
            IEnumerable <Tuple <int, int> > ijenum = ienum.SelectMany(i => jenum.Select(j => new Tuple <int, int>(i, j)));

            Parallel.ForEach(ijenum, ij =>
            {
                int i    = ij.Item1;
                int j    = ij.Item2;
                int iend = Math.Min(m - i, _block);
                int jend = Math.Min(n - j, _block);
                T[] work = workPool.Get();
                // Copy things over to the work block.
                int off = j * m + i;
                for (int jsub = 0; jsub < jend; ++jsub)
                {
                    int workoff = jsub * _block;
                    for (int isub = 0; isub < iend; ++isub)
                    {
                        //work[jsub * BLOCK + isub] = a[(j + jsub) * m + (i + isub)];
                        work[workoff + isub] = src[off + isub];
                    }
                    off += m;
                }
                // Copy the elements of the work block over to B.
                off = i * n + j;
                for (int isub = 0; isub < iend; ++isub)
                {
                    for (int jsub = 0; jsub < jend; ++jsub)
                    {
                        //dst[(i + isub) * n + (j + jsub)] = work[jsub * BLOCK + isub];
                        dst[off + jsub] = work[jsub * _block + isub];
                    }
                    off += n;
                }
                workPool.Return(work);
            });
        }
Пример #2
0
        /// <summary>
        /// Swap the first m*n elements within a given array so that, for any
        /// non-negative i and j less than m and n respectively, b[i*n+j] == a[j*m+i]
        /// </summary>
        /// <param name="src"></param>
        /// <param name="dst">Where to write the transpose. Note that dst cannot be the same as src.</param>
        /// <param name="m"></param>
        /// <param name="n"></param>
        public static unsafe void Transpose(double *src, double *dst, int m, int n)
        {
            MadeObjectPool <double[]> workPool = new MadeObjectPool <double[]>(() => new double[_block * _block]);
            //T[] work = new T[BLOCK * BLOCK];
            int isteps = (m - 1) / _block + 1;
            int jsteps = (n - 1) / _block + 1;
            IEnumerable <int> jenum = Enumerable.Range(0, jsteps).Select(j => j * _block);
            IEnumerable <int> ienum = Enumerable.Range(0, isteps).Select(i => i * _block);
            IEnumerable <Tuple <int, int> > ijenum = ienum.SelectMany(i => jenum.Select(j => new Tuple <int, int>(i, j)));

            Parallel.ForEach(ijenum, ij =>
            {
                int i         = ij.Item1;
                int j         = ij.Item2;
                int iend      = Math.Min(m - i, _block);
                int jend      = Math.Min(n - j, _block);
                double[] work = workPool.Get();
                // Copy things over to the work block.
                double *srcP = src + j * m + i;
                for (int jsub = 0; jsub < jend; ++jsub)
                {
                    for (int isub = 0; isub < iend; ++isub)
                    {
                        // This inner loop is equivalent to the following assignment:
                        // work[j * BLOCK + i] = src[(J + j) * m + (I + i)];
                        work[jsub * _block + isub] = srcP[isub];
                    }
                    srcP += m;
                }
                // Copy the elements of the work block over to B.
                double *dstP = dst + i * n + j;
                for (int isub = 0; isub < iend; ++isub)
                {
                    for (int jsub = 0; jsub < jend; ++jsub)
                    {
                        // This inner loop is equivalent to the following assignment:
                        // dst[(I + i) * n + (J + j)] = work[j * BLOCK + i];
                        dstP[jsub] = work[jsub * _block + isub];
                    }
                    dstP += n;
                }
                workPool.Return(work);
            });
        }