@@ -52,6 +52,10 @@ def numpy_broadcast_to(arr, shape):
5252 return np .broadcast_to (arr , shape )
5353
5454
55+ def numpy_broadcast_arrays (* args ):
56+ return np .broadcast_arrays (* args )
57+
58+
5559def numpy_broadcast_to_indexing (arr , shape , idx ):
5660 return np .broadcast_to (arr , shape )[idx ]
5761
@@ -965,6 +969,184 @@ def test_argwhere_array_like(self):
965969 got = cfunc (a )
966970 self .assertPreciseEqual (expected , got )
967971
972+ def broadcast_arrays_assert_correct_shape (self , input_shapes , expected_shape ):
973+ # Broadcast a list of arrays with the given input shapes and check the
974+ # common output shape.
975+ pyfunc = numpy_broadcast_arrays
976+ cfunc = jit (nopython = True )(pyfunc )
977+
978+ inarrays = [np .zeros (s ) for s in input_shapes ]
979+ outarrays = cfunc (* inarrays )
980+ expected = [expected_shape ] * len (inarrays )
981+ got = [a .shape for a in outarrays ]
982+ self .assertPreciseEqual (expected , got )
983+
984+ def test_broadcast_arrays_same_input_shapes (self ):
985+ # Tests taken from
986+ # https://github.com/numpy/numpy/blob/623bc1fae1d47df24e7f1e29321d0c0ba2771ce0/numpy/lib/tests/test_stride_tricks.py#L83-L107 # noqa: E501
987+ # Check that the final shape is just the input shape.
988+ pyfunc = numpy_broadcast_arrays
989+ cfunc = jit (nopython = True )(pyfunc )
990+
991+ data = [
992+ # (),
993+ (1 ,),
994+ (3 ,),
995+ (0 , 1 ),
996+ (0 , 3 ),
997+ (1 , 0 ),
998+ (3 , 0 ),
999+ (1 , 3 ),
1000+ (3 , 1 ),
1001+ (3 , 3 ),
1002+ ]
1003+ for shape in data :
1004+ input_shapes = [shape ]
1005+ # Single input.
1006+ self .broadcast_arrays_assert_correct_shape (input_shapes , shape )
1007+ # Double input.
1008+ input_shapes2 = [shape , shape ]
1009+ self .broadcast_arrays_assert_correct_shape (input_shapes2 , shape )
1010+ # Triple input.
1011+ input_shapes3 = [shape , shape , shape ]
1012+ self .broadcast_arrays_assert_correct_shape (input_shapes3 , shape )
1013+
1014+ def test_broadcast_arrays_two_compatible_by_ones_input_shapes (self ):
1015+ # Tests taken from
1016+ # https://github.com/numpy/numpy/blob/623bc1fae1d47df24e7f1e29321d0c0ba2771ce0/numpy/lib/tests/test_stride_tricks.py#L110-L132
1017+ # Check that two different input shapes of the same length, but some have
1018+ # ones, broadcast to the correct shape.
1019+
1020+ data = [
1021+ [[(1 ,), (3 ,)], (3 ,)],
1022+ [[(1 , 3 ), (3 , 3 )], (3 , 3 )],
1023+ [[(3 , 1 ), (3 , 3 )], (3 , 3 )],
1024+ [[(1 , 3 ), (3 , 1 )], (3 , 3 )],
1025+ [[(1 , 1 ), (3 , 3 )], (3 , 3 )],
1026+ [[(1 , 1 ), (1 , 3 )], (1 , 3 )],
1027+ [[(1 , 1 ), (3 , 1 )], (3 , 1 )],
1028+ [[(1 , 0 ), (0 , 0 )], (0 , 0 )],
1029+ [[(0 , 1 ), (0 , 0 )], (0 , 0 )],
1030+ [[(1 , 0 ), (0 , 1 )], (0 , 0 )],
1031+ [[(1 , 1 ), (0 , 0 )], (0 , 0 )],
1032+ [[(1 , 1 ), (1 , 0 )], (1 , 0 )],
1033+ [[(1 , 1 ), (0 , 1 )], (0 , 1 )],
1034+ ]
1035+ for input_shapes , expected_shape in data :
1036+ self .broadcast_arrays_assert_correct_shape (input_shapes , expected_shape )
1037+ # Reverse the input shapes since broadcasting should be symmetric.
1038+ self .broadcast_arrays_assert_correct_shape (input_shapes [::- 1 ], expected_shape )
1039+
1040+ def test_broadcast_arrays_two_compatible_by_prepending_ones_input_shapes (self ):
1041+ # Tests taken from
1042+ # https://github.com/numpy/numpy/blob/623bc1fae1d47df24e7f1e29321d0c0ba2771ce0/numpy/lib/tests/test_stride_tricks.py#L135-L164
1043+ # Check that two different input shapes (of different lengths) broadcast
1044+ # to the correct shape.
1045+
1046+ data = [
1047+ [[(), (3 ,)], (3 ,)],
1048+ [[(3 ,), (3 , 3 )], (3 , 3 )],
1049+ [[(3 ,), (3 , 1 )], (3 , 3 )],
1050+ [[(1 ,), (3 , 3 )], (3 , 3 )],
1051+ [[(), (3 , 3 )], (3 , 3 )],
1052+ [[(1 , 1 ), (3 ,)], (1 , 3 )],
1053+ [[(1 ,), (3 , 1 )], (3 , 1 )],
1054+ [[(1 ,), (1 , 3 )], (1 , 3 )],
1055+ [[(), (1 , 3 )], (1 , 3 )],
1056+ [[(), (3 , 1 )], (3 , 1 )],
1057+ [[(), (0 ,)], (0 ,)],
1058+ [[(0 ,), (0 , 0 )], (0 , 0 )],
1059+ [[(0 ,), (0 , 1 )], (0 , 0 )],
1060+ [[(1 ,), (0 , 0 )], (0 , 0 )],
1061+ [[(), (0 , 0 )], (0 , 0 )],
1062+ [[(1 , 1 ), (0 ,)], (1 , 0 )],
1063+ [[(1 ,), (0 , 1 )], (0 , 1 )],
1064+ [[(1 ,), (1 , 0 )], (1 , 0 )],
1065+ [[(), (1 , 0 )], (1 , 0 )],
1066+ [[(), (0 , 1 )], (0 , 1 )],
1067+ ]
1068+ for input_shapes , expected_shape in data :
1069+ self .broadcast_arrays_assert_correct_shape (input_shapes , expected_shape )
1070+ # Reverse the input shapes since broadcasting should be symmetric.
1071+ self .broadcast_arrays_assert_correct_shape (input_shapes [::- 1 ], expected_shape )
1072+
1073+ def test_broadcast_arrays_scalar_input (self ):
1074+ pyfunc = numpy_broadcast_arrays
1075+ cfunc = jit (nopython = True )(pyfunc )
1076+ data = [
1077+ [[True , False ], (1 ,)],
1078+ [[1 , 2 ], (1 ,)],
1079+ [[(1 , 2 ), 2 ], (2 ,)],
1080+ ]
1081+ for inarrays , expected_shape in data :
1082+ outarrays = cfunc (* inarrays )
1083+ got = [a .shape for a in outarrays ]
1084+ expected = [expected_shape ] * len (inarrays )
1085+ self .assertPreciseEqual (expected , got )
1086+
1087+ def test_broadcast_arrays_tuple_input (self ):
1088+ pyfunc = numpy_broadcast_arrays
1089+ cfunc = jit (nopython = True )(pyfunc )
1090+ outarrays = cfunc ((123 , 456 ), (789 ,))
1091+ expected = [(2 ,), (2 ,)]
1092+ got = [a .shape for a in outarrays ]
1093+ self .assertPreciseEqual (expected , got )
1094+
1095+ def test_broadcast_arrays_non_array_input (self ):
1096+ pyfunc = numpy_broadcast_arrays
1097+ cfunc = jit (nopython = True )(pyfunc )
1098+ outarrays = cfunc (np .intp (2 ), np .zeros ((1 , 3 ), dtype = np .intp ))
1099+ expected = [(1 , 3 ), (1 , 3 )]
1100+ got = [a .shape for a in outarrays ]
1101+ self .assertPreciseEqual (expected , got )
1102+
1103+ def test_broadcast_arrays_invalid_mixed_input_types (self ):
1104+ pyfunc = numpy_broadcast_arrays
1105+ cfunc = jit (nopython = True )(pyfunc )
1106+
1107+ self .disable_leak_check ()
1108+
1109+ with self .assertRaises (TypingError ) as raises :
1110+ arr = np .arange (6 ).reshape ((2 , 3 ))
1111+ b = True
1112+ cfunc (arr , b )
1113+ self .assertIn ('Mismatch of argument types' , str (raises .exception ))
1114+
1115+ def test_broadcast_arrays_invalid_input (self ):
1116+ pyfunc = numpy_broadcast_arrays
1117+ cfunc = jit (nopython = True )(pyfunc )
1118+
1119+ self .disable_leak_check ()
1120+
1121+ with self .assertRaises (TypingError ) as raises :
1122+ arr = np .zeros (3 , dtype = np .int64 )
1123+ s = 'hello world'
1124+ cfunc (arr , s )
1125+ self .assertIn ('Argument "1" must be array-like' , str (raises .exception ))
1126+
1127+ def test_broadcast_arrays_incompatible_shapes_raise_valueerror (self ):
1128+ # Check that a ValueError is raised for incompatible shapes.
1129+ pyfunc = numpy_broadcast_arrays
1130+ cfunc = jit (nopython = True )(pyfunc )
1131+
1132+ self .disable_leak_check ()
1133+
1134+ data = [
1135+ [(3 ,), (4 ,)],
1136+ [(2 , 3 ), (2 ,)],
1137+ [(3 ,), (3 ,), (4 ,)],
1138+ [(1 , 3 , 4 ), (2 , 3 , 3 )],
1139+ ]
1140+ for input_shapes in data :
1141+ for shape in [input_shapes , input_shapes [::- 1 ]]:
1142+ # Reverse the input shapes since broadcasting should be symmetric.
1143+ with self .assertRaises (ValueError ) as raises :
1144+ inarrays = [np .zeros (s ) for s in shape ]
1145+ cfunc (* inarrays )
1146+ self .assertIn ("shape mismatch: objects cannot be broadcast to a single shape" ,
1147+ str (raises .exception ))
1148+
1149+
9681150
9691151if __name__ == '__main__' :
9701152 unittest .main ()
0 commit comments