public CCSMatrix FastMultiply(CCSMatrix B)
        {
            CCSMatrix A = this;
            //if (A.n != B.m) throw new ArgumentException();

            CCSMatrix C        = new CCSMatrix(A.m, B.n);
            Set <int> tmpIndex = new Set <int>();

            double[]      tmp        = new double[A.m];
            List <int>    C_RowIndex = new List <int>();
            List <double> C_Value    = new List <double>();

            for (int i = 0; i < A.m; i++)
            {
                tmp[i] = 0;
            }

            for (int j = 0; j < B.n; j++)             // for each col in B
            {
                for (int col = B.colIndex[j]; col < B.colIndex[j + 1]; col++)
                {
                    int    k    = B.rowIndex[col];
                    double valB = B.values[col];

                    if (k < A.ColumnSize)
                    {
                        for (int col2 = A.colIndex[k]; col2 < A.colIndex[k + 1]; col2++)
                        {
                            int    k2   = A.rowIndex[col2];
                            double valA = A.values[col2];
                            tmpIndex.Add(k2);
                            tmp[k2] += valA * valB;
                        }
                    }
                }

                int[] t     = tmpIndex.ToArray();
                int   count = 0;
                Array.Sort(t);
                foreach (int k in t)
                {
                    if (tmp[k] == 0)
                    {
                        continue;
                    }
                    C_RowIndex.Add(k);
                    C_Value.Add(tmp[k]);
                    tmp[k] = 0;
                    count++;
                }
                C.colIndex[j + 1] = C.colIndex[j] + count;
                tmpIndex.Clear();
            }

            C.rowIndex = C_RowIndex.ToArray(); C_RowIndex = null;
            C.values   = C_Value.ToArray(); C_Value = null;
            return(C);
        }
        public bool Check(CCSMatrix B)
        {
            CCSMatrix A = this;

            if (A.rowIndex.Length != B.rowIndex.Length)
            {
                throw new Exception();
            }
            if (A.colIndex.Length != B.colIndex.Length)
            {
                throw new Exception();
            }
            if (A.values.Length != B.values.Length)
            {
                throw new Exception();
            }

            for (int i = 0; i < rowIndex.Length; i++)
            {
                if (A.rowIndex[i] != B.rowIndex[i])
                {
                    throw new Exception();
                }
            }
            for (int i = 0; i < colIndex.Length; i++)
            {
                if (A.colIndex[i] != B.colIndex[i])
                {
                    throw new Exception();
                }
            }
            for (int i = 0; i < values.Length; i++)
            {
                if (A.values[i] != B.values[i])
                {
                    throw new Exception();
                }
            }

            return(true);
        }
        public CCSMatrix Transpose()
        {
            CCSMatrix C = new CCSMatrix(n, m);

            int[] rowCount = new int[m];
            for (int i = 0; i < rowCount.Length; i++)
            {
                rowCount[i] = 0;
            }
            for (int i = 0; i < this.rowIndex.Length; i++)
            {
                rowCount[this.rowIndex[i]]++;
            }

            C.ColIndex[0] = 0;
            for (int i = 0; i < m; i++)
            {
                C.ColIndex[i + 1] = C.ColIndex[i] + rowCount[i];
                rowCount[i]       = C.ColIndex[i];
            }

            C.values   = new double[this.NumNonZero];
            C.rowIndex = new int[this.NumNonZero];
            for (int i = 0; i < n; i++)
            {
                for (int j = colIndex[i]; j < colIndex[i + 1]; j++)
                {
                    int k = rowIndex[j];
                    C.values[rowCount[k]]   = values[j];
                    C.rowIndex[rowCount[k]] = i;
                    rowCount[k]++;
                }
            }

            return(C);
        }