About IDOKSparseMatrix and DOKSparseMatrixBase

After much self-deliberation, I decided that the sparse matrix must be abstracted. The primary inspiration of the sparse matrix's design in Mendz.Graphs came from Wolfram where the SparseArray is shown as a collection of coordinates and their values ((0, 0) -> 1, (3, 1) -> 3, (7, 5) -> 5, ...).

The sparse matrix can be abstracted as: IDictionary<K, T>. Note that currently, K can either be (int row, int column) coordinates or int linear index.

IDOKSparseMatrix.cs
using System.Collections.Generic;

namespace Mendz.Library.Matrices
{
    public interface IDOKSparseMatrix<K, T>
    {
        T this[int row, int column] { get; }

        IDictionary<K, T> Matrix { get; }

        (int rows, int columns) Size { get; }

        MatrixLinearIndexMode LinearIndexMode { get; }

        T Default { get; }

        T Diagonal { get; }

        bool IsConcurrent { get; }

        T GetEntry(K key);

        void SetEntry(K key, T value);
    }
}

This code defines the interface of a sparse matrix. The IDOKSparseMatrix interface is implemented by DOKSparseMatrixBase.

DOKSparseMatrixBase.cs
using System.Collections.Generic;

namespace Mendz.Library.Matrices
{
    public abstract class DOKSparseMatrixBase<M, K, T> : IDOKSparseMatrix<K, T>
        where M : IDictionary<K, T>, new()
    {
        protected DOKSparseMatrixBase((int rows, int columns) size, 
            MatrixLinearIndexMode linearIndexMode = MatrixLinearIndexMode.RowMajorOrder, 
            T defaultValue = default(T), T diagonal = default(T))
        {
            Matrix = new M();
            Size = size;
            LinearIndexMode = linearIndexMode;
            Default = defaultValue;
            Diagonal = diagonal;
        }

        #region Implements
        public T this[int row, int column]
        {
            get
            {
                MatrixCoordinates.CheckCoordinates(Size, row, column);
                K key;
                if (typeof(K) == typeof(int))
                {
                    key = (dynamic)MatrixCoordinates.ToLinearIndex(
                        Size, row, column, LinearIndexMode);
                }
                else
                {
                    key = (dynamic)(row, column);
                }
                if (Matrix.ContainsKey(key))
                {
                    return GetEntry(key);
                }
                else
                {
                    return (row == column) ? Diagonal : Default;
                }
            }
        }

        public M Matrix { get; private set; }

        public (int rows, int columns) Size { get; private set; }

        public MatrixLinearIndexMode LinearIndexMode { get; private set; }

        public T Default { get; private set; }

        public T Diagonal { get; private set; }

        public virtual bool IsConcurrent { get; protected set; } = false;

        public T GetEntry(K key)
        {
            return Matrix[key];
        }

        public virtual void SetEntry(K key, T value)
        {
            if (Matrix.ContainsKey(key))
            {
                Matrix[key] = value;
            }
            else
            {
                Matrix.Add(key, value);
            }
        }
        #endregion

        #region Explicit Implements
        IDictionary<K, T> IDOKSparseMatrix<K, T>.Matrix => Matrix;

        (int rows, int columns) IDOKSparseMatrix<K, T>.Size => Size;

        MatrixLinearIndexMode IDOKSparseMatrix<K, T>.LinearIndexMode => LinearIndexMode;

        T IDOKSparseMatrix<K, T>.Default => Default;

        T IDOKSparseMatrix<K, T>.Diagonal => Diagonal;

        bool IDOKSparseMatrix<K, T>.IsConcurrent => IsConcurrent;

        T IDOKSparseMatrix<K, T>.GetEntry(K key) => GetEntry(key);

        void IDOKSparseMatrix<K, T>.SetEntry(K key, T value) => SetEntry(key, value);
        #endregion
    }
}

DOKSparseMatrixBase provides the basic implementations of the IDOKSparseMatrix members. The indexer is implemented to simulate matrix-like access. Note that the IDOKSparseMatrix members are also explicitly implemented.

Comments