@@ -786,8 +786,8 @@ def test_strides_out(self, stride, dt):
786786 )
787787 ia = dpnp .array (a )
788788
789- out_mant = numpy .ones ( 8 , dtype = dt )
790- out_exp = 2 * numpy .ones ( 8 , dtype = "i" )
789+ out_mant = numpy .ones_like ( a )
790+ out_exp = 2 * numpy .ones_like ( a , dtype = "i" )
791791 iout_mant , iout_exp = dpnp .array (out_mant ), dpnp .array (out_exp )
792792
793793 res1 , res2 = dpnp .frexp (
@@ -802,11 +802,34 @@ def test_strides_out(self, stride, dt):
802802 assert_array_equal (iout_mant , out_mant )
803803 assert_array_equal (iout_exp , out_exp )
804804
805- @pytest .mark .parametrize ("xp" , [numpy , dpnp ])
806- def test_out_wrong_type (self , xp ):
807- a = xp .array (0.5 )
808- with pytest .raises (TypeError , match = "'out' must be a tuple of arrays" ):
809- _ = xp .frexp (a , out = xp .empty (()))
805+ @pytest .mark .parametrize ("dt" , get_float_dtypes ())
806+ def test_out_overlap (self , dt ):
807+ a = numpy .ones (15 , dtype = dt )
808+ ia = dpnp .array (a )
809+
810+ out_mant = numpy .ones_like (a )
811+ out_exp = 2 * numpy .ones_like (a , dtype = "i" )
812+ iout_mant , iout_exp = dpnp .array (out_mant ), dpnp .array (out_exp )
813+
814+ res1 , res2 = dpnp .frexp (ia , out = (iout_mant , iout_exp ))
815+ exp1 , exp2 = numpy .frexp (a , out = (out_mant , out_exp ))
816+ assert_array_equal (res1 , exp1 )
817+ assert_array_equal (res2 , exp2 )
818+
819+ assert_array_equal (iout_mant , out_mant )
820+ assert_array_equal (iout_exp , out_exp )
821+ assert res1 is iout_mant
822+ assert res2 is iout_exp
823+
824+ @pytest .mark .parametrize ("dt" , get_float_dtypes ())
825+ def test_empty (self , dt ):
826+ a = numpy .empty ((), dtype = dt )
827+ ia = dpnp .array (a )
828+
829+ res1 , res2 = dpnp .frexp (ia )
830+ exp1 , exp2 = numpy .frexp (a )
831+ assert_array_equal (res1 , exp1 , strict = True )
832+ assert_array_equal (res2 , exp2 , strict = True )
810833
811834 @pytest .mark .parametrize ("xp" , [numpy , dpnp ])
812835 @pytest .mark .parametrize ("dt" , get_complex_dtypes ())
@@ -2080,7 +2103,7 @@ def test_not_supported_kwargs(self, func, kwargs):
20802103
20812104 @pytest .mark .parametrize ("func" , ["abs" , "frexp" , "add" ])
20822105 @pytest .mark .parametrize ("x" , [1 , [1 , 2 ], numpy .ones (5 )])
2083- def test_wrong_input (self , func , x ):
2106+ def test_unary_wrong_input (self , func , x ):
20842107 fn = getattr (dpnp , func )
20852108 args = [x ] * fn .nin
20862109 with pytest .raises (TypeError ):
@@ -2115,8 +2138,75 @@ def test_out_dtype(self, func):
21152138 ):
21162139 fn (* args , out = out , dtype = "f4" )
21172140
2141+ @pytest .mark .parametrize ("xp" , [numpy , dpnp ])
2142+ def test_unary_two_outs_out_ndarray (self , xp ):
2143+ x = xp .array (0.5 )
2144+ with pytest .raises (TypeError , match = "'out' must be a tuple of arrays" ):
2145+ _ = xp .frexp (x , out = xp .empty (()))
2146+
2147+ @pytest .mark .parametrize ("xp" , [numpy , dpnp ])
2148+ @pytest .mark .parametrize ("out" , [(), (1 ,), (1 , 2 , 3 )])
2149+ def test_unary_two_outs_out_wrong_tuple_len (self , xp , out ):
2150+ x = xp .array (0.5 )
2151+ with pytest .raises (
2152+ ValueError ,
2153+ match = "'out' tuple must have exactly one entry per ufunc output" ,
2154+ ):
2155+ _ = xp .frexp (x , out = out )
2156+
2157+ @pytest .mark .parametrize ("xp" , [numpy , dpnp ])
2158+ def test_unary_two_outs_out_mixed (self , xp ):
2159+ x = xp .array (0.5 )
2160+ with pytest .raises (
2161+ TypeError ,
2162+ match = "cannot specify 'out' as both a positional and keyword" ,
2163+ ):
2164+ _ = xp .frexp (x , xp .empty (()), out = (xp .empty (()), None ))
2165+
2166+ @pytest .mark .parametrize ("xp" , [numpy , dpnp ])
2167+ def test_unary_two_outs_out_not_writable (self , xp ):
2168+ x = xp .array (0.5 )
2169+ out1 = xp .empty (())
2170+ out1 .flags ["W" ] = False
2171+
2172+ with pytest .raises (ValueError , match = "array is read-only" ):
2173+ _ = xp .frexp (x , out1 )
2174+
2175+ out2 = xp .empty ((), dtype = "i" )
2176+ out2 .flags ["W" ] = False
2177+ with pytest .raises (ValueError , match = "array is read-only" ):
2178+ _ = xp .frexp (x , out = (None , out2 ))
2179+
2180+ @pytest .mark .parametrize ("xp" , [numpy , dpnp ])
2181+ def test_unary_two_outs_out_wrong_shape (self , xp ):
2182+ x = xp .full (6 , fill_value = 0.5 )
2183+ out1 = xp .empty (12 )
2184+ with pytest .raises (ValueError ):
2185+ _ = xp .frexp (x , out1 )
2186+
2187+ out2 = xp .empty ((2 , 3 ), dtype = "i" )
2188+ with pytest .raises (ValueError ):
2189+ _ = xp .frexp (x , out = (None , out2 ))
2190+
2191+ def test_unary_two_outs_cfd_error (self ):
2192+ x = dpnp .array (0.5 , sycl_queue = dpctl .SyclQueue ())
2193+ out1 = dpnp .empty ((), sycl_queue = dpctl .SyclQueue ())
2194+ out2 = dpnp .empty ((), sycl_queue = dpctl .SyclQueue ())
2195+ with pytest .raises (
2196+ ExecutionPlacementError ,
2197+ match = "Input and output allocation queues are not compatible" ,
2198+ ):
2199+ _ = dpnp .frexp (x , out1 )
2200+
2201+ with pytest .raises (
2202+ ExecutionPlacementError ,
2203+ match = "Input and output allocation queues are not compatible" ,
2204+ ):
2205+ _ = dpnp .frexp (x , out = (None , out2 ))
2206+
21182207 @pytest .mark .parametrize ("func" , ["abs" , "frexp" , "add" ])
2119- def test_order_none (self , func ):
2208+ @pytest .mark .parametrize ("order" , [None , "K" , "A" , "f" , "c" ])
2209+ def test_order (self , func , order ):
21202210 a = numpy .array ([1 , 2 , 3 ])
21212211 ia = dpnp .array (a )
21222212
@@ -2126,8 +2216,8 @@ def test_order_none(self, func):
21262216 args = [a ] * fn .nin
21272217 iargs = [ia ] * ifn .nin
21282218
2129- result = ifn (* iargs , order = None )
2130- expected = fn (* args , order = None )
2219+ result = ifn (* iargs , order = order )
2220+ expected = fn (* args , order = order )
21312221 if fn .nout == 1 :
21322222 assert_dtype_allclose (result , expected )
21332223 else :
0 commit comments