Is there a way to automatically cast double argument to Vector?

104 Views Asked by At

I am currently using the Math.NET Numerics library in a .NET project, and I find myself often writing code like the following:

public double Foo(Vector<double> x)
{
    ...
}

...

public double Foo(double x)
{
    return Foo(Vector<double>.Build.Dense(1, x));
}

The Vector class is from the Math.NET library, and the idea here is that a one-element vector is really just a scalar, so it is both convenient and intuitive to be able to call Foo with a double argument when the input happens to be 1-dimensional. The call Vector<double>.Build.Dense(1, x) implements the type conversion from double to Vector<double>.

Is there any way to automate this conversion? That is, some way to have double implicitly cast as Vector<double> when calling a function taking a Vector<double> argument?

3

There are 3 best solutions below

1
Heinzi On BEST ANSWER

What you want is to define an implicit cast operator as an extension, i.e., for two classes which are not under your control.

Unfortunately, at the time of writing (Sept 2023), this is currently not supported by C#. This feature has been requested multiple times and is being discussed at the C# language repository:

2
Mad hatter On

Here is a sample of extension method from double to Vector<double> This will not answer totally your question, but will get rid of code duplication at least.

public static class DoubleExtensions
{
    public static Vector<double> ToVector(this double x)
    {
        return Vector<double>.Build.Dense(1, x);
    }
}

Use it this way

public void Foo(double d)
{
    var vector = d.ToVector();
}
0
ummg On

Here's what I'm trying right now. It seems to cover my usecase pretty well, but please tell me what you think of it.

First I followed the suggestion in Mad hatter's answer and implemented a couple of extension methods:

public static class DoubleExtensions
{
    public static Vector<double> ToVector(this double x)
    {
        return Vector<double>.Build.Dense(1, x);
    }

    public static Vector<double>[] ToVectorArray(this double[] x)
    {
        var vectors = new Vector<double>[x.Length];

        for (int i = 0; i < x.Length; i++)
        {
            vectors[i] = x[i].ToVector();
        }

        return vectors;
    }
}

Then I wrote an abstract superclass that defines the various function signatures and type conversions:

public abstract class Distribution
{
    public abstract double Density(Vector<double> x);

    public double[] Density(Vector<double>[] x)
    {
        var y = new double[x.Length];

        for (int i = 0; i < x.Length; i++)
        {
            y[i] = Density(x[i]);
        }

        return y;
    }

    public double Density(double x) => Density(x.ToVector());

    public double[] Density(double[] x) => Density(x.ToVectorArray());
}

This is the code from my actual use case, so I have done away with the Foo artifice. Note also that I define a couple of more conversions than stated in the original question. I want Density to be callable both with a single vector input and with an array of vector inputs. And for both of these I want to also be able to call with ordinary doubles in the scalar case.

The subclasses will only have to implement the one abstract method:

public class SomeParticularDistribution : Distribution
{
    public override double Density(Vector<double> x)
    {
        ...
    }

    ...
}

It feels a little bit weird having the superclass be an abstract class instead of an interface, but I couldn't find a nice way to do it with an interface since I need to implement a few of the methods in the superclass (that is sort of the whole point).