Coverage for /usr/lib/python3/dist-packages/sympy/matrices/expressions/slice.py: 26%
65 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1from sympy.matrices.expressions.matexpr import MatrixExpr
2from sympy.core.basic import Basic
3from sympy.core.containers import Tuple
4from sympy.functions.elementary.integers import floor
6def normalize(i, parentsize):
7 if isinstance(i, slice):
8 i = (i.start, i.stop, i.step)
9 if not isinstance(i, (tuple, list, Tuple)):
10 if (i < 0) == True:
11 i += parentsize
12 i = (i, i+1, 1)
13 i = list(i)
14 if len(i) == 2:
15 i.append(1)
16 start, stop, step = i
17 start = start or 0
18 if stop is None:
19 stop = parentsize
20 if (start < 0) == True:
21 start += parentsize
22 if (stop < 0) == True:
23 stop += parentsize
24 step = step or 1
26 if ((stop - start) * step < 1) == True:
27 raise IndexError()
29 return (start, stop, step)
31class MatrixSlice(MatrixExpr):
32 """ A MatrixSlice of a Matrix Expression
34 Examples
35 ========
37 >>> from sympy import MatrixSlice, ImmutableMatrix
38 >>> M = ImmutableMatrix(4, 4, range(16))
39 >>> M
40 Matrix([
41 [ 0, 1, 2, 3],
42 [ 4, 5, 6, 7],
43 [ 8, 9, 10, 11],
44 [12, 13, 14, 15]])
46 >>> B = MatrixSlice(M, (0, 2), (2, 4))
47 >>> ImmutableMatrix(B)
48 Matrix([
49 [2, 3],
50 [6, 7]])
51 """
52 parent = property(lambda self: self.args[0])
53 rowslice = property(lambda self: self.args[1])
54 colslice = property(lambda self: self.args[2])
56 def __new__(cls, parent, rowslice, colslice):
57 rowslice = normalize(rowslice, parent.shape[0])
58 colslice = normalize(colslice, parent.shape[1])
59 if not (len(rowslice) == len(colslice) == 3):
60 raise IndexError()
61 if ((0 > rowslice[0]) == True or
62 (parent.shape[0] < rowslice[1]) == True or
63 (0 > colslice[0]) == True or
64 (parent.shape[1] < colslice[1]) == True):
65 raise IndexError()
66 if isinstance(parent, MatrixSlice):
67 return mat_slice_of_slice(parent, rowslice, colslice)
68 return Basic.__new__(cls, parent, Tuple(*rowslice), Tuple(*colslice))
70 @property
71 def shape(self):
72 rows = self.rowslice[1] - self.rowslice[0]
73 rows = rows if self.rowslice[2] == 1 else floor(rows/self.rowslice[2])
74 cols = self.colslice[1] - self.colslice[0]
75 cols = cols if self.colslice[2] == 1 else floor(cols/self.colslice[2])
76 return rows, cols
78 def _entry(self, i, j, **kwargs):
79 return self.parent._entry(i*self.rowslice[2] + self.rowslice[0],
80 j*self.colslice[2] + self.colslice[0],
81 **kwargs)
83 @property
84 def on_diag(self):
85 return self.rowslice == self.colslice
88def slice_of_slice(s, t):
89 start1, stop1, step1 = s
90 start2, stop2, step2 = t
92 start = start1 + start2*step1
93 step = step1 * step2
94 stop = start1 + step1*stop2
96 if stop > stop1:
97 raise IndexError()
99 return start, stop, step
102def mat_slice_of_slice(parent, rowslice, colslice):
103 """ Collapse nested matrix slices
105 >>> from sympy import MatrixSymbol
106 >>> X = MatrixSymbol('X', 10, 10)
107 >>> X[:, 1:5][5:8, :]
108 X[5:8, 1:5]
109 >>> X[1:9:2, 2:6][1:3, 2]
110 X[3:7:2, 4:5]
111 """
112 row = slice_of_slice(parent.rowslice, rowslice)
113 col = slice_of_slice(parent.colslice, colslice)
114 return MatrixSlice(parent.parent, row, col)