@@ -757,9 +757,6 @@ boundarraymethod__simple_strided_call(
757757
758758
759759/*
760- * TODO: Currently still based on the old ufunc system and not ArrayMethod!
761- * This requires fixing the ufunc code first.
762- *
763760 * Support for masked inner-strided loops. Masked inner-strided loops are
764761 * only used in the ufunc machinery. So this special cases them.
765762 * In the future it probably makes sense to create an::
@@ -770,8 +767,8 @@ boundarraymethod__simple_strided_call(
770767 */
771768typedef struct {
772769 NpyAuxData base ;
773- PyUFuncGenericFunction unmasked_stridedloop ;
774- void * innerloopdata ;
770+ PyArrayMethod_StridedLoop * unmasked_stridedloop ;
771+ NpyAuxData * unmasked_auxdata ;
775772 int nargs ;
776773 char * dataptrs [];
777774} _masked_stridedloop_data ;
@@ -781,6 +778,7 @@ static void
781778_masked_stridedloop_data_free (NpyAuxData * auxdata )
782779{
783780 _masked_stridedloop_data * data = (_masked_stridedloop_data * )auxdata ;
781+ NPY_AUXDATA_FREE (data -> unmasked_auxdata );
784782 PyMem_Free (data );
785783}
786784
@@ -790,15 +788,15 @@ _masked_stridedloop_data_free(NpyAuxData *auxdata)
790788 * masked strided-loop, only calling the function for elements
791789 * where the mask is True.
792790 */
793- static void
794- unmasked_ufunc_loop_as_masked (
795- char * * data , const npy_intp * dimensions ,
796- const npy_intp * strides , void * _auxdata )
791+ static int
792+ generic_masked_strided_loop ( PyArrayMethod_Context * context ,
793+ char * const * data , const npy_intp * dimensions ,
794+ const npy_intp * strides , NpyAuxData * _auxdata )
797795{
798796 _masked_stridedloop_data * auxdata = (_masked_stridedloop_data * )_auxdata ;
799797 int nargs = auxdata -> nargs ;
800- PyUFuncGenericFunction strided_loop = auxdata -> unmasked_stridedloop ;
801- void * innerloopdata = auxdata -> innerloopdata ;
798+ PyArrayMethod_StridedLoop * strided_loop = auxdata -> unmasked_stridedloop ;
799+ NpyAuxData * strided_loop_auxdata = auxdata -> unmasked_auxdata ;
802800
803801 char * * dataptrs = auxdata -> dataptrs ;
804802 memcpy (dataptrs , data , nargs * sizeof (char * ));
@@ -819,39 +817,37 @@ unmasked_ufunc_loop_as_masked(
819817
820818 /* Process unmasked values */
821819 mask = npy_memchr (mask , 0 , mask_stride , N , & subloopsize , 0 );
822- strided_loop (dataptrs , & subloopsize , strides , innerloopdata );
820+ int res = strided_loop (context ,
821+ dataptrs , & subloopsize , strides , strided_loop_auxdata );
822+ if (res != 0 ) {
823+ return res ;
824+ }
823825 for (int i = 0 ; i < nargs ; i ++ ) {
824826 dataptrs [i ] += subloopsize * strides [i ];
825827 }
826828 N -= subloopsize ;
827829 } while (N > 0 );
830+
831+ return 0 ;
828832}
829833
830834
831835/*
832- * TODO: This function will be the masked equivalent to `get_loop`.
833- * This function wraps a legacy inner loop so it becomes masked .
834- *
835- * Returns 0 on success, -1 on error.
836+ * Identical to the `get_loop` functions and wraps it. This adds support
837+ * to a boolean mask being passed in as a last, additional, operand .
838+ * The wrapped loop will only be called for unmasked elements.
839+ * (Does not support `move_references` or inner dimensions!)
836840 */
837841NPY_NO_EXPORT int
838- PyUFunc_DefaultMaskedInnerLoopSelector (PyUFuncObject * ufunc ,
839- PyArray_Descr * * dtypes ,
840- PyUFuncGenericFunction * out_innerloop ,
841- NpyAuxData * * out_innerloopdata ,
842- int * out_needs_api )
842+ PyArrayMethod_GetMaskedStridedLoop (
843+ PyArrayMethod_Context * context ,
844+ int aligned , npy_intp * fixed_strides ,
845+ PyArrayMethod_StridedLoop * * out_loop ,
846+ NpyAuxData * * out_transferdata ,
847+ NPY_ARRAYMETHOD_FLAGS * flags )
843848{
844- int retcode ;
845849 _masked_stridedloop_data * data ;
846- int nargs = ufunc -> nin + ufunc -> nout ;
847-
848- if (ufunc -> legacy_inner_loop_selector == NULL ) {
849- PyErr_SetString (PyExc_RuntimeError ,
850- "the ufunc default masked inner loop selector doesn't "
851- "yet support wrapping the new inner loop selector, it "
852- "still only wraps the legacy inner loop selector" );
853- return -1 ;
854- }
850+ int nargs = context -> method -> nin + context -> method -> nout ;
855851
856852 /* Add working memory for the data pointers, to modify them in-place */
857853 data = PyMem_Malloc (sizeof (_masked_stridedloop_data ) +
@@ -865,18 +861,14 @@ PyUFunc_DefaultMaskedInnerLoopSelector(PyUFuncObject *ufunc,
865861 data -> unmasked_stridedloop = NULL ;
866862 data -> nargs = nargs ;
867863
868- /* Get the unmasked ufunc inner loop */
869- retcode = ufunc -> legacy_inner_loop_selector (ufunc , dtypes ,
870- & data -> unmasked_stridedloop , & data -> innerloopdata ,
871- out_needs_api );
872- if (retcode < 0 ) {
873- PyArray_free (data );
874- return retcode ;
864+ if (context -> method -> get_strided_loop (context ,
865+ aligned , 0 , fixed_strides ,
866+ & data -> unmasked_stridedloop , & data -> unmasked_auxdata , flags ) < 0 ) {
867+ PyMem_Free (data );
868+ return -1 ;
875869 }
876-
877- /* Return the loop function + aux data */
878- * out_innerloop = & unmasked_ufunc_loop_as_masked ;
879- * out_innerloopdata = (NpyAuxData * )data ;
870+ * out_transferdata = (NpyAuxData * )data ;
871+ * out_loop = generic_masked_strided_loop ;
880872 return 0 ;
881873}
882874
0 commit comments