def __init__(self, data): '''Implementa um array de vetores bidimensionais. As operações matemáticas podem ser aplicadas diretamente ao array Exemplo ------- Criamos um array inicializando com uma lista de vetores ou uma lista de duplas >>> a = VecArray([(0, 0), (1, 0), (0, 1)]); a VecArray([(0, 0), (1, 0), (0, 1)]) Sob muitos aspectos, um VecArray funciona como uma lista de vetores >>> a[0], a[1] (Vec(0, 0), Vec(1, 0)) As operações matemáticas ocorrem termo a termo >>> a + (1, 1) VecArray([(1, 1), (2, 1), (1, 2)]) Já as funções de vetores são propagadas para cada elemento e retornam um Array numérico ou um VecArray >>> a.norm() Array([0, 1, 1]) ''' data = iter(data) L = self._data = [asvector(next(data))] for u in data: v = asvector(u) assert v.__class__ is L[-1].__class__ L.append(v)
def pos(self): length = 0 vector_part = Vec(0.0, 0.0) pt0 = self[-1] for pt in self: delta = asvector(pt - pt0).norm() #FIXME: Point subtraction --> Vec middle = asvector(pt.middle(pt0)) vector_part += delta * middle length += delta pt0 = pt return vector_part / length
def __iter__(self): N, M = self.shape data = self.flat start = 0 for _ in range(N): yield asvector(data[start:start + M]) start += M
def __mul__(self, other): if isinstance(other, (Vec, tuple, list)): other = asvector(other) return asvector([u.dot(other) for u in self.rows()]) elif isinstance(other, number): return self.from_flat([x * other for x in self.flat]) elif isinstance(other, Mat): cols = list(other.cols()) rows = list(self.rows()) data = sum([[u.dot(v) for u in cols] for v in rows], []) return type(self).from_flat(data) else: return NotImplemented
def diag(self): """ Return a vector with the diagonal elements of the matrix. """ N = self.nrows data = self.flat return asvector([data.flat[i * N + i] for i in range(N)])
def __mul__(self, other): if isinstance(other, (Vec, tuple, list)): other = asvector(other) return asvector([u.dot(other) for u in self.rows()]) elif isinstance(other, number): return self.from_flat([x * other for x in self.flat], copy=False) elif isinstance(other, Mat): cols = list(other.cols()) rows = list(self.rows()) data = sum([[u.dot(v) for u in cols] for v in rows], []) cls = self.__origin__[len(rows), len(cols), _dtype(data)] return cls.from_flat(data, copy=False) else: return NotImplemented
def rotate(self, theta, axis=None): """Retorna um vetor rotacionado por um ângulo theta""" # FIXME: use rotation matrix # R = RotMat2(theta) if axis is None: self._data[:] = [u.irotate(theta) for u in self._data] else: v = asvector(axis) self._data[:] = [v + (u - v).irotate(theta) for u in self._data]
def rotate(self, theta, axis=None): """Retorna um vetor rotacionado por um ângulo theta""" # FIXME: use rotation matrix # R = RotMat2(theta) if axis is None: self._data[:] = [u.rotated_by(theta) for u in self._data] else: v = asvector(axis) self._data[:] = [v + (u - v).rotated_by(theta) for u in self._data]
def row(self, i): """ Return the i-th row Vec. Same as matrix[i], but exists for symmetry with the matrix.col(i) method. """ M = self.ncols start = i * M return asvector(self.flat[start:start + M])
def solve_jacobi(self, b, tol=1e-3, x0=None, maxiter=1000): """ Solve a linear using Gauss-Jacobi method. """ b = asvector(b) x = b * 0 D = self.from_diag([1.0 / x for x in self.diag()]) R = self.new_dropping_diag() for _ in range(maxiter): x, old = D * (b - R * x), x if (x - old).norm() < tol: break return x
def solve_triangular(self, b, lower=False): """ Solve a triangular system. If lower=True, it assumes a lower triangular matrix, otherwise (default) assumes an upper triangular matrix. """ N = self.nrows x = [0] * N if lower: for i in range(N): x[i] = (b[i] - self[i].dot(x)) / self[i, i] else: for i in range(N - 1, -1, -1): x[i] = (b[i] - self[i].dot(x)) / self[i, i] return asvector(x)
def cols(self): """ Iterator over columns of matrix See also: :method:`rows`: iterate over the rows of a matrix. Example: >>> M = Mat([1, 2], ... [3, 4]) >>> list(M.cols()) [Vec(1, 3), Vec(2, 4)] >>> list(M.rows()) [Vec(1, 2), Vec(3, 4)] """ M = self.ncols data = self.flat for i in range(M): yield asvector(data[i::M])
def __sub__(self, other): other = asvector(other) return self._new(u - other for u in self._data)
def decorated_accept_vec_args(self, *args): if len(args) == 1: return func(self, asvector(args[0])) else: return func(self, asvector(args))
def __rsub__(self, other): '''x.__rsub__(y) <==> y - x''' other = asvector(other) return self._new(other - u for u in self._data)
def __init__(self, start, end): self._start = asvector(start) self._end = asvector(end)
def __iadd__(self, other): other = asvector(other) self._data[:] = [u + other for u in self._data] return self
def __add__(self, other): '''x.__add__(y) <==> x + y''' other = asvector(other) return self._new([u + other for u in self._data])
def __rmul__(self, other): if isinstance(other, number): return self.from_flat([x * other for x in self.flat], copy=False) else: other = asvector(other) return asvector([u.dot(other) for u in self.cols()])
def __init__(self, start, direction): self.pos = asvector(start) self.tangent = asdirection(direction)
def __isub__(self, other): '''x.__add__(y) <==> x + y''' other = asvector(other) self._data[:] = [u - other for u in self._data] return self
def __rsub__(self, other): other = asvector(other) return self._new(other - u for u in self._data)
def __isub__(self, other): other = asvector(other) self._data[:] = [u - other for u in self._data] return self
def __add__(self, other): other = asvector(other) return self._new([u + other for u in self._data])
def decorated(self, *args): if len(args) == 1: return func(self, asvector(args[0])) else: return func(self, asvector(args))
def col(self, i): """ Return the i-th column Vec. """ return asvector(self.flat[i::self.ncols])
def __sub__(self, other): '''x.__sub__(y) <==> x - y''' other = asvector(other) return self._new(u - other for u in self._data)