Thomas
Thomas

Reputation: 12107

Types with Math.net numerics

I am starting to use the Math.net numerics library and I can't find examples, so I'm running into a few issues:

To make a simple example, I have two arrays of doubles. I want to divide one by the other and then calculate the moving average.

So, the code looks like this:

var VD1 = Vector<double>.Build.Dense(Data1.ToArray());
var VD2 = Vector<double>.Build.Dense(Data2.ToArray());
var R = VD1 / VD2;
var SMA = R.MovingAverage(15);            

The problem is that, on the way, the data type changes. It starts as 2 Vectors, the division result is a Vector and the SMA result is not, it's an IEnumerable<double>.

So, now if I want to plug that result into more functions, for example multiply it by another array, I can't. I have to rebuild a Vector from the result.

Am I somehow doing this wrong? I can't imagine that the API would bounce back and forth between different but similar types.

Upvotes: 2

Views: 380

Answers (1)

CSDev
CSDev

Reputation: 3235

You are doing it right. That is how MathNet is designed. E.g., var R = VD1 / VD2; calls

// Summary: Pointwise divides two Vectors.
public static Vector<T> operator /(Vector<T> dividend, Vector<T> divisor);

and returns Vector<T>.

var SMA = R.MovingAverage(15); calls

public static IEnumerable<double> MovingAverage(this IEnumerable<double> samples, int windowSize);

and returns IEnumerable<double>.

You can call MovingAverage with Vector<double> R, because Vector<double> implements IEnumerable<double> and you get implicit casting. But MovingAverage does not know its argument is Vector<double>, it's designed to return IEnumerable<double>. And that makes sense. As far as I remember from colledge, moving average is about time series and it has no explicit relationship to vectors.

But you can have some workarounds. For example your own overload for MovingAverage:

static class VectorHeplper
{
    public static Vector<double> MovingAverage(this Vector<double> samples, int windowSize)
    {
        return DenseVector.OfEnumerable(samples.AsEnumerable().MovingAverage(windowSize));
    }
}

Then var SMA = R.MovingAverage(15); is Vector<double>.

Anyway, building a new instance of Vector is the right and logical way.

Upvotes: 3

Related Questions