0

I need to multiply two relatively large matrices and do it many times (in a loop). However, the format (type of objects) how these matrices are stored in the memory should be chosen by user. There are three possibilities:

  1. double [,] M1; double [,] M2; ( two-dimensional arrays)

  2. double[][] M1; double [][]M2; ( jagged arrays).

  3. Matrix <double> M1;Matrix <double> M2; ( Math Net Numerics format).

Each format suits a corresponding method ( taken from a numerical library as you may have already guessed). I need to avoid boxing and unboxing at all cost ( since its expensive) so the following code will not work for me ( unless you tell me that boxing/unboxing is cheaper than fast matrix multiplication):

object M1;
object M2;

switch case 
{
    case 1:
        M1 = new double[rows,columns];
    .../etc
}

One way to solve it is very straightforward: just to declare 6 matrices( 6 variables) and at runtime initialize two of them. But this looks ugly and will make the code much more complicated.

My question: is there any elegant solution of this problem? I am new to C# but the searching over the site did not help me much.

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
user3786219
  • 177
  • 1
  • 2
  • 11
  • Why not just use overloads of a method that take different types of arguments? E.g., `Calculate(double[,] M1, double[,] M2)`, `Calculate(double[][] M1, double[][] M2)`, etc.? – Heretic Monkey Apr 08 '19 at 23:03
  • can you point where do you think boxing will occur? – Iłya Bursov Apr 08 '19 at 23:06
  • Overloading is already implemented in the code. However, I do not want to pass a dynamic object (objects) to the method. – user3786219 Apr 08 '19 at 23:08
  • Arrays and `Matrix` are all classes so they don't suffer from boxing. What boxing do you see? – Enigmativity Apr 08 '19 at 23:10
  • I suppose you're mixing boxing and casting, as `double[]` is object already, there is no boxing – Iłya Bursov Apr 08 '19 at 23:10
  • @IłyaBursov What I am saying that M1 and M2 are objects, right? Thus, they have to be unboxed when I pass them to a method? – user3786219 Apr 08 '19 at 23:13
  • @user3786219 of course no, you even cannot unbox them into scalar type – Iłya Bursov Apr 08 '19 at 23:16
  • Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type.. Array types are reference types derived from the abstract base type Array.. (This is all laid out in the documentation), meaning storing an array in an object is not boxing – TheGeneral Apr 08 '19 at 23:27
  • I don't understand what this question is asking; there's no boxing, so asking how to avoid the boxing penalty is a non-starter. It sounds like you have what we call an "XY" problem; you have some real problem, you have some incorrect belief about that problem, and now you're asking a nonsensical question about that incorrect belief. What's the real problem you're trying to solve? – Eric Lippert Apr 09 '19 at 00:16
  • 2
    You say that you have a "dynamic" object. **Is it of type `dynamic`?** If so, then you have a serious performance problem in the making but it has nothing to do with boxing; boxing is the least of your worries when you use `dynamic`. Using `dynamic` *starts the compiler again at runtime*. That's *not fast*. – Eric Lippert Apr 09 '19 at 00:17
  • @EricLippert - Can you please expound on "_starts the compiler again at runtime_"? – Enigmativity Apr 09 '19 at 02:42
  • 3
    @Enigmativity: Eric Lippert's Explanation: https://stackoverflow.com/a/7480977/18192 – Brian Apr 09 '19 at 12:10
  • @Brian: Thanks for posting the link! – Eric Lippert Apr 09 '19 at 19:31

1 Answers1

0

Yes, you are all right, there is no boxing/unboxing here. I figured out what I want and need to do. I will create an interface which declares some matrix methods:

interface MatrixMethods
{
   void MatrixIni();
   void DoMultiplication();
   double ReturnFinalResult();
// etc
}

Then I will use a generic class:

class MatrixStorage <T> 
{
  protected T M1;
  protected T M2;
// etc
}

and finally the needed class:

    class MatrixMult<T> : MatrixStorage<T> , MatrixMethods
{
    public void MatrixIni()
    {
        //etc Matrix random ini
    }
    public void DoMultiplication()
    {
        // multiplication
    }
    public double ReturnFinalResult()
    {
        // compute output
    }
    MatrixMult(params int[] input)
    {
        // ini
    }

}

and, then I instantiate the class and do calculations:

MatrixMethods newMatrixMult;
newMatrixMult = new MatrixMult<UserMatrixType>(userData);
newMatrixMult.DoMultiplication();
double result = newMatrixMult.ReturnFinalResult

I apologize for a misleading question. Best

user3786219
  • 177
  • 1
  • 2
  • 11