@@ -2704,13 +2704,13 @@ array_vdot(PyObject *NPY_UNUSED(dummy), PyObject *const *args, Py_ssize_t len_ar
2704
2704
}
2705
2705
2706
2706
static int
2707
- einsum_sub_op_from_str (PyObject * args , PyObject * * str_obj , char * * subscripts ,
2708
- PyArrayObject * * op )
2707
+ einsum_sub_op_from_str (
2708
+ Py_ssize_t nargs , PyObject * const * args ,
2709
+ PyObject * * str_obj , char * * subscripts , PyArrayObject * * op )
2709
2710
{
2710
- int i , nop ;
2711
+ Py_ssize_t nop = nargs - 1 ;
2711
2712
PyObject * subscripts_str ;
2712
2713
2713
- nop = PyTuple_GET_SIZE (args ) - 1 ;
2714
2714
if (nop <= 0 ) {
2715
2715
PyErr_SetString (PyExc_ValueError ,
2716
2716
"must specify the einstein sum subscripts string "
@@ -2723,7 +2723,7 @@ einsum_sub_op_from_str(PyObject *args, PyObject **str_obj, char **subscripts,
2723
2723
}
2724
2724
2725
2725
/* Get the subscripts string */
2726
- subscripts_str = PyTuple_GET_ITEM ( args , 0 ) ;
2726
+ subscripts_str = args [ 0 ] ;
2727
2727
if (PyUnicode_Check (subscripts_str )) {
2728
2728
* str_obj = PyUnicode_AsASCIIString (subscripts_str );
2729
2729
if (* str_obj == NULL ) {
@@ -2740,15 +2740,13 @@ einsum_sub_op_from_str(PyObject *args, PyObject **str_obj, char **subscripts,
2740
2740
}
2741
2741
2742
2742
/* Set the operands to NULL */
2743
- for (i = 0 ; i < nop ; ++ i ) {
2743
+ for (Py_ssize_t i = 0 ; i < nop ; ++ i ) {
2744
2744
op [i ] = NULL ;
2745
2745
}
2746
2746
2747
2747
/* Get the operands */
2748
- for (i = 0 ; i < nop ; ++ i ) {
2749
- PyObject * obj = PyTuple_GET_ITEM (args , i + 1 );
2750
-
2751
- op [i ] = (PyArrayObject * )PyArray_FROM_OF (obj , NPY_ARRAY_ENSUREARRAY );
2748
+ for (Py_ssize_t i = 0 ; i < nop ; ++ i ) {
2749
+ op [i ] = (PyArrayObject * )PyArray_FROM_OF (args [i + 1 ], NPY_ARRAY_ENSUREARRAY );
2752
2750
if (op [i ] == NULL ) {
2753
2751
goto fail ;
2754
2752
}
@@ -2757,7 +2755,7 @@ einsum_sub_op_from_str(PyObject *args, PyObject **str_obj, char **subscripts,
2757
2755
return nop ;
2758
2756
2759
2757
fail :
2760
- for (i = 0 ; i < nop ; ++ i ) {
2758
+ for (Py_ssize_t i = 0 ; i < nop ; ++ i ) {
2761
2759
Py_XDECREF (op [i ]);
2762
2760
op [i ] = NULL ;
2763
2761
}
@@ -2861,13 +2859,12 @@ einsum_list_to_subscripts(PyObject *obj, char *subscripts, int subsize)
2861
2859
* Returns -1 on error, number of operands placed in op otherwise.
2862
2860
*/
2863
2861
static int
2864
- einsum_sub_op_from_lists (PyObject * args ,
2865
- char * subscripts , int subsize , PyArrayObject * * op )
2862
+ einsum_sub_op_from_lists (Py_ssize_t nargs , PyObject * const * args ,
2863
+ char * subscripts , int subsize , PyArrayObject * * op )
2866
2864
{
2867
2865
int subindex = 0 ;
2868
- npy_intp i , nop ;
2869
2866
2870
- nop = PyTuple_Size ( args )/ 2 ;
2867
+ Py_ssize_t nop = nargs / 2 ;
2871
2868
2872
2869
if (nop == 0 ) {
2873
2870
PyErr_SetString (PyExc_ValueError , "must provide at least an "
@@ -2880,15 +2877,12 @@ einsum_sub_op_from_lists(PyObject *args,
2880
2877
}
2881
2878
2882
2879
/* Set the operands to NULL */
2883
- for (i = 0 ; i < nop ; ++ i ) {
2880
+ for (Py_ssize_t i = 0 ; i < nop ; ++ i ) {
2884
2881
op [i ] = NULL ;
2885
2882
}
2886
2883
2887
2884
/* Get the operands and build the subscript string */
2888
- for (i = 0 ; i < nop ; ++ i ) {
2889
- PyObject * obj = PyTuple_GET_ITEM (args , 2 * i );
2890
- int n ;
2891
-
2885
+ for (Py_ssize_t i = 0 ; i < nop ; ++ i ) {
2892
2886
/* Comma between the subscripts for each operand */
2893
2887
if (i != 0 ) {
2894
2888
subscripts [subindex ++ ] = ',' ;
@@ -2899,25 +2893,21 @@ einsum_sub_op_from_lists(PyObject *args,
2899
2893
}
2900
2894
}
2901
2895
2902
- op [i ] = (PyArrayObject * )PyArray_FROM_OF (obj , NPY_ARRAY_ENSUREARRAY );
2896
+ op [i ] = (PyArrayObject * )PyArray_FROM_OF (args [ 2 * i ] , NPY_ARRAY_ENSUREARRAY );
2903
2897
if (op [i ] == NULL ) {
2904
2898
goto fail ;
2905
2899
}
2906
2900
2907
- obj = PyTuple_GET_ITEM (args , 2 * i + 1 );
2908
- n = einsum_list_to_subscripts (obj , subscripts + subindex ,
2909
- subsize - subindex );
2901
+ int n = einsum_list_to_subscripts (
2902
+ args [2 * i + 1 ], subscripts + subindex , subsize - subindex );
2910
2903
if (n < 0 ) {
2911
2904
goto fail ;
2912
2905
}
2913
2906
subindex += n ;
2914
2907
}
2915
2908
2916
2909
/* Add the '->' to the string if provided */
2917
- if (PyTuple_Size (args ) == 2 * nop + 1 ) {
2918
- PyObject * obj ;
2919
- int n ;
2920
-
2910
+ if (nargs == 2 * nop + 1 ) {
2921
2911
if (subindex + 2 >= subsize ) {
2922
2912
PyErr_SetString (PyExc_ValueError ,
2923
2913
"subscripts list is too long" );
@@ -2926,9 +2916,8 @@ einsum_sub_op_from_lists(PyObject *args,
2926
2916
subscripts [subindex ++ ] = '-' ;
2927
2917
subscripts [subindex ++ ] = '>' ;
2928
2918
2929
- obj = PyTuple_GET_ITEM (args , 2 * nop );
2930
- n = einsum_list_to_subscripts (obj , subscripts + subindex ,
2931
- subsize - subindex );
2919
+ int n = einsum_list_to_subscripts (
2920
+ args [2 * nop ], subscripts + subindex , subsize - subindex );
2932
2921
if (n < 0 ) {
2933
2922
goto fail ;
2934
2923
}
@@ -2941,7 +2930,7 @@ einsum_sub_op_from_lists(PyObject *args,
2941
2930
return nop ;
2942
2931
2943
2932
fail :
2944
- for (i = 0 ; i < nop ; ++ i ) {
2933
+ for (Py_ssize_t i = 0 ; i < nop ; ++ i ) {
2945
2934
Py_XDECREF (op [i ]);
2946
2935
op [i ] = NULL ;
2947
2936
}
@@ -2950,108 +2939,74 @@ einsum_sub_op_from_lists(PyObject *args,
2950
2939
}
2951
2940
2952
2941
static PyObject *
2953
- array_einsum (PyObject * NPY_UNUSED (dummy ), PyObject * args , PyObject * kwds )
2942
+ array_einsum (PyObject * NPY_UNUSED (dummy ),
2943
+ PyObject * const * args , Py_ssize_t nargsf , PyObject * kwnames )
2954
2944
{
2955
2945
char * subscripts = NULL , subscripts_buffer [256 ];
2956
2946
PyObject * str_obj = NULL , * str_key_obj = NULL ;
2957
- PyObject * arg0 ;
2958
- int i , nop ;
2947
+ int nop ;
2959
2948
PyArrayObject * op [NPY_MAXARGS ];
2960
2949
NPY_ORDER order = NPY_KEEPORDER ;
2961
2950
NPY_CASTING casting = NPY_SAFE_CASTING ;
2951
+ PyObject * out_obj = NULL ;
2962
2952
PyArrayObject * out = NULL ;
2963
2953
PyArray_Descr * dtype = NULL ;
2964
2954
PyObject * ret = NULL ;
2955
+ NPY_PREPARE_ARGPARSER ;
2956
+
2957
+ Py_ssize_t nargs = PyVectorcall_NARGS (nargsf );
2965
2958
2966
- if (PyTuple_GET_SIZE ( args ) < 1 ) {
2959
+ if (nargs < 1 ) {
2967
2960
PyErr_SetString (PyExc_ValueError ,
2968
2961
"must specify the einstein sum subscripts string "
2969
2962
"and at least one operand, or at least one operand "
2970
2963
"and its corresponding subscripts list" );
2971
2964
return NULL ;
2972
2965
}
2973
- arg0 = PyTuple_GET_ITEM (args , 0 );
2974
2966
2975
2967
/* einsum('i,j', a, b), einsum('i,j->ij', a, b) */
2976
- if (PyBytes_Check (arg0 ) || PyUnicode_Check (arg0 )) {
2977
- nop = einsum_sub_op_from_str (args , & str_obj , & subscripts , op );
2968
+ if (PyBytes_Check (args [ 0 ] ) || PyUnicode_Check (args [ 0 ] )) {
2969
+ nop = einsum_sub_op_from_str (nargs , args , & str_obj , & subscripts , op );
2978
2970
}
2979
2971
/* einsum(a, [0], b, [1]), einsum(a, [0], b, [1], [0,1]) */
2980
2972
else {
2981
- nop = einsum_sub_op_from_lists (args , subscripts_buffer ,
2982
- sizeof (subscripts_buffer ), op );
2973
+ nop = einsum_sub_op_from_lists (nargs , args , subscripts_buffer ,
2974
+ sizeof (subscripts_buffer ), op );
2983
2975
subscripts = subscripts_buffer ;
2984
2976
}
2985
2977
if (nop <= 0 ) {
2986
2978
goto finish ;
2987
2979
}
2988
2980
2989
2981
/* Get the keyword arguments */
2990
- if (kwds != NULL ) {
2991
- PyObject * key , * value ;
2992
- Py_ssize_t pos = 0 ;
2993
- while (PyDict_Next (kwds , & pos , & key , & value )) {
2994
- char * str = NULL ;
2995
-
2996
- Py_XDECREF (str_key_obj );
2997
- str_key_obj = PyUnicode_AsASCIIString (key );
2998
- if (str_key_obj != NULL ) {
2999
- key = str_key_obj ;
3000
- }
3001
-
3002
- str = PyBytes_AsString (key );
3003
-
3004
- if (str == NULL ) {
3005
- PyErr_Clear ();
3006
- PyErr_SetString (PyExc_TypeError , "invalid keyword" );
3007
- goto finish ;
3008
- }
3009
-
3010
- if (strcmp (str ,"out" ) == 0 ) {
3011
- if (PyArray_Check (value )) {
3012
- out = (PyArrayObject * )value ;
3013
- }
3014
- else {
3015
- PyErr_SetString (PyExc_TypeError ,
3016
- "keyword parameter out must be an "
3017
- "array for einsum" );
3018
- goto finish ;
3019
- }
3020
- }
3021
- else if (strcmp (str ,"order" ) == 0 ) {
3022
- if (!PyArray_OrderConverter (value , & order )) {
3023
- goto finish ;
3024
- }
3025
- }
3026
- else if (strcmp (str ,"casting" ) == 0 ) {
3027
- if (!PyArray_CastingConverter (value , & casting )) {
3028
- goto finish ;
3029
- }
3030
- }
3031
- else if (strcmp (str ,"dtype" ) == 0 ) {
3032
- if (!PyArray_DescrConverter2 (value , & dtype )) {
3033
- goto finish ;
3034
- }
3035
- }
3036
- else {
3037
- PyErr_Format (PyExc_TypeError ,
3038
- "'%s' is an invalid keyword for einsum" ,
3039
- str );
3040
- goto finish ;
3041
- }
2982
+ if (kwnames != NULL ) {
2983
+ if (npy_parse_arguments ("einsum" , args + nargs , 0 , kwnames ,
2984
+ "$out" , NULL , & out_obj ,
2985
+ "$order" , & PyArray_OrderConverter , & order ,
2986
+ "$casting" , & PyArray_CastingConverter , & casting ,
2987
+ "$dtype" , & PyArray_DescrConverter2 , & dtype ,
2988
+ NULL , NULL , NULL ) < 0 ) {
2989
+ goto finish ;
3042
2990
}
2991
+ if (out_obj != NULL && !PyArray_Check (out_obj )) {
2992
+ PyErr_SetString (PyExc_TypeError ,
2993
+ "keyword parameter out must be an "
2994
+ "array for einsum" );
2995
+ goto finish ;
2996
+ }
2997
+ out = (PyArrayObject * )out_obj ;
3043
2998
}
3044
2999
3045
3000
ret = (PyObject * )PyArray_EinsteinSum (subscripts , nop , op , dtype ,
3046
- order , casting , out );
3001
+ order , casting , out );
3047
3002
3048
3003
/* If no output was supplied, possibly convert to a scalar */
3049
3004
if (ret != NULL && out == NULL ) {
3050
3005
ret = PyArray_Return ((PyArrayObject * )ret );
3051
3006
}
3052
3007
3053
3008
finish :
3054
- for (i = 0 ; i < nop ; ++ i ) {
3009
+ for (Py_ssize_t i = 0 ; i < nop ; ++ i ) {
3055
3010
Py_XDECREF (op [i ]);
3056
3011
}
3057
3012
Py_XDECREF (dtype );
@@ -4518,7 +4473,7 @@ static struct PyMethodDef array_module_methods[] = {
4518
4473
METH_FASTCALL , NULL },
4519
4474
{"c_einsum" ,
4520
4475
(PyCFunction )array_einsum ,
4521
- METH_VARARGS |METH_KEYWORDS , NULL },
4476
+ METH_FASTCALL |METH_KEYWORDS , NULL },
4522
4477
{"correlate" ,
4523
4478
(PyCFunction )array_correlate ,
4524
4479
METH_FASTCALL | METH_KEYWORDS , NULL },
0 commit comments