/// <summary>
        /// Linear system solution x = inv(A) * b, with A being a triangular matrix in Skyline format. See
        /// https://software.intel.com/node/0a9d506f-d424-4651-8e68-16625ed412e7#0A9D506F-D424-4651-8E68-16625ED412E7
        /// Warning: Intel MKL's Skyline format uses 1-based indexing and the non zero entries of each column are ordered from
        /// the top to the diagonal, if the upper triangle is stored. See
        /// https://software.intel.com/en-us/mkl-developer-reference-c-sparse-blas-skyline-matrix-storage-format
        /// In constrast, in the current version of our Skyline matrix, 0-based indexing is used and the entries of each column
        /// are ordered from the diagonal to the top.
        /// </summary>
        public void Dskysv(bool upper, int orderA, double[] valuesA, int[] colOffsetsA, double[] b, double[] x)
        {
            string trans    = "N";    //TODO: not sure about this
            string matdscrA = "SUNF"; // symmetric, upper, non-unit, fortran indexing
            double alpha    = 1.0;

            SpBlas.MklDskysv(trans, ref orderA, ref alpha, matdscrA, ref valuesA[0], ref colOffsetsA[0],
                             ref b[0], ref x[0]);
        }
        /// <summary>
        /// See
        /// https://software.intel.com/en-us/mkl-developer-reference-fortran-mkl-cspblas-csrgemv#9E1032C5-F844-42D4-A0F0-D62E52D77020
        /// </summary>
        public void Dcsrgemv(bool transposeA, int numRowsA, int numColsA, double[] valuesA, int[] rowOffsetsA, int[] colIndicesA,
                             double[] vectorX, int offsetX, double[] vectorY, int offsetY)
        {
            //TODO: For some reason, the resultis added to vector y, instead of overwritting it. Perhaps this behaviour is
            //      different in the non-deprecated routines.
            if (transposeA)
            {
                Array.Clear(vectorY, offsetY, numColsA);

                // This MKL function is only for square CSR matrices. We can use it for rectangular too, but it overwrites memory
                // of the rhs vector y equal to the number of matrix rows. If the rhs vector is shorter than that, then the
                // remaining entries are overwritten with 0. However, this messes up the managed vector objects, since
                // important data is overwritten (why doesn't it throw access violation exception?). For now I am going to
                // use a temp array and then copy the relevant part. This problem does not seem to appear in the untransposeAd
                // version of the method.
                //TODO: Try using the SparseBLAS inspector-executor routines, instead of the deprecated dcsrgemv().
                if (numColsA < numRowsA) // Do not use y.Length, since y can be an unrolled matrix
                {
                    var temp = new double[numRowsA];
                    SpBlas.MklCspblasDcsrgemv("T", ref numRowsA, ref valuesA[0], ref rowOffsetsA[0], ref colIndicesA[0],
                                              ref vectorX[offsetX], ref temp[0]);
                    Array.Copy(temp, 0, vectorY, offsetY, numColsA);
                }
                else
                {
                    SpBlas.MklCspblasDcsrgemv("T", ref numRowsA, ref valuesA[0], ref rowOffsetsA[0], ref colIndicesA[0],
                                              ref vectorX[offsetX], ref vectorY[offsetY]);
                }
            }
            else
            {
                Array.Clear(vectorY, offsetY, numRowsA);
                SpBlas.MklCspblasDcsrgemv("N", ref numRowsA, ref valuesA[0], ref rowOffsetsA[0], ref colIndicesA[0],
                                          ref vectorX[offsetX], ref vectorY[offsetY]);
            }
        }