I am working with NumSharp and a bit new to it. I would like to set multiple data values and there are two main functions of concern:
NDArray.SetValue(object value, param int[] indices)
NDArray.SetData(object value, param int[] indices)
The first one SetValue
expects full index of a single value element, for example, if you have np.zeros(3,3)
it expects full indexing, and if there is missing index it will use 0
in its place.
For example:
var arr = np.zeros(3,3);
arr.SetValue(10.0, 0);
arr.SetValue(10.0, 0, 0);
Both lines are equivalent.
On the other hand, SetData
will modify an entire sub-array based on the index, and if you give full index, it works like SetValue
. For example:
arr.SetData(10.0, 0); // sets all arr[0] values to 10
arr.SetData(10.0, 0, 1); // sets arr[0][1] to 10
Now, for my use case, I would like to redefine a function that accepts multiple values and treats each one as a sub-array index.
arr.SetMultiData(10.0, 0, 1); /// sets arr[0] and arr[10] values to 10
Naturally, I went for an extension method:
public static class Extensions
{
public static void SetMultiData(this NDArray arr, object value, int[] indices)
{
foreach (var i in indices)
arr.SetData(value, i);
}
}
But here is what completely lost me. This code, which does not use extension method, works:
static void Main(string[] args)
{
NDArray arr = np.zeros(3, 3);
int[] indices = new int[] { 0, 1 };
double value = 10;
foreach (var i in indices)
arr.SetData(value, i);
Console.WriteLine(arr.ToString());
}
Output:
[[10, 10, 10],[10, 10, 10],[0, 0, 0]]
This code doesn't:
static void Main(string[] args)
{
NDArray arr = np.zeros(3, 3);
int[] indices = new int[] { 0, 1 };
double value = 10;
arr.SetMultiData(value, indices);
Console.WriteLine(arr.ToString());
}
Output:
[[10, 0, 0],[0, 0, 0],[0, 0, 0]]
This isn't always going to print, in most cases it just fails to print and I believe the underlying arr
structure is corrupted accordingly, which leads to undefined behavior when I run it multiple times.
Now, the last bit. When I change the Extension
method to accept double
instead of object
, it works perfectly. But I need the extension method to work with more than one type given it is just a wrapper around SetData
. Given this, I also tried changing the method to be generic:
public static class Extensions
{
public static void SetMultiData<T>(this NDArray arr, object value, int[] indices)
{
T val = (T)value;
foreach (var i in indices)
arr.SetData(val, i);
}
}
I was shocked when this didn't work and produced the same output. Basically, I made the explicit cast from object to type. And I called the function like this: arr.SetMultiData<double>(value, indicies);
and I used the debugger and compared the code that worked with this and the types are exactly the same ones that are passed to arr.SetValue
given i = int
and val = double
, yet one works and one doesn't.
What causes such behavior? And why does it work when I explicitly set it to double
when it fails both using generic/object
types?
For reference, here is the SetData
implementation. which is open-source.