Skip to content

Instantly share code, notes, and snippets.

@jul
Last active August 29, 2024 00:25
Show Gist options
  • Save jul/265589b0436317cafc5c3e336bf69724 to your computer and use it in GitHub Desktop.
Save jul/265589b0436317cafc5c3e336bf69724 to your computer and use it in GitHub Desktop.
matrix as a view on a linear array
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