3

I'm creating a custom matrix class that only has a single 2D array to hold everything (I know that a 1D array is faster and better, but that's not the point of this implementation) the thing is, I'd like to have a constructor, and be able to do something like

Matrix a = new Matrix(2,2){{1,2},{3,4}};

and have it all work out. I've run into the "'Matrix' does not contain a definition for 'Add' and no extension method 'Add' etc." but after looking around, I've yet to be able to find robust enough info on how to define the Add() method in order to make it work. Here's the code I have so far

public class Matrix : IEnumerable
    {
        /* What we know abuot matricies
         * - matricies are defined by rows, cols
         * - addition is element-wise
         */

        public IEnumerator GetEnumerator()
        {
            yield return m;
        }

        private void Add(double a)
        {
            // what exactly should go here anyway?
        }

        private double[,] m;

        public double this[int rows, int cols]
        {
            get => m[rows, cols];
            set => m[rows, cols] = value;
        }       

        public Matrix(int rows, int cols)
        {
            m = new double[rows, cols];
        }
    ...
    }

so, how would I go about doing the Add() method anyway?

Frank Boyne
  • 4,400
  • 23
  • 30
Raxmo
  • 57
  • 5

3 Answers3

2

Try this code. Your Add method must be public. Also, to make the code safe, you must add verifiers to check if the sizes of the m matrix and the provided data match.

private int currentRow = 0;
public void Add(params double[] a)
{
    for (int c = 0; c < a.Length; c++)
    {
        m[currentRow, c] = a[c];
    }
    currentRow++;
}

If you don't provide all the rows, the remaining rows will have the elements with their defaults values. Also, note that this method can be called in the future, and it would throw an exception when the m matrix has all the rows filled.

Magnetron
  • 7,495
  • 1
  • 25
  • 41
  • Thanks! it works fine. Since I'm going to be pretty much the only one to use this library, the potential hazards will be fine, I'll just have to be careful. – Raxmo Jul 11 '18 at 18:37
  • @Raxmo Another option is to make the matrix size dinamic, redimensionating the `m`matrix whenever you add rows. That way you could call `Matrix a = new Matrix(){{1,2},{3,4}};` – Magnetron Jul 11 '18 at 18:42
  • the current implementation (with your help) works for my particular usage. However, resizing the matrix while _removing_ rows or columns would actually be VERY useful (for use with matrix math) – Raxmo Jul 14 '18 at 09:24
1

Magnetron's answer is the way to do it if you want to use the collection initializer syntax. This would work better with a jagged array instead of a two-dimensional array; as he points out, it's not possible to do a compile time check to ensure that the number of arguments in the initializer matches the size of the matrix, so you're going to risk runtime errors just initializing the class.

Another approach would be to implement an alternative constructor that allows you to initialize the matrix, like this:

public Matrix(double[,] source)
{
    m = source;
}

Then your line of code would look like this:

Matrix a = new Matrix(new double[,]{ {1,2},{3,4} });

This would avoid the issue since the dimensions of the matrix are determined by the dimensions of the initialization data, which must be a two-dimensional array.

John Wu
  • 50,556
  • 8
  • 44
  • 80
  • While this would work well enough, it's not the kind of syntax that I was going for. Would be easy to implement though. Still a good solution for other applications. – Raxmo Jul 14 '18 at 09:19
1

I know I am late, but what about an extension method of double[,], or even implementing an implicit cast?

class Matrix
{
    // Implicit cast
    public static implicit operator Matrix(double[,] array) => new Matrix(array);

    private double[,] source;
    public Matrix(double[,] source)
    {
        this.source = source;
    }
}
static class Extensions
{
    // Extension
    public static Matrix ToMatrix(this double[,] array)
    {
        return new Matrix(array);
    }
}
static class Program
{
    static void Main()
    {
        // Extension
        Matrix a = new double[,] {
            { 1.0, 2.0, 3.0 },
            { 1.0, 2.0, 3.0 },
            { 1.0, 2.0, 3.0 }
        }.ToMatrix();

        // Implicit cast
        Matrix b = new double[,] {
            { 1.0, 2.0, 3.0 },
            { 1.0, 2.0, 3.0 },
            { 1.0, 2.0, 3.0 }
        };
    }
}
Carlos
  • 586
  • 1
  • 9
  • 19
  • I really do love this implementation. Will likely be my future implimentation probably, though, megatron's answer is more of a direct answer to my question as stated. – Raxmo Apr 28 '21 at 18:39