14
14
"""
15
15
16
16
from hypothesis import assume , given
17
- from hypothesis .strategies import booleans , composite , none , integers , shared
17
+ from hypothesis .strategies import booleans , composite , none , tuples , integers , shared
18
18
19
- from .array_helpers import assert_exactly_equal , ndindex , asarray
19
+ from .array_helpers import assert_exactly_equal , ndindex , asarray , equal , zero , infinity
20
20
from .hypothesis_helpers import (xps , dtypes , shapes , kwargs , matrix_shapes ,
21
21
square_matrix_shapes , symmetric_matrices ,
22
22
positive_definite_matrices , MAX_ARRAY_SIZE ,
23
23
invertible_matrices , two_mutual_arrays ,
24
- mutually_promotable_dtypes )
24
+ mutually_promotable_dtypes , one_d_shapes )
25
25
from .pytest_helpers import raises
26
26
from . import dtype_helpers as dh
27
27
@@ -339,12 +339,27 @@ def test_matrix_transpose(x):
339
339
_test_stacks (linalg .matrix_transpose , x , res = res , true_val = true_val )
340
340
341
341
@given (
342
- x1 = xps . arrays ( dtype = xps . floating_dtypes (), shape = shapes ) ,
343
- x2 = xps . arrays ( dtype = xps . floating_dtypes (), shape = shapes ),
342
+ * two_mutual_arrays ( dtype_objects = dh . numeric_dtypes ,
343
+ two_shapes = tuples ( one_d_shapes , one_d_shapes ))
344
344
)
345
345
def test_outer (x1 , x2 ):
346
- # res = linalg.outer(x1, x2)
347
- pass
346
+ # outer does not work on stacks. See
347
+ # https://github.com/data-apis/array-api/issues/242.
348
+ res = linalg .outer (x1 , x2 )
349
+
350
+ shape = (x1 .shape [0 ], x2 .shape [0 ])
351
+ assert res .shape == shape , "outer() did not return the correct shape"
352
+ assert res .dtype == dh .promotion_table [x1 , x2 ], "outer() did not return the correct dtype"
353
+
354
+ if 0 in shape :
355
+ true_res = _array_module .empty (shape , dtype = res .dtype )
356
+ else :
357
+ true_res = _array_module .asarray ([[x1 [i ]* x2 [j ]
358
+ for j in range (x2 .shape [0 ])]
359
+ for i in range (x1 .shape [0 ])],
360
+ dtype = res .dtype )
361
+
362
+ assert_exactly_equal (res , true_res )
348
363
349
364
@given (
350
365
x = xps .arrays (dtype = xps .floating_dtypes (), shape = shapes ),
@@ -363,11 +378,38 @@ def test_qr(x, kw):
363
378
pass
364
379
365
380
@given (
366
- x = xps .arrays (dtype = xps .floating_dtypes (), shape = shapes ),
381
+ x = xps .arrays (dtype = xps .floating_dtypes (), shape = square_matrix_shapes ),
367
382
)
368
383
def test_slogdet (x ):
369
- # res = linalg.slogdet(x)
370
- pass
384
+ res = linalg .slogdet (x )
385
+
386
+ _test_namedtuple (res , ['sign' , 'logabsdet' ], 'slotdet' )
387
+
388
+ sign , logabsdet = res
389
+
390
+ assert sign .dtype == x .dtype , "slogdet().sign did not return the correct dtype"
391
+ assert sign .shape == x .shape [:- 2 ], "slogdet().sign did not return the correct shape"
392
+ assert logabsdet .dtype == x .dtype , "slogdet().logabsdet did not return the correct dtype"
393
+ assert logabsdet .shape == x .shape [:- 2 ], "slogdet().logabsdet did not return the correct shape"
394
+
395
+
396
+ _test_stacks (lambda x : linalg .slogdet (x ).sign , x ,
397
+ res = sign , dims = 0 )
398
+ _test_stacks (lambda x : linalg .slogdet (x ).logabsdet , x ,
399
+ res = logabsdet , dims = 0 )
400
+
401
+ # Check that when the determinant is 0, the sign and logabsdet are (0,
402
+ # -inf).
403
+ d = linalg .det (x )
404
+ zero_det = equal (d , zero (d .shape , d .dtype ))
405
+ assert_exactly_equal (sign [zero_det ], zero (sign [zero_det ].shape , x .dtype ))
406
+ assert_exactly_equal (logabsdet [zero_det ], - infinity (logabsdet [zero_det ].shape , x .dtype ))
407
+
408
+ # More generally, det(x) should equal sign*exp(logabsdet), but this does
409
+ # not hold exactly due to floating-point loss of precision.
410
+
411
+ # TODO: Test this when we have tests for floating-point values.
412
+ # assert all(abs(linalg.det(x) - sign*exp(logabsdet)) < eps)
371
413
372
414
@given (
373
415
x1 = xps .arrays (dtype = xps .floating_dtypes (), shape = shapes ),
0 commit comments