• C++ Programming for Financial Engineering
    Highly recommended by thousands of MFE students. Covers essential C++ topics with applications to financial engineering. Learn more Join!
    Python for Finance with Intro to Data Science
    Gain practical understanding of Python to read, understand, and write professional Python code for your first day on the job. Learn more Join!
    An Intuition-Based Options Primer for FE
    Ideal for entry level positions interviews and graduate studies, specializing in options trading arbitrage and options valuation models. Learn more Join!

Method Overloading

Joined
2/21/10
Messages
50
Points
18
Look I have 2 or 3 parameters(see the code below) and I want to make sure that Im protected against all the incoming data types (int, long,double) So I have defined a method via double types. What should I do now? Provide the same method with all the combinations of data types??? Cast them to double and invoke the original double method which exposes its implementation????

C++:
public static double[,] MAdd(double[,] matrixA, double[,] matrixB)
{
    int n = matrixA.GetLength(0);
    int m = matrixA.GetLength(1);
    double[,] matrixS = new double[n, m];
    if ((n == matrixB.GetLength(0)) && (m == matrixB.GetLength(1)))
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                matrixS[i, j] = matrixA[i, j] + matrixB[i, j];
            }
        } return matrixS;
    }
    else 
        Console.WriteLine("Error! Matrix dimensions must exactly match!"); 
    return matrixS;
}
 
1. Do you know how to use CODE tags (here on Quantnet forums)?
2. Have you ever heard of generics in Java? That would be one of the ways to approach your problem. Google it and read about it.
 
what are you trying to do? This has already being done. Don't try to re-invent the wheel.
 
A generic implementation, will only work for .net 4.0 though. Don't know about performance penalty because of dynamic cast though.

C++:
public static T[,] MAdd<T>(T[,] matrixA, T[,] matrixB) where T : struct
        {
            int n = matrixA.GetLength(0);
            int m = matrixA.GetLength(1);

            T[,] matrixS = new T[n, m];
            if ((n == matrixB.GetLength(0)) && (m == matrixB.GetLength(1)))
            {
                for (int i = 0; i < n; i++)
                {
                    for (int j = 0; j < m; j++)
                    {
                        matrixS[i, j] = (dynamic)matrixA[i, j] + matrixB[i, j];
                    }
                } return matrixS;
            }
            else
                Console.WriteLine("Error! Matrix dimensions must exactly match!");
            return matrixS;
        }
 
C# generics and matrix operator overloading don't mix well. One solution is to use Reflection to generate code. I have not used 'dynamic'. Feells like it is a run-time phenomenon, But maybe it generates IL code...

In many cases T = double, so a work around is just to use matrix that uses doubles. And you don't get so much hassle.

This aspect of C# generics is less developed than C++ templates.
 
Here's the gist; I define generic operator overloading which calls Reflection code called
GenericOperatorFactory. This works on 3.0 as well:

!!!! The QN editor does NOT recognise syntax "<<T>>" thus the code gets mangled<T>

class NumericMatrix<<T>><T>
{
...
publicstatic NumericMatrix<T<T>><T> operator +( NumericMatrix<<T>><T> m1, NumericMatrix<<T>><T> m2 )
{
NumericMatrix<<T>><T> temp_matrix =
new NumericMatrix<<T>><T>( m1.Rows, m1.Columns, m1.MinRowIndex, m1.MinColumnIndex );
int i, j;
if( addTT == null )
{
addTT = GenericOperatorFactory<T, T, Vector<T>>.Add;

}

for( i = m1.MinColumnIndex; i <= m1.MaxColumnIndex; i++ )
for( j = m1.MinRowIndex; j <= m1.MaxRowIndex; j++ )
temp_matrix[ j, i ] = addTT( m1[ j, i ], m2[ j, i ] );
return temp_matrix;
}

...
}
 
'dynamic' is a fantastic feature in .net 4.0 that makes alot of things possible. The problem with generics as you probably know is that the use of operators are not allowed with generic types. Although code is written as generic the type is applied to the code at compile time, it would have been great if .net had a numeric generic constraint which would have made the use of operators seamless but since this feature is lacking it won't be known until compile time if the type applied allows the use of a certain operator. Here is where the magic of 'dynamic' comes in, it skips type or even object member checking until runtime i.e. if at runtime it finds out that the type supplied has no overload for the '+' operator it would only blow up then and only then. For example, the code below will compile but blow up at runtime;

C++:
dynamic sample = new Object();
sample.IAmNotAMemberOfTheObjectClass();

Casting to dynamic in my example earlier allows the verification of the use of the '+' operator to be skipped until runtime at which point the type of the variable will be resolved to the type supplied as an argument.
 
Since 'dynamic' is run-time (late binding) it will be a performance hit (how much?) and if you want code to be robust exception handing try/catch should be introduced. Not sure if these are the features you want to have in a matrix, which I presume should be _very_ efficient??

Nonethesless, 'dynamic' is a useful feature.

"if at runtime it finds out that the type supplied has no overload for the '+' operator it would only blow up then and only then. For example, the code below will compile but blow up at runtime;"

ouch! the developer does not see the error, but the trader does?
 
Since 'dynamic' is run-time (late binding) it will be a performance hit (how much?)

Yes and don't know how much. I did mention the performance penalty it would incur, my example was just to show how one would convert that block of code into a generic implementation. Personally I would stick with the double type for matrix calculation and not bother.

ouch! the developer does not see the error, but the trader does?

As long as the programmer is careful not to pass a none numeric type as argument, it should be fine.
 
As long as the programmer is careful not to pass a none numeric type as argument, it should be fine.

Unfortunately, all software error are caused by human :) I am sorry, but this is scary. This leads to buggy code.

Even if the human is careful, may not be enough. Your _generated_ data may be inputted and may even be NaN. Result, run-time crash.

//
I like this from Edsger Dijkstra

"The competent programmer is fully aware of the limited size of his own skull. He therefore approaches his task with full humility, and avoids clever tricks like the plague. "
 
Unfortunately, all software error are caused by human :) I am sorry, but this is scary. This leads to buggy code.

Even if the human is careful, may not be enough. Your _generated_ data may be inputted and may even be NaN. Result, run-time crash.

//
I like this from Edsger Dijkstra

"The competent programmer is fully aware of the limited size of his own skull. He therefore approaches his task with full humility, and avoids clever tricks like the plague. "

Agreed, missed the possibility of NaN although it won't throw a runtime exception during the matrix add operation as NaN is still of type double but its still an error that cannot be checked non the less and will lead to bigger problems. Like i said i wouldn't bother with a generic implementation.
 
You could also use delegates and closures if you'd like to avoid using 'dynamic'. Here's an example, though I'd clean it up a bit (specifically, remove the casts from the inside loop) before using it in practice.

If I had to write something like this though, I'd prefer to use F# these days, since the type inference takes care of this sort of problem automagically. Or, use Math.NET (mathdotnet.com) since it's already got a good matrix implementation.

C++:
// This delegate represents a method which performs an operation on a certain element (specified by x, y) of a matrix
private delegate void MatrixOperationAction(int x, int y);

private static T[,] MatrixAdd&lt;T&gt;<t>(T[,] matrixA, T[,] matrixB)
    where T : struct
{
    // Make sure that T is a supported type
    if (typeof(T) != typeof(int) && typeof(T) != typeof(float) && typeof(T) != typeof(double)) { throw new ArgumentException(String.Format("Matrices with element type '{0}' are not supported by this method.", typeof(T).Name)); }

    // Get dimensions of matrixA
    int n = matrixA.GetLength(0);
    int m = matrixA.GetLength(1);

    // Make sure that input matrix sizes match
    if ((n != matrixB.GetLength(0)) || (m != matrixB.GetLength(1))) { throw new ArgumentException("The dimensions of the input matrices do not match."); }

    // Create the output matrix
    T[,] matrixS = new T[n, m];

    // Create a local variable which will hold a delegate wrapping an anonymous method (which will perform the addition operation)
    // Then, based on typeof(T), populate the variable with the correctly-typed anonymous method
    MatrixOperationAction AddAction = null;
    if (typeof(T) == typeof(int))
    {
        AddAction = (i, j) =>
        {
            ((int[,])(object)matrixS)[i, j] = ((int[,])(object)matrixA)[i, j] + ((int[,])(object)matrixB)[i, j];
        };
    }
    else if (typeof(T) == typeof(double))
    {
        AddAction = (i, j) =>
        {
            ((double[,])(object)matrixS)[i, j] = ((double[,])(object)matrixA)[i, j] + ((double[,])(object)matrixB)[i, j];
        };
    }
    // TODO: Support other types
    else { throw new NotSupportedException(String.Format("Matrices with element type '{0}' are not supported by this method.", typeof(T).Name)); }

    // Iterate over the matrix elements and invoke the operation on each
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            AddAction(i, j);
        }
    }

    return matrixS;
}
</t>
 
Matrix addition

David! Define them with the double type and then explicitly cast any incoming value in the scope invoking. Programming Fear: "Do not duplicate the code" as it is a maintaince nightmare.


C++:
public static double[,] MAdd(double[,] matrixA, double[,] matrixB)
{
    int n = matrixA.GetLength(0);
    int m = matrixA.GetLength(1);
    double[,] matrixS = new double[n, m];
    if ((n == matrixB.GetLength(0)) && (m == matrixB.GetLength(1)))
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                matrixS[i, j] = matrixA[i, j] + matrixB[i, j];
            }
        } return matrixS;
    }
    else 
        Console.WriteLine("Error! Matrix dimensions must exactly match!"); 
    return matrixS;
}


Then simply invoke the code casting any array intended to pass to double.
 
Thank you Tsotne. I need to define the MMult (matrix multiplication) method in the same manner, now thinking of the algorithm. Any ideas? I have already taken your advice into account to cast them explicitly from the caller's scope
 
Multiplication

Well you know, programming is a kinda art of fantasy. You can come up with many ways to define the matrix multiplication algorithm. I have personally defined such that it takes into account your error checking strategy in the console window message. Look at this.

C++:
public static double[,] MMult(double[,] matrixA, double[,] matrixB)
        {
            int n = matrixA.GetLength(0);   //rows
            int m = matrixA.GetLength(1);   //columns
            int a = matrixB.GetLength(0);   //rows
            int b = matrixB.GetLength(1);   //columns
            double[,] MM = new double[n, b];

            if (m == a)
            {
                int k = 0;

                for (int i = 0; i < n; i++)
                {
                    for (int j = 0; j < b; j++)
                    {
                        while (k < m)
                        {
                            MM[i, j] += matrixA[i, k] * matrixB[k, j];
                            k++;
                        }
                        k = 0;
                    }
                }
                return MM;
            }
            else
                Console.WriteLine("Error! Columns of the first matrix must be the same as the raws of the second matrix!");
            return MM;
        }

Also in the same vein, you just define any numeric array and pass it, but remember explicitly cast the types of incoming arguments. But actually this matrix is defined to work for 2 dimensional matrix originally. You can also overload the method at least for the sake of providing intellisense of the arguments required. For example you can also define the method multiplying 2 dimensional array by scalar, vector,etc. I think you'll handle the case. Good luck with that
 
Back
Top