From 683c877946737b6f165c8e84c8295f1715ba9ca0 Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Thu, 21 Aug 2008 22:30:51 +0400 Subject: [PATCH] Matrix: speedup __getattr__ and __setattr__ for element-wise access MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This two operations are the workhorse of many matrix algorithms, e.g. solve_linear_system. That's why it is so important to provide fast access to matrix elements. The speedup is done through: o not using isinstance (which is slow) and using type(x) is Y (which is much faster) instead o inlining calls to a2idx (function calls are expensive in Pthon) Timings (cache: off) -------------------- N=8 M=eye(N) %timeit %time M[0,0] integrate(x**3*sin(x), x) old: 38.3 µs 5.77 s new: 14.4 µs 5.04 s speedup: 2.66x 14% Signed-off-by: Kirill Smelkov Signed-off-by: Mateusz Paprocki --- sympy/matrices/matrices.py | 92 +++++++++++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 26 deletions(-) diff --git a/sympy/matrices/matrices.py b/sympy/matrices/matrices.py index 54e8a9a..2f8c582 100644 --- a/sympy/matrices/matrices.py +++ b/sympy/matrices/matrices.py @@ -187,19 +187,40 @@ class Matrix(object): 2 - I """ - if isinstance(key, (list, tuple)): - if len(key) == 2: - # proper 2-index access - if isinstance(key[0], slice) or isinstance(key[1], slice): - return self.submatrix(key) + if type(key) is tuple: + i, j = key + if type(i) is slice or type(j) is slice: + return self.submatrix(key) + + else: + # a2idx inlined + try: + i = i.__int__() + except AttributeError: + try: + i = i.__index__() + except AttributeError: + raise IndexError("Invalid index a[%r]" % (key,)) + + # a2idx inlined + try: + j = j.__int__() + except AttributeError: + try: + j = j.__index__() + except AttributeError: + raise IndexError("Invalid index a[%r]" % (key,)) + + + if not (i>=0 and i=0 and j < self.cols): + raise IndexError("Index out of range: a[%s]" % (key,)) else: - k1, k2 = a2idx(key[0]), a2idx(key[1]) - if k1 is not None and k2 is not None: - i,j=self.key2ij([k1, k2]) - return self.mat[i*self.cols+j] + return self.mat[i*self.cols + j] + + else: # row-wise decomposition of matrix - if isinstance(key, slice): + if type(key) is slice: return self.mat[key] else: k = a2idx(key) @@ -220,25 +241,44 @@ class Matrix(object): [9, 4] """ - if isinstance(key, (list, tuple)): - if len(key) == 2: - # proper 2-index access - if isinstance(key[0], slice) or isinstance(key[1], slice): - if isinstance(value, Matrix): - self.copyin_matrix(key, value) - return - if isinstance(value, (list, tuple)): - self.copyin_list(key, value) - return + if type(key) is tuple: + i, j = key + if type(i) is slice or type(j) is slice: + if isinstance(value, Matrix): + self.copyin_matrix(key, value) + return + if isinstance(value, (list, tuple)): + self.copyin_list(key, value) + return + else: + # a2idx inlined + try: + i = i.__int__() + except AttributeError: + try: + i = i.__index__() + except AttributeError: + raise IndexError("Invalid index a[%r]" % (key,)) + + # a2idx inlined + try: + j = j.__int__() + except AttributeError: + try: + j = j.__index__() + except AttributeError: + raise IndexError("Invalid index a[%r]" % (key,)) + + + if not (i>=0 and i=0 and j < self.cols): + raise IndexError("Index out of range: a[%s]" % (key,)) else: - k1, k2 = a2idx(key[0]), a2idx(key[1]) - if k1 is not None and k2 is not None: - i,j=self.key2ij([k1, k2]) - self.mat[i*self.cols + j] = sympify(value) - return + self.mat[i*self.cols + j] = sympify(value) + return + else: # row-wise decomposition of matrix - if isinstance(key, slice): + if type(key) is slice: raise IndexError("Vector slices not implemented yet.") else: k = a2idx(key) -- 2.11.4.GIT