Skip to content

Add NumPy-like add and multiply for CLR arrays - #2110

Open
BCSharp wants to merge 1 commit into
IronLanguages:mainfrom
BCSharp:ndarray-add-mul
Open

BCSharp wants to merge 1 commit into
IronLanguages:mainfrom
BCSharp:ndarray-add-mul

Conversation

@BCSharp

@BCSharp BCSharp commented Oct 22, 2026

Copy link
Copy Markdown
Member

This is the first step in implementing #1887. The proposal was posted some 1.5 years ago but it did not attract any comments. I myself have nothing to add to it, looking back, it still looks good, in my opinion. So here it is: add and multiply on CLR arrays using NumPy semantics: element-wise, with NumPy broadcasting, NumPy type promotion (Python scalars are weak, as in NumPy 2), and the same_kind casting rule for dtype and out. I placed the new functions in NDArrayOps, to keep them separate from the "ordinary" members of System.Array.

I am reusing some of the existing tests of NumPy with adaptations; they are of great help. The NumPy test code is under the BSD licence, which requires the licence being included, but the code is only used in tests, and only in source form, so it is compatible with our licensing policy. It is all placed in tests/suite/ndarray.

This interface is still work in progress and may be tweaked as we go, but I wanted to get the beginning out here, before the next release (e.g. I'm considering moving dtype_of(x) to NDArrayOps to have x.dtype, like in NumPy). I have the feeling that the next release is close 😸

@slozier slozier left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the feeling that the next release is close

Maybe? .NET 8/9 will reach end of support soon out so maybe a good time... But on the other hand there are so many things I want to look at I'm not sure where to draw the line. 🐱


I guess some comment is better than silence for a few days while I look through this, so here are my first ones:

I tried this one before checking the examples 😄.

Array[bool]([True]).add(Array[bool]([False]), out=Array[bool]([False])) # [False]

The instance is ignored and out out gets bound to the 2nd argument. Seems like a core argument binding issue.

It looks like you're deferring to IronPython's binary operations to get the results, but when no out or dtype is given the output type simply matches the inputs (I have not explored mixed type inputs). This can cause some weirdness when the operation overflow. When this occurs the behaviour of IronPython is not super consistent, for System integer types we grow the output whereas for Single we keep it as a Single(?) (I complained about this recently in #2077). This means we get things like:

Array.add(Array[bool]([True]), Array[bool]([True])) # [True]
Array.add(Array[bool]([True]), Array[bool]([True]), out=Array[Int64]([0])) # [2]

Maybe System.Boolean is a weird one because we're forcing it to behave like an int subclass, but System.Int16 for example has similar issues:

Array.add(Array[Int16]([32767]), Array[Int16]([1])) # OverflowError
Array.add(Array[Int16]([32767]), Array[Int16]([1]), out=Array[Int64]([0])) # [32768]

Anyway, it's just not as clear cut as numpy which doesn't grow out of its type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants