2
\$\begingroup\$

I wrote this function to multiply vector with a matrix and I was wondering if someone experienced can spot something can improved its performance.

class matrix:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.m = [[0 for i in range(width)]for i in range(height)]

class vec2:
    def __init__(self, x, y):
        self.x, self.y = x, y
        self.vals = [x, y]
        
class vec3:
    def __init__(self, x, y, z):
        self.x, self.y, self.z = x, y, z
        self.vals = [x, y, z]

matrix = matrix(3, 3)
matrix.m[0][0] = 2
matrix.m[0][1] = 1
matrix.m[0][2] = 0.5
matrix.m[1][0] = 1
matrix.m[2][0] = 1
matrix.m[1][2] = 0.2

vector = vec3(1, 10, 10)

def multVecMat(vec, mat):
    canCarryOut = False
    if vec.__class__.__name__ == "vec3":
        if mat.width == 3 and mat.height == 3:
            canCarryOut = True
            newVec = vec3(0, 0, 0)
    else:
        if vec.__class__.__name__ == "vec2":
            if mat.width == 2 and mat.height == 2:
                canCarryOut = True
                newVec = vec2(0, 0)

    if canCarryOut:
        vecValues = []
        for v in range(mat.width):
            tempValues = []
            for m in range(mat.height):
                tempValues.append(vec.vals[v]*mat.m[v][m])
            vecValues.append(sum(tempValues))
        if vec.__class__.__name__ == "vec3":
            newVec.x, newVec.y, newVec.z = vecValues[0], vecValues[1], vecValues[2]
        else:
             newVec.x, newVec.y = vecValues[0], vecValues[1]

        return newVec
    raise ValueError


v = multVecMat(vector, matrix)
print(v.x, v.y, v.z)
\$\endgroup\$
3
  • \$\begingroup\$ First thing to notice is, that you check for square matrices. But you can multiply vectors (essentially rectangular matrices) with non-square matrices, which results in a new rectangular matrix. Only if the matrix is square, you'll get a vector in return. \$\endgroup\$ Commented Oct 5, 2020 at 13:00
  • \$\begingroup\$ Ah yes. I noticed that as well but I wasn't too sure about how I would go about doing that. For 3d, I came up with this but I am still not sure If it works for all cases: if vec.__class__.__name__ == "vec3": if mat.height == 3 and mat.width < 4: \$\endgroup\$ Commented Oct 5, 2020 at 13:21
  • \$\begingroup\$ since the arguments are (vec, math), you multiply a row vector with a matrix. the matrix's row size must match the vector column size. For further reading see here \$\endgroup\$ Commented Oct 5, 2020 at 13:30

1 Answer 1

1
\$\begingroup\$

Throw out the works and use Numpy. Seriously. Rolling your own matrix multiplication is fun and educational, but pretty much immediately reaches its limit if you care about performance. There is no universe in which a native Python implementation of low-level matrix operations will out-perform a well-written C library that has FFI to Python.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.