Last active
August 29, 2024 00:25
-
-
Save jul/265589b0436317cafc5c3e336bf69724 to your computer and use it in GitHub Desktop.
matrix as a view on a linear array
This file contains hidden or 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
class DimensionError(Exception): | |
pass | |
class matrix(object): | |
def __eq__(self, tocomp): | |
other=tocomp | |
if type(tocomp) != type(self): | |
other=matrix(tocomp) | |
return (self.__val__, self.dim) == (other.__val__, other.dim) | |
def __init__(self,a,**kw): | |
if kw.get("dim"): | |
self.__val__ = a | |
self.dim = kw["dim"] | |
else: | |
self.__val__,self.dim = list(self.flattener(a)) | |
def flattener(self, v): | |
dimy=len(v[0]) | |
dimx=len(v) | |
ret = [ j for i in v for j in i ] | |
assert len(ret) == dimx*dimy | |
return ret,(dimx, dimy) | |
def unflattener(self): | |
return self[(0,0): (self.dim[0]-1, self.dim[1]-1)] | |
def __setitem__(self, k, v): | |
if type(k)==int: | |
# set nth line with slice | |
raise NotImplementedError() | |
for e, p in enumerate(zip(k,self.dim)): | |
i,j=p | |
try: | |
assert i <= j, f"ooupla dim:{e+1} {i}>{j} " | |
except: | |
raise IndexError | |
x,y=k | |
dy=self.dim[1] | |
offby=x*(dy)+y | |
self.__val__[offby]=v | |
def __repr__(self): | |
return repr(self.unflattener()) | |
def __getitem__(self, k): | |
x,y = 0,0 | |
dx, dy=self.dim | |
step=(1,1) | |
if type(k)==int: | |
return self[(k,0):(k,dy-1)][0] | |
if not isinstance(k,slice): | |
x, y=k | |
for e, p in enumerate(zip(k,self.dim)): | |
i,j=p | |
try: | |
assert i <= j, f"ooupla dim:{e+1} {i}<={j} k={k}" | |
except: | |
raise IndexError | |
off=x*dy+y | |
return self.__val__[off] | |
start, stop, step=k.start,k.stop,k.step | |
step = step or (1,1) | |
x0, xn, xd=start[1], stop[1]+1, step[1] | |
if x0 > xn or xn < 0: | |
raise NotImplementedError() | |
y0, yn, yd=start[0], stop[0]+1, step[0] | |
if y0 > yn or yn < 0: | |
raise NotImplementedError() | |
ret = [] | |
for y in range(y0,yn, yd): | |
ret+=[[],] | |
for x in range(x0, xn, xd): | |
# row padding | |
# I HATE PYTHON for [[],] * n => shallow copies ! | |
# if not for this bug, padding would be as simple as | |
# if y-y0>=len(ret): | |
# ret+=[[],] * (y-y0-len(ret)+1) | |
for k in range(len(ret)-1, y-y0): | |
ret+=[[],] | |
ret[y-y0]+=[self[(y,x)]] | |
return ret | |
def transpose(md): | |
res = [] | |
for x in range(md.dim[1]): | |
res+=[[0] * md.dim[0],] | |
for y in range(md.dim[0]): | |
res[x][y]=md[(y,x)] | |
return matrix(res) | |
def mul(m,n): | |
mx,my=m.dim | |
nx,ny=n.dim | |
v = matrix([0,] * (mx * ny), dim = (mx, ny)) | |
stride=my-1 | |
for x in range(mx): | |
for y in range(ny): | |
#z=sum([ x*y for x,y in zip(matrix(n[(0,y):(0+stride,y)]).__val__,matrix(m[(x,0):(x,0+stride)]).__val__)]) | |
zz = sum(map(lambda e: e[0]*e[1],zip( | |
m[(x,0):(x,0+stride)][0], # xth line from m | |
matrix(n[(0,y):(0+stride,y)]).__val__, # yth row from n | |
))) | |
v[(x,y)]=zz | |
return v | |
m= matrix([[1,2],[3,4], [5,6], [7,8],[9,10]]) | |
assert m[1][0] == m[(1,0)] | |
assert m[2][0] == m[(2,0)] | |
assert m[1][1] == m[(1,1)] | |
assert m[3][1] == m[(3,1)] | |
assert m[(-1,-1)]==8 | |
assert m[0] == [1,2] | |
assert m[1] == [3,4] | |
assert m[2] == [5,6] | |
assert m[3] == [7,8] | |
assert m[(0,0)]==1 | |
assert m[(0,1)]==2 | |
assert m[(1,0)]==3 | |
assert m[(1,1)]==4 | |
assert m[(2,0)]==5 | |
assert m[(2,1)]==6 | |
assert m[(0,0):(0,1)]==[m[0],] | |
assert m[(0,0):(1,0)] == [[1], [3]] | |
assert m[(0,0):(1,1)]==[[1,2], [3,4]] | |
assert m[(0,0):(2,1):(2,1)] == [[1, 2], [], [5, 6]] | |
assert m[(0,0):(3,0)] == [[1], [3], [5], [7]] | |
assert m[(0,1):(3,1)] == [[2], [4], [6], [8]] | |
assert m[(0,0):(3,0):(2,1)] == [[1], [], [5]] | |
assert m[(0,0):(3,0):(3,1)] == [[1], [], [], [7]] | |
assert m[(0,0)] == 1 | |
assert m[(1,0)]==3 | |
try: | |
print(m[(6,1)]) | |
except IndexError: | |
pass | |
from time import time | |
m= matrix([[1,2],[3,4], [5,6], [7,8],[9,10]]) | |
n= matrix([[11,12],[13,14], [15,16], [17,18],[19,20]]) | |
start=time() | |
for i in range(100_000): | |
c=matrix(list(map(lambda x:x[0]+x[1], zip(m.__val__, n.__val__))), dim=m.dim) | |
print("addition with zip") | |
print(time() - start) | |
start=time() | |
for i in range(100_000): | |
dx,dy=m.dim | |
c=[] | |
for x in range(dx): | |
c+=[[0] * (dy), ] | |
for y in range(dy): | |
c[x][y]=m[x][y]+n[x][y] | |
print("addition with full loops") | |
print(time() - start) | |
m = matrix([[1,2,0],[4,3,-1]]) | |
n = matrix([[5,1],[2,3],[3,4]]) | |
assert mul(m,n)==[[9, 7], [23, 9]] | |
n,m = m,n | |
assert mul(m,n) == [[9, 13, -1], [14, 13, -3], [19, 18, -4]] | |
m=matrix([[1],[-1],[1], [1]]) | |
n=matrix([[-10,2,3, 4],]) | |
assert mul(m,n)==[[-10, 2, 3, 4], [10, -2, -3, -4], [-10, 2, 3, 4], [-10, 2, 3, 4]] | |
assert mul(n,m)== [[-5]] | |
m=matrix([[1],[-1],[1]]) | |
n=matrix([[-7,2,3],[1,-2,3],]) | |
assert mul(m,n)==[[-7, 2, 3], [7, -2, -3], [-7, 2, 3]] | |
assert mul(n,m) == [[-6], [6]] | |
m= matrix([[1,2],[3,4], [5,6], [7,8],[9,10]]) | |
assert m[1] == [3,4] | |
assert mul(transpose(m),m)==[[165, 190], [190, 220]] | |
assert transpose(m) == [[1, 3, 5, 7, 9], [2, 4, 6, 8, 10]] | |
assert m[1] == [3,4] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment