Skip to content

Commit

Permalink
Fix #210: matrix multiplication of array of vectors (#212)
Browse files Browse the repository at this point in the history
* fix

* Fix matrix multiplication in arrays

+ Should fix #210
+ Fixed matrix multiplication for `arr * arr`, `mat * arr` and `arr * mat`

---------

Co-authored-by: Zuzu-Typ <[email protected]>
  • Loading branch information
cspotcode and Zuzu-Typ authored Feb 26, 2023
1 parent 97841d8 commit 9f2cdfe
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 19 deletions.
29 changes: 11 additions & 18 deletions PyGLM/type_methods/glmArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -5134,15 +5134,13 @@ static PyObject* glmArray_mul_T_MMUL(glmArray* arr1, glmArray* arr2) {
outArray->readonly = false;
outArray->reference = NULL;

Py_ssize_t n, arr1Stride, arr2Stride, trueShape1;
Py_ssize_t n, arr1Stride, arr2Stride;

if (arr1->glmType == PyGLM_TYPE_VEC) {
n = arr1->shape[0];
arr1Stride = 1;
arr2Stride = arr2->shape[1];

trueShape1 = 1;

outArray->glmType = PyGLM_TYPE_VEC;
outArray->shape[0] = arr2->shape[0];
outArray->shape[1] = 0;
Expand All @@ -5155,8 +5153,6 @@ static PyObject* glmArray_mul_T_MMUL(glmArray* arr1, glmArray* arr2) {
arr1Stride = arr1->shape[1];
arr2Stride = 0;

trueShape1 = arr1->shape[1];

outArray->glmType = PyGLM_TYPE_VEC;
outArray->shape[0] = arr1->shape[1];
outArray->shape[1] = 0;
Expand All @@ -5169,8 +5165,6 @@ static PyObject* glmArray_mul_T_MMUL(glmArray* arr1, glmArray* arr2) {
arr1Stride = arr1->shape[1];
arr2Stride = arr2->shape[1];

trueShape1 = arr1->shape[1];

outArray->glmType = PyGLM_TYPE_MAT;
outArray->shape[0] = arr2->shape[0];
outArray->shape[1] = arr1->shape[1];
Expand Down Expand Up @@ -5198,13 +5192,16 @@ static PyObject* glmArray_mul_T_MMUL(glmArray* arr1, glmArray* arr2) {
for (Py_ssize_t j = 0; j < outArrayRatio; j++) {
T result = (T)0;
for (Py_ssize_t k = 0; k < n; k++) {
T a = arr1DataPtr[k * arr1Stride + j % trueShape1];
T b = arr2DataPtr[k + (j / trueShape1) * arr2Stride];
T a = arr1DataPtr[k * arr1Stride + j % arr1Stride];
T b = arr2DataPtr[k + (j / arr1Stride) * arr2Stride];

result += a * b;
}
outArrayDataPtr[outArrayIndex++] = result;
}
// move pointers by one item
arr1DataPtr = reinterpret_cast<T*>(reinterpret_cast<char*>(arr1DataPtr) + arr1->itemSize);
arr2DataPtr = reinterpret_cast<T*>(reinterpret_cast<char*>(arr2DataPtr) + arr2->itemSize);
}

return (PyObject*)outArray;
Expand Down Expand Up @@ -5283,15 +5280,13 @@ static PyObject* glmArray_mulO_T(glmArray* arr, T* o, Py_ssize_t o_size, PyGLMTy
return (PyObject*)outArray;
}

Py_ssize_t n, arrStride, oStride, trueShape1;
Py_ssize_t n, arrStride, oStride;

if (arr->glmType == PyGLM_TYPE_VEC) {
n = arr->shape[0];
arrStride = 1;
oStride = pto->R;

trueShape1 = 1;

outArray->glmType = PyGLM_TYPE_VEC;
outArray->shape[0] = pto->C;
outArray->shape[1] = 0;
Expand All @@ -5304,8 +5299,6 @@ static PyObject* glmArray_mulO_T(glmArray* arr, T* o, Py_ssize_t o_size, PyGLMTy
arrStride = arr->shape[1];
oStride = 0;

trueShape1 = arr->shape[1];

outArray->glmType = PyGLM_TYPE_VEC;
outArray->shape[0] = arr->shape[1];
outArray->shape[1] = 0;
Expand All @@ -5318,8 +5311,6 @@ static PyObject* glmArray_mulO_T(glmArray* arr, T* o, Py_ssize_t o_size, PyGLMTy
arrStride = arr->shape[1];
oStride = pto->R;

trueShape1 = arr->shape[1];

outArray->glmType = PyGLM_TYPE_MAT;
outArray->shape[0] = pto->C;
outArray->shape[1] = arr->shape[1];
Expand All @@ -5346,13 +5337,14 @@ static PyObject* glmArray_mulO_T(glmArray* arr, T* o, Py_ssize_t o_size, PyGLMTy
for (Py_ssize_t j = 0; j < outArrayRatio; j++) {
T result = (T)0;
for (Py_ssize_t k = 0; k < n; k++) {
T a = arrDataPtr[k * arrStride + j % trueShape1];
T b = o[k + (j / trueShape1) * oStride];
T a = arrDataPtr[k * arrStride + j % arrStride];
T b = o[k + (j / arrStride) * oStride];

result = result + a * b;
}
outArrayDataPtr[outArrayIndex++] = result;
}
arrDataPtr = reinterpret_cast<T*>(reinterpret_cast<char*>(arrDataPtr) + arr->itemSize);
}

return (PyObject*)outArray;
Expand Down Expand Up @@ -5441,6 +5433,7 @@ static PyObject* glmArray_rmulO_T(glmArray* arr, T* o, Py_ssize_t o_size, PyGLMT
}
outArrayDataPtr[outArrayIndex++] = result;
}
arrDataPtr = reinterpret_cast<T*>(reinterpret_cast<char*>(arrDataPtr) + arr->itemSize);
}

return (PyObject*)outArray;
Expand Down
31 changes: 30 additions & 1 deletion test/PyGLM_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3643,7 +3643,36 @@ def test_mat2x2():
##/core_type_mat2x2 ##
###/GLM TESTS ###


def test_array_matmul():
hitbox = glm.array(
glm.vec2(0., 1.),
glm.vec2(1., 1.),
glm.vec2(1., 0.),
glm.vec2(0., 0.),
)
rotation = glm.radians(90)
scale_x = 1.
scale_y = 2.

cos_rotation = glm.cos(rotation)
sin_rotation = glm.sin(rotation)

rotation_scale_matrix = glm.mat2x2(
scale_x * cos_rotation, -scale_y * sin_rotation,
scale_x * sin_rotation, scale_y * cos_rotation
)
hitbox_rotated = hitbox * rotation_scale_matrix

# I expect to see the points rotated 90 degrees, approximately:
# array(vec2(-2, 0), vec2(-2, 1), vec2(0, 1), vec2(0, 0))
assert glm.equal(hitbox_rotated[0].x, -2, 0.00001)
assert glm.equal(hitbox_rotated[0].y, 0, 0.00001)
assert glm.equal(hitbox_rotated[1].x, -2, 0.00001)
assert glm.equal(hitbox_rotated[1].y, 1, 0.00001)
assert glm.equal(hitbox_rotated[2].x, 0, 0.00001)
assert glm.equal(hitbox_rotated[2].y, 1, 0.00001)
assert glm.equal(hitbox_rotated[3].x, 0, 0.00001)
assert glm.equal(hitbox_rotated[3].y, 0, 0.00001)

### TEST TEST ###

Expand Down

0 comments on commit 9f2cdfe

Please sign in to comment.