예제 #1
0
        /// <summary>
        /// Construct packed versions of input matrices, and then use sparse row/column dot
        /// to compute elements of output matrix. This is faster. But still relatively expensive.
        /// </summary>
        void multiply_fast(SymmetricSparseMatrix M2in, ref SymmetricSparseMatrix Rin, bool bParallel)
        {
            int N = Rows;

            if (M2in.Rows != N)
            {
                throw new Exception("SymmetricSparseMatrix.Multiply: matrices have incompatible dimensions");
            }

            if (Rin == null)
            {
                Rin = new SymmetricSparseMatrix();
            }
            SymmetricSparseMatrix R = Rin;      // require alias for use in lambda below

            PackedSparseMatrix M = new PackedSparseMatrix(this);

            M.Sort();
            PackedSparseMatrix M2 = new PackedSparseMatrix(M2in, true);

            M2.Sort();

            // Parallel variant is vastly faster, uses spinlock to control access to R
            if (bParallel)
            {
                // goddamn SpinLock is in .Net 4
                //SpinLock spin = new SpinLock();
                gParallel.ForEach(Interval1i.Range(N), (r1i) => {
                    for (int c2i = r1i; c2i < N; c2i++)
                    {
                        double v = M.DotRowColumn(r1i, c2i, M2);
                        if (Math.Abs(v) > math.MathUtil.ZeroTolerance)
                        {
                            //bool taken = false;
                            //spin.Enter(ref taken);
                            //Debug.Assert(taken);
                            //R[r1i, c2i] = v;
                            //spin.Exit();
                            lock (R) {
                                R[r1i, c2i] = v;
                            }
                        }
                    }
                });
            }
            else
            {
                for (int r1i = 0; r1i < N; r1i++)
                {
                    for (int c2i = r1i; c2i < N; c2i++)
                    {
                        double v = M.DotRowColumn(r1i, c2i, M2);
                        if (Math.Abs(v) > math.MathUtil.ZeroTolerance)
                        {
                            R[r1i, c2i] = v;
                        }
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Compute dot product of this.row[r] and M.col[c], where the
        /// column is stored as MTranspose.row[c]
        /// </summary>
        public double DotRowColumn(int r, int c, PackedSparseMatrix MTranspose)
        {
            Debug.Assert(Sorted && MTranspose.Sorted);
            Debug.Assert(Rows.Length == MTranspose.Rows.Length);

            int a = 0;
            int b = 0;

            nonzero[] Row = Rows[r];
            nonzero[] Col = MTranspose.Rows[c];
            int       NA  = Row.Length;
            int       NB  = Col.Length;

            double sum = 0;

            while (a < NA && b < NB)
            {
                if (Row[a].j == Col[b].j)
                {
                    sum += Row[a].d * Col[b].d;
                    a++;
                    b++;
                }
                else if (Row[a].j < Col[b].j)
                {
                    a++;
                }
                else
                {
                    b++;
                }
            }

            return(sum);
        }
예제 #3
0
        // returns this*this (requires less memory)
        public SymmetricSparseMatrix Square(bool bParallel = true)
        {
            SymmetricSparseMatrix R = new SymmetricSparseMatrix();
            PackedSparseMatrix    M = new PackedSparseMatrix(this);

            M.Sort();

            // Parallel variant is vastly faster, uses spinlock to control access to R
            if (bParallel)
            {
                // goddamn SpinLock is in .Net 4
                //SpinLock spin = new SpinLock();
                gParallel.ForEach(Interval1i.Range(N), (r1i) => {
                    for (int c2i = r1i; c2i < N; c2i++)
                    {
                        double v = M.DotRowColumn(r1i, c2i, M);
                        if (Math.Abs(v) > math.MathUtil.ZeroTolerance)
                        {
                            //bool taken = false;
                            //spin.Enter(ref taken);
                            //Debug.Assert(taken);
                            //R[r1i, c2i] = v;
                            //spin.Exit();
                            lock (R) {
                                R[r1i, c2i] = v;
                            }
                        }
                    }
                });
            }
            else
            {
                for (int r1i = 0; r1i < N; r1i++)
                {
                    for (int c2i = r1i; c2i < N; c2i++)
                    {
                        double v = M.DotRowColumn(r1i, c2i, M);
                        if (Math.Abs(v) > math.MathUtil.ZeroTolerance)
                        {
                            R[r1i, c2i] = v;
                        }
                    }
                }
            }

            return(R);
        }
예제 #4
0
        /// <summary>
        /// Compute dot product of this.row[r] with all columns of M,
        /// where columns are stored in MTranspose rows.
        /// In theory more efficient than doing DotRowColumn(r,c) for each c,
        /// however so far the difference is negligible...perhaps because
        /// there are quite a few more branches in the inner loop
        /// </summary>
        public void DotRowAllColumns(int r, double[] sums, int[] col_indices, PackedSparseMatrix MTranspose)
        {
            Debug.Assert(Sorted && MTranspose.Sorted);
            Debug.Assert(Rows.Length == MTranspose.Rows.Length);

            int N = Rows.Length;
            int a = 0;

            nonzero[] Row = Rows[r];
            int       NA  = Row.Length;

            Array.Clear(sums, 0, N);
            Array.Clear(col_indices, 0, N);

            while (a < NA)
            {
                int aj = Row[a].j;
                for (int ci = 0; ci < N; ++ci)
                {
                    nonzero[] Col = MTranspose.Rows[ci];

                    int b = col_indices[ci];
                    if (b >= Col.Length)
                    {
                        continue;
                    }

                    while (b < Col.Length && Col[b].j < aj)
                    {
                        b++;
                    }

                    if (b < Col.Length && aj == Col[b].j)
                    {
                        sums[ci] += Row[a].d * Col[b].d;
                        b++;
                    }
                    col_indices[ci] = b;
                }
                a++;
            }
        }