0

Ill make this short, I have two instances of a 4x4 matrix that seam to share the internal data list. the erroneous code goes as follows.

mat0 = Matrix4f.Matrix4f()
print mat0
~ prints ~
[ 0.0,  0.0,    0.0,    0.0 ] # empty matrix
[ 0.0,  0.0,    0.0,    0.0 ]
[ 0.0,  0.0,    0.0,    0.0 ]
[ 0.0,  0.0,    0.0,    0.0 ]
~
mat0.initIdentity()
print mat0
~ prints ~
[ 1.0,  0.0,    0.0,    0.0 ] # identity matrix
[ 0.0,  1.0,    0.0,    0.0 ]
[ 0.0,  0.0,    1.0,    0.0 ]
[ 0.0,  0.0,    0.0,    1.0 ]
~

mat1 = Matrix4f.Matrix4f()
print mat0
~ prints ~
[ 1.0,  0.0,    0.0,    0.0 ] # still identity matrix
[ 0.0,  1.0,    0.0,    0.0 ]
[ 0.0,  0.0,    1.0,    0.0 ]
[ 0.0,  0.0,    0.0,    1.0 ]
~
mat1.mat[3] = 96
print mat0
~ prints ~
[ 1.0,  0.0,    0.0,    96 ]  # why has mat0 changed as well...?
[ 0.0,  1.0,    0.0,    0.0 ]
[ 0.0,  0.0,    1.0,    0.0 ]
[ 0.0,  0.0,    0.0,    1.0 ]
~

for full information, ill provide the complete Matrix4f module, though i recon the top 20 lines will be most pertinent. Am I missing anything? Or is that something that happens with lists?

class Matrix4f:

# alloc
def __init__(self, mat = [0.] * 16):
    if len(mat) is not 16:
        raise Exception("matrix array given is not of length 16")
    self.mat = mat

# identity matrix
def initIdentity(self):
    self.mat[ 0] = 1.
    self.mat[ 5] = 1.
    self.mat[10] = 1.
    self.mat[15] = 1.

# Orthographic projection matrix
def initOrtho(self, left, right, bottom, top, near = -1, far = 1):
    self.mat[ 0] = 2. / (right - left)
    self.mat[ 3] = - (right + left) / (right - left)
    self.mat[ 5] = 2. / (top - bottom)
    self.mat[ 7] = - (top + bottom) / (top - bottom)
    self.mat[10] = 2. / (far - near)
    self.mat[11] = - (far + near) / (far - near)
    self.mat[15] = 1.

def __mul__(self, other):
    ret = Matrix4f()
    ret.mat[ 0] = self.mat[ 0] * other.mat[ 0] + self.mat[ 1] * other.mat[ 4] + self.mat[ 2] * other.mat[ 8] + self.mat[ 3] * other.mat[12]
    ret.mat[ 1] = self.mat[ 0] * other.mat[ 1] + self.mat[ 1] * other.mat[ 5] + self.mat[ 2] * other.mat[ 9] + self.mat[ 3] * other.mat[13]
    ret.mat[ 2] = self.mat[ 0] * other.mat[ 2] + self.mat[ 1] * other.mat[ 6] + self.mat[ 2] * other.mat[10] + self.mat[ 3] * other.mat[14]
    ret.mat[ 3] = self.mat[ 0] * other.mat[ 3] + self.mat[ 1] * other.mat[ 7] + self.mat[ 2] * other.mat[11] + self.mat[ 3] * other.mat[15]
    ret.mat[ 4] = self.mat[ 4] * other.mat[ 0] + self.mat[ 5] * other.mat[ 4] + self.mat[ 6] * other.mat[ 8] + self.mat[ 7] * other.mat[12]
    ret.mat[ 5] = self.mat[ 4] * other.mat[ 1] + self.mat[ 5] * other.mat[ 5] + self.mat[ 6] * other.mat[ 9] + self.mat[ 7] * other.mat[13]
    ret.mat[ 6] = self.mat[ 4] * other.mat[ 2] + self.mat[ 5] * other.mat[ 6] + self.mat[ 6] * other.mat[10] + self.mat[ 7] * other.mat[14]
    ret.mat[ 7] = self.mat[ 4] * other.mat[ 3] + self.mat[ 5] * other.mat[ 7] + self.mat[ 6] * other.mat[11] + self.mat[ 7] * other.mat[15]
    ret.mat[ 8] = self.mat[ 8] * other.mat[ 0] + self.mat[ 9] * other.mat[ 4] + self.mat[10] * other.mat[ 8] + self.mat[11] * other.mat[12]
    ret.mat[ 9] = self.mat[ 8] * other.mat[ 1] + self.mat[ 9] * other.mat[ 5] + self.mat[10] * other.mat[ 9] + self.mat[11] * other.mat[13]
    ret.mat[10] = self.mat[ 8] * other.mat[ 2] + self.mat[ 9] * other.mat[ 6] + self.mat[10] * other.mat[10] + self.mat[11] * other.mat[14]
    ret.mat[11] = self.mat[ 8] * other.mat[ 3] + self.mat[ 9] * other.mat[ 7] + self.mat[10] * other.mat[11] + self.mat[11] * other.mat[15]
    ret.mat[12] = self.mat[12] * other.mat[ 0] + self.mat[13] * other.mat[ 4] + self.mat[14] * other.mat[ 8] + self.mat[15] * other.mat[12]
    ret.mat[13] = self.mat[12] * other.mat[ 1] + self.mat[13] * other.mat[ 5] + self.mat[14] * other.mat[ 9] + self.mat[15] * other.mat[13]
    ret.mat[14] = self.mat[12] * other.mat[ 2] + self.mat[13] * other.mat[ 6] + self.mat[14] * other.mat[10] + self.mat[15] * other.mat[14]
    ret.mat[15] = self.mat[12] * other.mat[ 3] + self.mat[13] * other.mat[ 7] + self.mat[14] * other.mat[11] + self.mat[15] * other.mat[15]
    return ret

# to string
def __str__(self, terminate = "\n"):
    return ("[ " + str(self.mat[ 0]) + ",\t" + str(self.mat[ 1]) + ",\t" + str(self.mat[ 2]) + ",\t" + str(self.mat[ 3]) + " ]\n"
            "[ " + str(self.mat[ 4]) + ",\t" + str(self.mat[ 5]) + ",\t" + str(self.mat[ 6]) + ",\t" + str(self.mat[ 7]) + " ]\n"
            "[ " + str(self.mat[ 8]) + ",\t" + str(self.mat[ 9]) + ",\t" + str(self.mat[10]) + ",\t" + str(self.mat[11]) + " ]\n"
            "[ " + str(self.mat[12]) + ",\t" + str(self.mat[13]) + ",\t" + str(self.mat[14]) + ",\t" + str(self.mat[15]) + " ]" + terminate)

sorry about the indent...

Thanks in advance!

claudehenry
  • 736
  • 8
  • 17
  • Have you heard of loops? You should really be using loops to implement those `__mul__` and `__str__` methods instead of copy-pasting so much code. – user2357112 Mar 06 '16 at 08:20
  • @user2357112, I'll give you the str one, sure, i could have used a loop, but the mul of a matrix is usually written componentwise, also, thx for the link that helped. I come from a C++ background so i wasn't expecting functions to be first class citizen – claudehenry Mar 06 '16 at 08:27
  • What do you mean, "usually written componentwise"? Naive matrix multiplication like you've written is usually implemented with 3 nested loops. It's certainly not implemented by individually writing out 144 element accesses, 64 multiplications, and 48 additions. I hope you're not going to produce megabytes of source code for a 50x50 matrix. – user2357112 Mar 06 '16 at 08:34
  • @user2357112, no, theres a difference between handling a specific case (in this case 4x4) and a general case. Considering the uses i have for my matrix4f classes, that being tranforms in 3D graphics, i don't have time to waste with a generic matrix multiplication algorithm. And, as far as "It's certainly not implemented by individually writing out [...]" I'd beg to differ, and refer you to several Matrix4 classes : https://github.com/hharrison/vecmath/blob/master/src/javax/vecmath/Matrix4f.java https://github.com/g-truc/glm/blob/master/glm/detail/type_mat4x4.inl – claudehenry Mar 06 '16 at 08:50
  • If you're pressed for speed enough to want to unroll those loops, why are you doing math in interpreted Python? You're taking like a 100x to 1000x performance hit from interpreter overhead. Get NumPy and take advantage of its array operations, or turn your code into an extension module with Cython. Trying to optimize Python like it's C++ isn't going to produce efficient code. – user2357112 Mar 06 '16 at 09:18
  • cool, ill look into that, didn't know that was an option. thanks for the help! – claudehenry Mar 06 '16 at 09:25

0 Answers0