mathnet / mathnet-numerics

Math.NET Numerics
http://numerics.mathdotnet.com
MIT License
3.47k stars 893 forks source link

Operator '*' cannot be applied to operands of type 'MathNet.Numerics.LinearAlgebra.Complex.DenseMatrix' and 'MathNet.Numerics.LinearAlgebra.Double.DenseMatrix' #304

Open PawelTroka opened 9 years ago

PawelTroka commented 9 years ago

Operator '*' cannot be applied to operands of type 'MathNet.Numerics.LinearAlgebra.Complex.DenseMatrix' and 'MathNet.Numerics.LinearAlgebra.Double.DenseMatrix' Same goes for =,-,%,/

Also when you are trying to multiply by complex number Double.DenseMatrix it isnt working too.

I think that It would be nice if we had implicit conversion from MathNet.Numerics.LinearAlgebra.Double.DenseMatrix to MathNet.Numerics.LinearAlgebra.Complex.DenseMatrix :)

PawelTroka commented 7 years ago

My implementation proposal

Under Matrix<T> / Vector<T> classes we can add operator implicit

        public static implicit operator Matrix<Complex64>(Matrix<T> matrix)
        {
            return matrix.Map(x => (Complex64)(object)x, Zeros.AllowSkip);
        }

This is very simple and it will work in all cases where there is a cast avalaible from T to Complex64 so in all cases it should.

Another option could be something like the following:

        public static implicit operator Matrix<Complex64>(Matrix<T> matrix)
        {
            var matrixDouble = matrix as Matrix<double>;
            if (matrixDouble != null)
                return matrixDouble.ToComplex();

            var matrixFloat = matrix as Matrix<float>;
            if (matrixFloat != null)
                return matrixFloat.ToDouble().ToComplex();

            var matrixComplex32 = matrix as Matrix<Numerics.Complex32>;
            if (matrixComplex32 != null)
                return matrixComplex32.ToComplex();

            throw new InvalidCastException(string.Format("Cannot convert from {0} to {1}", typeof(T), typeof(Complex64)));
        }

I don't like option 2 honestly because the code is longer and it still will not work in all cases (example Matrix<int>).

There is also option 3 which requires ToComplex extension method to be done for more types.

        public static implicit operator Matrix<Complex64>(Matrix<T> matrix)
        {
            dynamic dynamicMatrix = matrix;
            return dynamicMatrix.ToComplex();
        }

I don't like it thought because it uses dynamic.

I would go with option 1 and there is also possibility for extending it further - adding implicit conversion to Matrix<double> (from Matrix<int> etc).

I think that in the end we should have the same implicit conversions for Matrix<T>, Vector<T> that there are for T (there is conversion from int to double -> there should be from Matrix<int> to Matrix<double> etc).