Last active
December 15, 2016 17:58
-
-
Save rldotai/0b0e56c4dfb17cde00f2 to your computer and use it in GitHub Desktop.
Pure Python Vector class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
A simple implementation of vectors in Python modelled after tuples, but having | |
altered some of the operations to be closer to vector arithmetic. | |
It targets Python 3.5+ in order to support __matmul__, allowing for dot | |
products, which I have heard are important in linear algebra. | |
We check for whether it is operating on a number in order to implement | |
broadcasting; otherwise it performs the operations elementwise. | |
We also use `zip_longest` because it performs an implicit check for sequences | |
of unequal length; it pads the iteration with `None`, which will raise an error | |
during arithmetic operations. | |
""" | |
from itertools import zip_longest | |
from numbers import Number | |
from operator import add, floordiv, mul, pow, sub, truediv | |
class Vector(tuple): | |
def __abs__(self): | |
return Vector(abs(x) for x in self) | |
def __add__(self, other): | |
if isinstance(other, Number): | |
return Vector(i + other for i in self) | |
return Vector(add(a, b) for a, b in zip_longest(self, other)) | |
def __floordiv__(self, other): | |
if isinstance(other, Number): | |
return Vector(i // other for i in self) | |
return Vector(floordiv(a, b) for a, b in zip_longest(self, other)) | |
def __matmul__(self, other): | |
return sum(mul(a, b) for a, b in zip_longest(self, other)) | |
def __mul__(self, other): | |
if isinstance(other, Number): | |
return Vector(i * other for i in self) | |
return Vector(mul(a, b) for a, b in zip_longest(self, other)) | |
def __neg__(self): | |
return Vector(-x for x in self) | |
def __pow__(self, other): | |
if isinstance(other, Number): | |
return Vector(i**other for i in self) | |
return Vector(pow(a, b) for a, b in zip_longest(self, other)) | |
def __sub__(self, other): | |
if isinstance(other, Number): | |
return Vector(i - other for i in self) | |
return Vector(sub(a, b) for a, b in zip_longest(self, other)) | |
def __radd__(self, other): | |
if isinstance(other, Number): | |
return Vector(i + other for i in self) | |
return Vector(add(a, b) for a, b in zip_longest(self, other)) | |
def __rfloordiv__(self, other): | |
if isinstance(other, Number): | |
return Vector(i // other for i in self) | |
return Vector(floordiv(a, b) for a, b in zip_longest(self, other)) | |
def __rmatmul__(self, other): | |
return sum(mul(a, b) for a, b in zip_longest(self, other)) | |
def __rmul__(self, other): | |
if isinstance(other, Number): | |
return Vector(i * other for i in self) | |
return Vector(mul(a, b) for a, b in zip_longest(self, other)) | |
def __rpow__(self, other): | |
if isinstance(other, Number): | |
return Vector(i**other for i in self) | |
return Vector(pow(a, b) for a, b in zip_longest(self, other)) | |
def __rsub__(self, other): | |
if isinstance(other, Number): | |
return Vector(i - other for i in self) | |
return Vector(sub(a, b) for a, b in zip_longest(self, other)) | |
def __rtruediv__(self, other): | |
if isinstance(other, Number): | |
return Vector(i / other for i in self) | |
return Vector(truediv(a, b) for a, b in zip_longest(self, other)) | |
def __truediv__(self, other): | |
if isinstance(other, Number): | |
return Vector(i / other for i in self) | |
return Vector(truediv(a, b) for a, b in zip_longest(self, other)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello,
looks good, would you add a license, so that I can (hopefully) use it in my code?
Thank you.
ps my code is MIT licenced.