@@ -901,7 +901,7 @@ static PyObject *box_from_arystruct_parent(usmarystruct_t *arystruct,
901
901
int ndim ,
902
902
PyArray_Descr * descr )
903
903
{
904
- int i = 0 , exp = 0 ;
904
+ int i = 0 , j = 0 , k = 0 , exp = 0 ;
905
905
npy_intp * p = NULL ;
906
906
npy_intp * shape = NULL , * strides = NULL ;
907
907
PyObject * array = arystruct -> parent ;
@@ -933,6 +933,8 @@ static PyObject *box_from_arystruct_parent(usmarystruct_t *arystruct,
933
933
shape = UsmNDArray_GetShape (arrayobj );
934
934
strides = UsmNDArray_GetStrides (arrayobj );
935
935
936
+ // Ensure the shape of the array to be boxed matches the shape of the
937
+ // original parent.
936
938
for (i = 0 ; i < ndim ; i ++ , p ++ ) {
937
939
if (shape [i ] != * p )
938
940
return NULL ;
@@ -942,20 +944,52 @@ static PyObject *box_from_arystruct_parent(usmarystruct_t *arystruct,
942
944
itemsize = arystruct -> itemsize ;
943
945
while (itemsize >>= 1 )
944
946
exp ++ ;
945
- // dpctl stores strides as number of elements and Numba stores strides as
947
+
948
+ // Ensure the strides of the array to be boxed matches the shape of the
949
+ // original parent. Things to note:
950
+ //
951
+ // 1. dpctl only stores stride information if the array has a non-unit
952
+ // stride. If the array is unit strided then dpctl does not populate the
953
+ // stride attribute. To verify strides, we compute the strides from the
954
+ // shape vector.
955
+ //
956
+ // 2. dpctl stores strides as number of elements and Numba stores strides as
946
957
// bytes, for that reason we are multiplying stride by itemsize when
947
- // unboxing the external array.
958
+ // unboxing the external array and dividing by itemsize when boxing the
959
+ // array back.
960
+
948
961
if (strides ) {
949
- if (strides [i ] << exp != * p )
950
- return NULL ;
962
+ for (i = 0 ; i < ndim ; ++ i , ++ p ) {
963
+ if (strides [i ] << exp != * p ) {
964
+ DPEXRT_DEBUG (
965
+ drt_debug_print ("DPEXRT-DEBUG: Arrayobj cannot be boxed "
966
+ "from parent as strides in the "
967
+ "arystruct are not the same as "
968
+ "the strides in the parent object. "
969
+ "Expected stride = %d actual stride = %d\n" ,
970
+ strides [i ] << exp , * p ));
971
+ return NULL ;
972
+ }
973
+ }
951
974
}
952
975
else {
953
- for (i = 1 ; i < ndim ; ++ i , ++ p ) {
954
- if (shape [i ] != * p )
976
+ npy_intp tmp ;
977
+ for (i = (ndim * 2 ) - 1 ; i >= ndim ; -- i , ++ p ) {
978
+ tmp = 1 ;
979
+ for (j = i , k = ndim - 1 ; j > ndim ; -- j , -- k )
980
+ tmp *= shape [k ];
981
+ tmp <<= exp ;
982
+ if (tmp != * p ) {
983
+ DPEXRT_DEBUG (
984
+ drt_debug_print ("DPEXRT-DEBUG: Arrayobj cannot be boxed "
985
+ "from parent as strides in the "
986
+ "arystruct are not the same as "
987
+ "the strides in the parent object. "
988
+ "Expected stride = %d actual stride = %d\n" ,
989
+ tmp , * p ));
955
990
return NULL ;
991
+ }
956
992
}
957
- if (* p != 1 )
958
- return NULL ;
959
993
}
960
994
961
995
// At the end of boxing our Meminfo destructor gets called and that will
0 commit comments