|
1 | 1 | from functools import reduce
|
2 | 2 | from operator import mul
|
3 | 3 | from math import sqrt
|
| 4 | +import itertools |
4 | 5 |
|
5 | 6 | from hypothesis import assume
|
6 | 7 | from hypothesis.strategies import (lists, integers, sampled_from,
|
|
12 | 13 | from .array_helpers import (dtype_ranges, integer_dtype_objects,
|
13 | 14 | floating_dtype_objects, numeric_dtype_objects,
|
14 | 15 | boolean_dtype_objects,
|
15 |
| - integer_or_boolean_dtype_objects, dtype_objects) |
| 16 | + integer_or_boolean_dtype_objects, dtype_objects, |
| 17 | + ndindex) |
16 | 18 | from ._array_module import (full, float32, float64, bool as bool_dtype,
|
17 | 19 | _UndefinedStub, eye, broadcast_to)
|
18 | 20 | from . import _array_module
|
@@ -150,6 +152,24 @@ def positive_definite_matrices(draw, dtypes=xps.floating_dtypes()):
|
150 | 152 | dtype = draw(dtypes)
|
151 | 153 | return broadcast_to(eye(n, dtype=dtype), shape)
|
152 | 154 |
|
| 155 | +@composite |
| 156 | +def invertible_matrices(draw, dtypes=xps.floating_dtypes()): |
| 157 | + # For now, just generate stacks of diagonal matrices. |
| 158 | + n = draw(integers(0, SQRT_MAX_ARRAY_SIZE),) |
| 159 | + stack_shape = draw(shapes) |
| 160 | + shape = stack_shape + (n, n) |
| 161 | + d = draw(xps.arrays(dtypes, shape=n*prod(stack_shape), |
| 162 | + elements=dict(allow_nan=False, allow_infinity=False))) |
| 163 | + # Functions that require invertible matrices may do anything when it is |
| 164 | + # singular, including raising an exception, so we make sure the diagonals |
| 165 | + # are sufficiently nonzero to avoid any numerical issues. |
| 166 | + assume(xp.all(xp.abs(d) > 0.5)) |
| 167 | + |
| 168 | + a = xp.zeros(shape) |
| 169 | + for j, (idx, i) in enumerate(itertools.product(ndindex(stack_shape), range(n))): |
| 170 | + a[idx + (i, i)] = d[j] |
| 171 | + return a |
| 172 | + |
153 | 173 | @composite
|
154 | 174 | def two_broadcastable_shapes(draw):
|
155 | 175 | """
|
|
0 commit comments