Exemplo n.º 1
0
        private static void Tst()
        {
            int n = 8;

            int[] ia /*[9]*/ = new int[] { 1, 5, 8, 10, 12, 15, 17, 18, 19 };

            int[] ja /*[18]*/ = new int[] { 1, 3, 6, 7,
                                            2, 3, 5,
                                            3, 8,
                                            4, 7,
                                            5, 6, 7,
                                            6, 8,
                                            7,
                                            8 };

            double[] a /*[18]*/ = new double[] { 7.0, 1.0, 2.0, 7.0,
                                                 -4.0, 8.0, 2.0,
                                                 1.0, 5.0,
                                                 7.0, 9.0,
                                                 5.0, 1.0, 5.0,
                                                 -1.0, 5.0,
                                                 11.0,
                                                 5.0 };

            var csr = new CSparse.Double.SparseMatrix(n, n, 18);

            csr.ColumnPointers = ia;
            csr.RowIndices     = ja;
            csr.Values         = a;
        }
        public CSR GetAdjacencyGraph(CSR P_delta)
        {
            var p = P_delta.Clone();

            for (var i = 0; i < p.NonZerosCount; i++)
            {
                p.Values[i] = 1;
            }

            var buf = (CSR)p.Multiply(p.Transpose());

            return(buf);
        }
Exemplo n.º 3
0
        public static SparseEqSystem Generate(CSparse.Double.SparseMatrix eqSystem)
        {
            var buf     = new SparseEqSystem();
            var lastCol = eqSystem.ColumnCount;

            var eqs     = buf.Equations = new SparseRow[eqSystem.RowCount];
            var colNnzs = buf.ColumnNonzeros = new int[eqSystem.ColumnCount];

            buf.RowNonzeros = new int[eqSystem.RowCount];


            for (var i = 0; i < eqs.Length; i++)
            {
                buf.Equations[i] = new SparseRow(1);
            }


            foreach (var tuple in eqSystem.EnumerateIndexed())
            {
                var rw  = tuple.Item1; //tuple.Item1;
                var col = tuple.Item2; //tuple.Item2;
                var val = tuple.Item3;

                eqs[rw].Add(col, val);

                if (col != lastCol)
                {
                    colNnzs[col]++;
                }
            }


            for (var i = 0; i < eqs.Length; i++)
            {
                buf.RowNonzeros[i] = buf.Equations[i].CalcNnz(lastCol);
            }

            buf.RowCount    = eqSystem.RowCount;
            buf.ColumnCount = eqSystem.ColumnCount;

            return(buf);
        }
        public CCS CalculateRref(CCS a)
        {
            var singleMemberColumns = 00;

            var aTran = a.Transpose();

            var n = a.ColumnCount;

            for (var i = 0; i < n; i++)
            {
                if (a.GetNnzcForColumn(i) == 1)
                {
                    singleMemberColumns++;
                }
            }

            if (singleMemberColumns == a.RowCount)
            {
                return((CCS)a.Clone());
            }

            var pat  = new CoordinateStorage <double>(a.RowCount, a.ColumnCount - 1, 1);
            var bCrd = new CoordinateStorage <double>(a.RowCount, a.ColumnCount - 1, 1);//a matrix without last column

            a.EnumerateIndexed((row, col, val) =>
            {
                if (col != a.ColumnCount - 1)
                {
                    pat.At(row, col, 1);
                    bCrd.At(row, col, val);
                }
            });
            //nonzero pattern of a, except last column

            var b     = bCrd.ToCCs();
            var bTran = b.Transpose();

            var patt   = pat.ToCCs();
            var pattTr = patt.Transpose();


            var varGraph = pattTr.Multiply(patt);

            varGraph.Values.FillWith(1);

            var eqnGraph = patt.Multiply(pattTr);

            eqnGraph.Values.FillWith(1);



            if (!varGraph.IsSymmetric() || !eqnGraph.IsSymmetric())
            {
                throw new Exception();
            }

            var eqnParts = CalcUtil.EnumerateGraphParts(eqnGraph);

            var varParts = CalcUtil.EnumerateGraphParts(varGraph);

            var varVisited = new bool[varGraph.ColumnCount];

            foreach (var eqnPart in eqnParts)
            {
                //i'th independent system.
                var firstEq = eqnPart.First();

                int firstVarOfFirstEq = -1;

                /*
                 * patt.EnumerateRowMembers(firstEq, (row, col, val) => {
                 * if (firstValOfFirstEq != -1)
                 *  firstValOfFirstEq = col;
                 * );
                 */


                pattTr.EnumerateColumnMembers(firstEq, (row, col, val) =>
                {
                    if (firstVarOfFirstEq == -1)
                    {
                        firstVarOfFirstEq = row;
                    }
                });

                //var firstVar = patt.EnumerateColumnMembers()

                var connectedVariables = CalcUtil.DepthFirstSearch(varGraph, varVisited, firstVarOfFirstEq);

                connectedVariables.Sort();

                var vp = new Dictionary <int, int>();//variablePermute

                //vp[a] = b, a: number of variable in original system
                // b: index of variable in connectedVariables

                for (var i = 0; i < connectedVariables.Count; i++)
                {
                    vp[connectedVariables[i]] = i;
                }


                var denseSubSytem = new Matrix(eqnPart.Count, connectedVariables.Count + 1);////i'th independent system as dense

                // Convert sparse to dense.
                //var dns = Matrix.OfMatrix(aTran);

                for (var i = 0; i < eqnPart.Count; i++)
                {
                    //insert i'th eqn into denseSubSytem

                    var row = i;

                    var st = aTran.ColumnPointers[i];
                    var en = aTran.ColumnPointers[i + 1];

                    for (int j = st; j < en; j++)
                    {
                        var col = aTran.RowIndices[j];

                        if (col == a.ColumnCount - 1)
                        {
                            continue;
                        }

                        var val = aTran.Values[j];


                        denseSubSytem[i, vp[col]] = val;
                    }
                }
            }

            throw new NotImplementedException();
        }
Exemplo n.º 5
0
        /// <summary>
        /// The Direct Conformal Parameterization (DCP) method, see (Desbrun et al. 2002)
        /// </summary>
        /// <param name="meshin"></param>
        /// <param name="meshout"></param>
        private void DCP(TriangleMesh meshin, out TriangleMesh meshout)
        {
            MeshLaplacian.PrecomputeTraits(meshin);

            /// copy the mesh
            meshout = meshin.Copy();

            /// counters
            var vertexCount = meshout.Vertices.Count;

            /// output uv-coordinates
            var bu = new double[vertexCount];
            var bv = new double[vertexCount];
            var b0 = new double[vertexCount];

            // A * x = b
            var x = new double[vertexCount * 2 + 4];

            var M_A = new TripletMatrix(2 * (vertexCount + 2), 2 * vertexCount, 4 * (vertexCount + 1) * vertexCount);
            var M_X = new TripletMatrix(2 * (vertexCount + 2), 2 * vertexCount, 4 * (vertexCount + 1) * vertexCount);

            foreach (var vertex in meshin.Vertices.Where(v => !v.OnBoundary))
            {
                var angleWeightSum = 0d;
                var areaWeightSum  = 0d;

                foreach (var halfEdge in vertex.Halfedges)
                {
                    // cot(alpha) + cot(beta)
                    var angleWeight = halfEdge.Previous.Traits.Cotan + halfEdge.Opposite.Previous.Traits.Cotan;
                    // cot(gamma) + cot(delta)
                    var areaWeight = (halfEdge.Next.Traits.Cotan + halfEdge.Opposite.Traits.Cotan);
                    areaWeight /= (halfEdge.FromVertex.Traits.Position - halfEdge.ToVertex.Traits.Position).LengthSquared();

                    M_A.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, angleWeight);
                    M_A.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, angleWeight);
                    M_X.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, areaWeight);
                    M_X.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, areaWeight);

                    angleWeightSum += angleWeight;
                    areaWeightSum  += areaWeight;
                }

                M_A.Entry(vertex.Index * 2, vertex.Index * 2, -angleWeightSum);
                M_A.Entry(vertex.Index * 2 + 1, vertex.Index * 2 + 1, -angleWeightSum);
                M_X.Entry(vertex.Index * 2, vertex.Index * 2, -areaWeightSum);
                M_X.Entry(vertex.Index * 2 + 1, vertex.Index * 2 + 1, -areaWeightSum);
            }

            // Free boundary
            foreach (var vertex in meshin.Vertices.Where(v => v.OnBoundary))
            {
                var weightSum = 0d;

                // Inner edges
                foreach (var halfEdge in vertex.Halfedges.Where(he => !he.Edge.OnBoundary))
                {
                    // cot(alpha) + cot(beta)
                    var borderWeight = halfEdge.Previous.Traits.Cotan + halfEdge.Opposite.Previous.Traits.Cotan;

                    M_A.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, -borderWeight);
                    M_A.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, -borderWeight);
                    M_X.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, -borderWeight);
                    M_X.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, -borderWeight);

                    weightSum += borderWeight;
                }

                // Boundary edges
                foreach (var halfEdge in vertex.Halfedges.Where(he => he.Edge.OnBoundary))
                {
                    // Last edge
                    if (halfEdge.OnBoundary)
                    {
                        var borderWeight = halfEdge.Opposite.Previous.Traits.Cotan;

                        // Weight edge by cotan once and substract the rotated uv vector
                        M_A.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, -borderWeight);
                        M_A.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2 + 1, -1);
                        M_A.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, -borderWeight);
                        M_A.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2, 1);

                        M_X.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, -borderWeight);
                        M_X.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2 + 1, -1);
                        M_X.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, -borderWeight);
                        M_X.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2, 1);

                        weightSum += borderWeight;
                    }
                    // First edge
                    else
                    {
                        // cot(alpha) + cot(beta)
                        var borderWeight = halfEdge.Previous.Traits.Cotan;

                        // Weight edge by cotan once and substract the rotated uv vector
                        M_A.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, -borderWeight);
                        M_A.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2 + 1, 1);
                        M_A.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, -borderWeight);
                        M_A.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2, -1);

                        M_X.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2, -borderWeight);
                        M_X.Entry(vertex.Index * 2, halfEdge.ToVertex.Index * 2 + 1, 1);
                        M_X.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2 + 1, -borderWeight);
                        M_X.Entry(vertex.Index * 2 + 1, halfEdge.ToVertex.Index * 2, -1);

                        weightSum += borderWeight;
                    }
                }

                M_A.Entry(vertex.Index * 2, vertex.Index * 2, weightSum);
                M_A.Entry(vertex.Index * 2 + 1, vertex.Index * 2 + 1, weightSum);
                M_X.Entry(vertex.Index * 2, vertex.Index * 2, weightSum);
                M_X.Entry(vertex.Index * 2 + 1, vertex.Index * 2 + 1, weightSum);
            }

            // Fixed vertices

            // M^n
            M_A.Entry(2 * vertexCount, 2 * P1Index, 1);
            M_A.Entry(2 * vertexCount + 1, 2 * P1Index + 1, 1);
            M_X.Entry(2 * vertexCount, 2 * P1Index, 1);
            M_X.Entry(2 * vertexCount + 1, 2 * P1Index + 1, 1);

            M_A.Entry(2 * vertexCount + 2, 2 * P2Index, 1);
            M_A.Entry(2 * vertexCount + 3, 2 * P2Index + 1, 1);
            M_X.Entry(2 * vertexCount + 2, 2 * P2Index, 1);
            M_X.Entry(2 * vertexCount + 3, 2 * P2Index + 1, 1);

            // M^n transp
            M_A.Entry(2 * P1Index, 2 * vertexCount, 1);
            M_A.Entry(2 * P1Index + 1, 2 * vertexCount + 1, 1);
            M_X.Entry(2 * P1Index, 2 * vertexCount, 1);
            M_X.Entry(2 * P1Index + 1, 2 * vertexCount + 1, 1);

            M_A.Entry(2 * P2Index, 2 * vertexCount + 2, 1);
            M_A.Entry(2 * P2Index + 1, 2 * vertexCount + 3, 1);
            M_X.Entry(2 * P2Index, 2 * vertexCount + 2, 1);
            M_X.Entry(2 * P2Index + 1, 2 * vertexCount + 3, 1);

            // b^n
            x[2 * vertexCount]     = P1UV.X;
            x[2 * vertexCount + 1] = P1UV.Y;
            x[2 * vertexCount + 2] = P2UV.X;
            x[2 * vertexCount + 3] = P2UV.Y;

            var matrix = SparseMatrix.Add(M_A.Compress(), M_X.Compress(), AngleToAreaRatio, 1 - AngleToAreaRatio);
            var solver = QR.Create(matrix);

            solver.Solve(x);

            for (var vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++)
            {
                bu[vertexIndex] = x[2 * vertexIndex];
                bv[vertexIndex] = x[2 * vertexIndex + 1];
            }

            /// update mesh positions and uv's
            MeshLaplacian.UpdateMesh(meshout, bu, bv, b0, bu, bv);
            MeshLaplacian.UpdateMesh(meshin, bu, bv);
        }
Exemplo n.º 6
0
 /// <summary>
 /// Divides the zones of reduced <see cref="matrix"/>.
 /// </summary>
 /// <param name="model">The model.</param>
 /// <param name="matrix">The reduced matrix.</param>
 /// <param name="dofMap">The DoF map.</param>
 /// <returns></returns>
 /// <exception cref="System.NotImplementedException"></exception>
 public static ZoneDevidedMatrix DivideZones(Model model, CCS matrix, DofMappingManager dofMap)
 {
     //see Calcutil.GetReducedZoneDividedMatrix
     throw new NotImplementedException();
 }
Exemplo n.º 7
0
 /// <summary>
 /// Extracts the free free part.
 /// </summary>
 /// <param name="matrix">The matrix.</param>
 /// <param name="nodeMapping">The node mapping.</param>
 /// <returns></returns>
 /// <exception cref="System.NotImplementedException"></exception>
 public static CCS ExtractFreeFreePart(CCS matrix, int[] nodeMapping)
 {
     throw new NotImplementedException();
 }
        public Tuple <CCS, double[]> CalculateDisplacementPermutation(CCS a)
        {
            //based on this solution : https://github.com/wo80/CSparse.NET/issues/7#issuecomment-317268696

            if (a.RowCount < a.ColumnCount)
            {
                //For a matrix A with rows < columns, SparseQR does a factorization of the transpose A'
                //so we add zero rows to A and make it rectangular!

                var a2 = new CoordinateStorage <double>(a.ColumnCount, a.ColumnCount, a.NonZerosCount);

                foreach (var t in a.EnumerateIndexed())
                {
                    a2.At(t.Item1, t.Item2, t.Item3);
                }

                a = a2.ToCCs();
            }

            SparseMatrix buf;

            var n = a.RowCount;
            var m = a.ColumnCount;

            var order = ColumnOrdering.MinimumDegreeAtA;

            var sp = System.Diagnostics.Stopwatch.StartNew();

            var qr = SparseQR.Create(a, order);

            var t2 = sp.ElapsedMilliseconds;


            var r = GetFactorR(qr);
            var q = GetFactorQ(qr);

            var leads = new int[a.RowCount];

            leads.FillWith(-1);

            var epsilon = 1e-8;

            foreach (var t in r.EnumerateIndexed())
            {
                if (Math.Abs(t.Item3) > epsilon)
                {
                    if (leads[t.Item1] == -1)
                    {
                        leads[t.Item1] = t.Item2;
                    }
                    else
                    {
                        leads[t.Item1] = Math.Min(leads[t.Item1], t.Item2);
                    }
                }
            }

            var leadCount = leads.Count(i => i != -1);

            {
                var nnzApprox = leadCount;
                var p1Crd     = new CoordinateStorage <double>(leadCount, r.RowCount, nnzApprox);
                var p2Crd     = new CoordinateStorage <double>(r.ColumnCount, leadCount, nnzApprox);
                var p2pCrd    = new CoordinateStorage <double>(r.ColumnCount, r.ColumnCount - leadCount, nnzApprox);

                var cnt1 = 0;
                var cnt2 = 0;

                for (var i = 0; i < leads.Length; i++)
                {
                    if (leads[i] != -1)
                    {
                        var j = leads[i];

                        p1Crd.At(cnt1, i, 1);
                        p2Crd.At(j, cnt1, 1);

                        cnt1++;
                    }

                    if (leads[i] == -1)
                    {
                        var j = i;// leads[i];

                        p2pCrd.At(j, cnt2, 1);

                        cnt2++;
                    }
                }

                var p1  = p1Crd.ToCCs();
                var p2  = p2Crd.ToCCs();
                var p2p = p2pCrd.ToCCs();

                //var rp = r.Transpose();

                var rdep = p1.Multiply(r).Multiply(p2);

                var rinDep = p1.Multiply(r).Multiply(p2p);



                var qr2 = SparseQR.Create(rdep, order);

                var t = sp.ElapsedMilliseconds;

                var right = new double[rinDep.RowCount];
                var sol   = new double[rinDep.RowCount];

                var bufCrd = new CoordinateStorage <double>(leadCount, a.ColumnCount - leadCount, leadCount);

                for (var j = 0; j < rinDep.ColumnCount; j++)
                {
                    //put the j'th column of r into the rightSide

                    right.FillWith(0);

                    {
                        var col = j;

                        var st  = rinDep.ColumnPointers[j];
                        var end = rinDep.ColumnPointers[j + 1];

                        for (var ii = st; ii < end; ii++)
                        {
                            var row = rinDep.RowIndices[ii];

                            var val = rinDep.Values[ii];

                            right[row] = val;
                        }
                    }

                    qr2.Solve(right, sol);

                    for (var i = 0; i < rdep.RowCount; i++)
                    {
                        bufCrd.At(i, j, sol[i]);
                    }
                }

                buf = bufCrd.ToCCs();
            }

            //var top = buf.ToDenseMatrix();

            var buft = buf.Transpose();


            var masterCount = a.ColumnCount - 1 - leadCount;

            //var p_d_dense = new Matrix(a.ColumnCount - 1, masterCount);

            var p_d = new CoordinateStorage <double>(a.ColumnCount - 1, masterCount, 1);

            var rightSideDense = new double[a.ColumnCount - 1];
            var rightSide      = new double[a.ColumnCount - 1];

            var cnt  = 0;
            var cnt3 = 0;

            for (var i = 0; i < a.ColumnCount - 1; i++)
            {
                if (leads[i] != -1)
                {
                    /*{//dense
                     *  var rw = top.ExtractRow(cnt).CoreArray;
                     *
                     *  var right = rw.Last();
                     *  Array.Resize(ref rw, rw.Length - 1);
                     *
                     *  for (var j = 0; j < rw.Length; j++)
                     *  {
                     *      p_d_dense[i, j] = -rw[j];
                     *  }
                     *
                     *  rightSideDense[i] = -right;
                     * }*/

                    {//sparse
                        var right = 0.0;

                        foreach (var t in buft.EnumerateColumnMembers(cnt))//enumerate column members of transposed matrix
                        {
                            if (t.Item1 != p_d.ColumnCount)
                            {
                                p_d.At(i, t.Item1, -t.Item2);
                            }
                            else
                            {
                                right = t.Item2;
                            }
                        }

                        rightSide[i] = -right;
                    }


                    cnt++;
                }
                else
                {
                    {
                        var t = cnt3++;
                        //p_d_dense[i, t] = 1;
                        p_d.At(i, t, 1);
                    }
                }
            }

            //var top2 = p_d_dense;//.ToDenseMatrix();
            //var top3 = p_d.ToCCs().ToDenseMatrix();

            //var d = (top2 - top3);
            //var d2 = rightSide.Plus(rightSideDense, -1);


            var pdd = (CCS)p_d.ToCCs();

            return(Tuple.Create(pdd, rightSide));

            var tol = 1e-6;

            throw new NotImplementedException();
        }
Exemplo n.º 9
0
        public Tuple <CCS, double[]> CalculateDisplacementPermutation(CCS a)
        {
            //based on this solution : https://github.com/wo80/CSparse.NET/issues/7#issuecomment-317268696

            if (a.RowCount < a.ColumnCount)
            {
                //For a matrix A with rows < columns, SparseQR does a factorization of the transpose A'
                //so we add zero rows to A and make it rectangular!

                var a2 = new CoordinateStorage <double>(a.ColumnCount, a.ColumnCount, a.NonZerosCount);

                foreach (var t in a.EnumerateIndexed())
                {
                    a2.At(t.Item1, t.Item2, t.Item3);
                }

                a = a2.ToCCs();
            }

            //var adense = a.ToDenseMatrix();

            SparseMatrix buf;

            var n = a.RowCount;
            var m = a.ColumnCount;

            var order = ColumnOrdering.Natural;

            var sp = System.Diagnostics.Stopwatch.StartNew();

            var qr = SparseQR.Create(a, order);

            var t2 = sp.ElapsedMilliseconds;


            var r = GetFactorR(qr);
            var q = GetFactorQ(qr);
            var s = GetSymbolicFactorization(qr);

            var leads = new int[a.RowCount];

            leads.FillWith(-1);
            //leads[i] = columnIndex of first nonzero in i'th row of r fasctor
            //if leads[i] == -1, then there is no nonzero in row[i] then i'th equation in original a matrix in non usable
            //this will be used for rdep and rindep

            var epsilon = 1e-8;


            foreach (var r_item in r.EnumerateIndexed())
            {
                var rowNum = r_item.Item1;
                var colNum = r_item.Item2;
                var val    = r_item.Item3;


                if (Math.Abs(val) <= epsilon)
                {
                    ;                        //then row at
                }
                if (Math.Abs(val) > epsilon) //Then, if abs(R[i, i]) > tol, you found an independent row
                //Make sure to take row permutations into account (again, you can get the SymbolicFactorization containing row and column permutations using reflection)
                {
                    if (leads[rowNum] == -1)
                    {
                        leads[rowNum] = colNum;
                    }
                    else
                    {
                        leads[rowNum] = Math.Min(leads[rowNum], colNum);
                    }
                }
            }



            //throw new NotImplementedException("above section not right");

            var leadCount = leads.Count(i => i != -1);

            {
                var nnzApprox = leadCount;
                var p1Crd     = new CoordinateStorage <double>(leadCount, r.RowCount, nnzApprox);
                var p2Crd     = new CoordinateStorage <double>(r.ColumnCount, leadCount, nnzApprox);
                var p2pCrd    = new CoordinateStorage <double>(r.ColumnCount, r.ColumnCount - leadCount, nnzApprox);

                var cnt1 = 0;
                var cnt2 = 0;

                for (var i = 0; i < leads.Length; i++)
                {
                    if (leads[i] != -1)
                    {
                        var j = leads[i];

                        p1Crd.At(cnt1, i, 1);
                        p2Crd.At(j, cnt1, 1);

                        cnt1++;
                    }

                    if (leads[i] == -1)
                    {
                        var j = i;// leads[i];

                        p2pCrd.At(j, cnt2, 1);

                        cnt2++;
                    }
                }

                var p1  = p1Crd.ToCCs();
                var p2  = p2Crd.ToCCs();
                var p2p = p2pCrd.ToCCs();

                //var rp = r.Transpose();

                var rdep = p1.Multiply(r).Multiply(p2);

                var rinDep = p1.Multiply(r).Multiply(p2p);

                var qr2 = SparseQR.Create(rdep, order);

                var t = sp.ElapsedMilliseconds;

                var right = new double[rinDep.RowCount];
                var sol   = new double[rinDep.RowCount];

                var bufCrd = new CoordinateStorage <double>(leadCount, a.ColumnCount - leadCount, leadCount);

                for (var j = 0; j < rinDep.ColumnCount; j++)
                {
                    //put the j'th column of r into the rightSide

                    right.FillWith(0);

                    {
                        var col = j;

                        var st  = rinDep.ColumnPointers[j];
                        var end = rinDep.ColumnPointers[j + 1];

                        for (var ii = st; ii < end; ii++)
                        {
                            var row = rinDep.RowIndices[ii];

                            var val = rinDep.Values[ii];

                            right[row] = val;
                        }
                    }

                    qr2.Solve(right, sol);

                    for (var i = 0; i < rdep.RowCount; i++)
                    {
                        bufCrd.At(i, j, sol[i]);
                    }
                }

                buf = bufCrd.ToCCs();
            }

            //var top = buf.ToDenseMatrix();

            var buft = buf.Transpose();


            var masterCount = a.ColumnCount - 1 - leadCount;

            //var p_d_dense = new Matrix(a.ColumnCount - 1, masterCount);

            var p_d = new CoordinateStorage <double>(a.ColumnCount - 1, masterCount, 1);

            var rightSideDense = new double[a.ColumnCount - 1];
            var rightSide      = new double[a.ColumnCount - 1];

            var cnt  = 0;
            var cnt3 = 0;

            for (var i = 0; i < a.ColumnCount - 1; i++)
            {
                if (leads[i] != -1)
                {
                    /*{//dense
                     *  var rw = top.ExtractRow(cnt).CoreArray;
                     *
                     *  var right = rw.Last();
                     *  Array.Resize(ref rw, rw.Length - 1);
                     *
                     *  for (var j = 0; j < rw.Length; j++)
                     *  {
                     *      p_d_dense[i, j] = -rw[j];
                     *  }
                     *
                     *  rightSideDense[i] = -right;
                     * }*/

                    {//sparse
                        var right = 0.0;

                        //var rowNum = s.pinv[i];

                        foreach (var t in buft.EnumerateColumnMembers(cnt))//enumerate column members of transposed matrix
                        {
                            var rowNum = i;
                            var colNum = t.Item1;


                            //var colNum = s.q[t.Item1];

                            var value = t.Item2;

                            if (t.Item1 != p_d.ColumnCount)
                            {
                                p_d.At(rowNum, colNum, -value);
                            }
                            else
                            {
                                right = value;
                            }
                        }

                        //rightSide[s.cp[i]] = -right;
                        rightSide[i] = -right;
                    }


                    cnt++;
                }
                else
                {
                    var t = cnt3++;

                    var rowNum = i; // s.pinv[ i];
                    var colNum = t; // s.q[ t];

                    p_d.At(rowNum, colNum, 1);
                }
            }

            //var top2 = p_d_dense;//.ToDenseMatrix();
            //var top3 = p_d.ToCCs().ToDenseMatrix();

            //var d = (top2 - top3);
            //var d2 = rightSide.Plus(rightSideDense, -1);


            var pdd = (CCS)p_d.ToCCs();

            return(Tuple.Create(pdd, rightSide));

            var tol = 1e-6;

            throw new NotImplementedException();
        }