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

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 

5 

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 

25 

26 if ((stop - start) * step < 1) == True: 

27 raise IndexError() 

28 

29 return (start, stop, step) 

30 

31class MatrixSlice(MatrixExpr): 

32 """ A MatrixSlice of a Matrix Expression 

33 

34 Examples 

35 ======== 

36 

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]]) 

45 

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]) 

55 

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)) 

69 

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 

77 

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) 

82 

83 @property 

84 def on_diag(self): 

85 return self.rowslice == self.colslice 

86 

87 

88def slice_of_slice(s, t): 

89 start1, stop1, step1 = s 

90 start2, stop2, step2 = t 

91 

92 start = start1 + start2*step1 

93 step = step1 * step2 

94 stop = start1 + step1*stop2 

95 

96 if stop > stop1: 

97 raise IndexError() 

98 

99 return start, stop, step 

100 

101 

102def mat_slice_of_slice(parent, rowslice, colslice): 

103 """ Collapse nested matrix slices 

104 

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)