When a.ndim >= 2 and b.ndim > 2, np.dot() and ndarray.dot() place b's leading dimensions in the middle of the result:
a = np.ones((2, 3))
b = np.ones((4, 3, 5))
np.dot(a, b).shape # (2, 4, 5) - the 4 ends up in the middle
@/matmul gives (4, 2, 5). This PR deprecates the dot behavior for these inputs and suggests numpy.tensordot(a, b, axes=[-1, -2]) for the same result, or @/matmul for batched matrix multiplication.
Implements np.minmax using the new ability to register reduction loops to ufuncs implemented in #31816
The loops are implemented in the existing .c.src files with the np.minimun/maximum loops and using exactly the same optimizations and SIMD as them. Two new files minmax.cpp and minmax.h are created just to create the ufunc and initialize the array methods.
I found this to be by far the easiest setup to do now. The other option would be porting the whole loops_minmax.dispatch.c.src to highway and using only c++ but that is a more complicated change with a way more difficult review so I did not do that.
minmax is not a method on the ndarray like min and max are. The only thing exposed in the top-level API is the new np.minmax function. The minimummaximum ufunc is not exposed as np.minimummaximum like np.minimum and np.maximum are as I do not believe there's much use in that. If we ever need it, it's a very simple change.
We should also consider adding a nanminmax in a follow-up PR for completeness and also adding a masked array aware implementation (either by making minmax a method on the ndarray or only by a np.ma.minmax).
Signed-off-by: Iason Krommydas <iason.krom@gmail.com>
Adds a new helper stringdtype_find_fixed_width_descr and uses
it in a new code path in find_descriptor_from_array that works
like the existing object string and datetime code paths in that
function that scan array values to infer the destination dtype.
Also adds tests for this new behavior.
Rather than looking up loops with the `PyUFunc_DefaultLegacyInnerLoopSelector` every time, this caches
the actual loop on the ArrayMethod.
Conceptually, this is the right thing, but there are two annoyances unfortunately:
1. We have a `ReplaceLoopByDescr` whether it is used by anyone (except pnumpy which is unmaintained) is another question.
2. We allow dict registration of dtypes which is contrary to how ufunc dispatching works and means that we can't use the path quite always (until that get's deprecated at least)...
For NpyString_acquire_allocators and NpyString_release_allocators, the fix is to sort the mutexes by address before locking. I added tests for ufuncs that need 2, 3, and 4 allocators as well as one that uses a duplicate allocator that all deadlock on main and don't with the fixes here.
Also releases the string allocator mutex before grabbing the GIL, as this in theory not necessary safe if arbitrary Python could be running (there are more paths that would need this fix, though).
This allows `finfo` to be used for downstream user dtypes that do not subclass `inexact` or are "complex". Where complex is defined by whether `arr.imag/arr.real` return the same "real" dtype correspondance.
This PR adds `descending` as an option to partitioning and expands the internal implementations
to support it.
User DTypes are not yet supported as they currently always use the sort fallback. Additional changes
should allow to (a) use the sort as a fallback in a more reliable way and (b) change partitioning to support
a similar new-style API with registration for user DTypes.
Co-authored-by: Sebastian Berg <sebastianb@nvidia.com>
This adds and importantly backports a way for legacy dtypes to transition to the new API.
I.e. with one caveat I found for now (array dtype printing prints as np.array([1.0], dtype=repr(dtype)) and the repr now shouldn't be bfloat16 for an ml_dtype bfloat16), this allows transitioning a package like ml_dtypes over.
The advantage of this is that it allows using the new API even back to NumPy 2 without any real serious downsides (for dtypes that are currently on the legacy API).
This is a pretty big deal, I think. Because the new API does offer a few improvements that can be reliably overridden also for NumPy 2.0 and it makes it a lot simpler to opt-in to new API e.g. for NumPy 2.4+ (with a runtime check).
Restructure real/imag attributes to use an `ArrayMethod` that can be registered similar to other ufuncs and sorting functions.
Object dtype is changed here to use `getattr(element, "real", element)` and `getattr(element, "imag", 0)` as a step in a more reliable direction. The returned array is marked as read-only to prevent trying to modify `.real/.imag` results directly.
(If the object changes are problematic, they can be modified again. The main reason for this is also to allow user DTypes to define this correctly.)
This PR adds getters for accessing struct fields in cython. In future these would call an ABI function to get the actual fields struct on opaque PyObject builds.
Co-authored-by: Nathan Goldbaum <nathan.goldbaum@gmail.com>