From b3dc39c34b8749f04bbcb2f9f3ae7899a9dc797a Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Sun, 26 Feb 2023 14:52:25 -0500 Subject: [PATCH 1/4] broken attempt at this; need guidance --- PyGLM/functions/detail/func_common.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/PyGLM/functions/detail/func_common.h b/PyGLM/functions/detail/func_common.h index 2069bb5..e2686b7 100644 --- a/PyGLM/functions/detail/func_common.h +++ b/PyGLM/functions/detail/func_common.h @@ -267,6 +267,29 @@ min_(PyObject*, PyObject* args) { PyObject *arg1, *arg2 = NULL, *arg3 = NULL, *arg4 = NULL; if (!PyArg_UnpackTuple(args, "min", 1, 4, &arg1, &arg2, &arg3, &arg4)) return NULL; if (arg2 == NULL) { + if (PyObject_TypeCheck(arg1, &glmArrayType)) { + // arg1 is a pyglm array + glmArray* arr1 = (glmArray*)arg1; + + // Below this line is wrong. Gotta generate a switch-case to call + // the correct template to apply_min over the contents of a glmArray + PyGLMTypeObject* pti = (PyGLMTypeObject*)type; + + switch (pti->C) { + case 1: + min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(1); + break; + case 2: + min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(2); + break; + case 3: + min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(3); + break; + case 4: + min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(4); + break; + } + } if (PyObject_IterCheck(arg1)) { PyObject* iterator = PyObject_GetIter(arg1); From 36b615ab1e427e3d6a4a428574843b68a7269771 Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Tue, 28 Feb 2023 15:30:52 -0500 Subject: [PATCH 2/4] WIP --- PyGLM/functions/detail/func_common.h | 83 +++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 14 deletions(-) diff --git a/PyGLM/functions/detail/func_common.h b/PyGLM/functions/detail/func_common.h index e2686b7..4773292 100644 --- a/PyGLM/functions/detail/func_common.h +++ b/PyGLM/functions/detail/func_common.h @@ -262,6 +262,32 @@ case get_format_specifier(): \ return apply_min_from_PyObject_vector_vector(items); \ } +// #define GLM_ARRAY_MINMAX_IF_IS_VEC(F, T) switch (arr1->shape[0]) {\ +// case 1:\ +// return F>(arr1->data); +// case 2:\ +// return F>(arr1->data); +// case 3:\ +// return F>(arr1->data); +// case 4:\ +// return F>(arr1->data); +// default:\ +// PyGLM_ASSERT(0, "Invalid shape occured. This should not have happened.");\ +// } + +// template +// static T +// min_internal(T* items) { +// T minimum = items[0]; +// for (T item : items) { +// if (item == minimum) { +// continue; +// } +// minimum = glm::min(item, minimum); +// } +// return minimum; +// } + static PyObject* min_(PyObject*, PyObject* args) { PyObject *arg1, *arg2 = NULL, *arg3 = NULL, *arg4 = NULL; @@ -275,20 +301,49 @@ min_(PyObject*, PyObject* args) { // the correct template to apply_min over the contents of a glmArray PyGLMTypeObject* pti = (PyGLMTypeObject*)type; - switch (pti->C) { - case 1: - min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(1); - break; - case 2: - min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(2); - break; - case 3: - min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(3); - break; - case 4: - min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(4); - break; - } + // switch (pti->C) { + // case 1: + // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(1); + // break; + // case 2: + // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(2); + // break; + // case 3: + // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(3); + // break; + // case 4: + // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(4); + // break; + // } + + // if (arr1->glmType == PyGLM_TYPE_VEC) { + // switch (arr1->format) { + // case 'f': + // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, float); + // case 'd': + // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, double); + // case 'i': + // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, int32); + // case 'I': + // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, uint32); + // case 'b': + // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, int8); + // case 'B': + // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, uint8); + // case 'h': + // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, int16); + // case 'H': + // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, uint16); + // case 'q': + // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, int64); + // case 'Q': + // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, uint64); + // case '?': + // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, bool); + // default: + // PyGLM_ASSERT(0, "Invalid format specifier. This should not have happened."); + // } + // } } if (PyObject_IterCheck(arg1)) { PyObject* iterator = PyObject_GetIter(arg1); From a91baad72aca50c3476054f45ac8e2c058b84652 Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Wed, 1 Mar 2023 11:50:04 -0500 Subject: [PATCH 3/4] proof-of-concept, very messy, only works for arrays of floats --- PyGLM/functions/detail/func_common.h | 170 ++++++++++++++++----------- test_min_glm.py | 14 +++ test_min_py.py | 14 +++ 3 files changed, 129 insertions(+), 69 deletions(-) create mode 100644 test_min_glm.py create mode 100644 test_min_py.py diff --git a/PyGLM/functions/detail/func_common.h b/PyGLM/functions/detail/func_common.h index 4773292..c93a0a4 100644 --- a/PyGLM/functions/detail/func_common.h +++ b/PyGLM/functions/detail/func_common.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "../../compiler_setup.h" #include "../../types/all.h" @@ -262,88 +264,118 @@ case get_format_specifier(): \ return apply_min_from_PyObject_vector_vector(items); \ } -// #define GLM_ARRAY_MINMAX_IF_IS_VEC(F, T) switch (arr1->shape[0]) {\ -// case 1:\ -// return F>(arr1->data); -// case 2:\ -// return F>(arr1->data); -// case 3:\ -// return F>(arr1->data); -// case 4:\ -// return F>(arr1->data); -// default:\ -// PyGLM_ASSERT(0, "Invalid shape occured. This should not have happened.");\ -// } +#define GLM_ARRAY_RETURN_CALL_IF_IS_VEC(A, F, T) switch (A->shape[0]) {\ +case 1:\ + return pack<1, T>(F>(reinterpret_cast*>(A->data), A->itemCount));\ +case 2:\ + // printf("min for vec2\n");\ + return pack<2, T>(F>(reinterpret_cast*>(A->data), A->itemCount));\ +case 3:\ + return pack<3, T>(F>(reinterpret_cast*>(A->data), A->itemCount));\ +case 4:\ + return pack<4, T>(F>(reinterpret_cast*>(A->data), A->itemCount));\ +default:\ + PyGLM_ASSERT(0, "Invalid shape occured. This should not have happened.");\ +} -// template -// static T -// min_internal(T* items) { -// T minimum = items[0]; -// for (T item : items) { -// if (item == minimum) { -// continue; -// } -// minimum = glm::min(item, minimum); -// } -// return minimum; -// } +template +static T +min_internal(T* items, Py_ssize_t count) { + T minimum = items[0]; + for (Py_ssize_t i = 0; i < count; i++) { + T item = items[i]; + // if (item == minimum) { + // continue; + // } + minimum = glm::min(item, minimum); + } + return minimum; +} static PyObject* min_(PyObject*, PyObject* args) { PyObject *arg1, *arg2 = NULL, *arg3 = NULL, *arg4 = NULL; if (!PyArg_UnpackTuple(args, "min", 1, 4, &arg1, &arg2, &arg3, &arg4)) return NULL; + // printf("min_\n"); if (arg2 == NULL) { + // printf("min_ A\n"); if (PyObject_TypeCheck(arg1, &glmArrayType)) { + // printf("min_ B\n"); // arg1 is a pyglm array glmArray* arr1 = (glmArray*)arg1; + if (arr1->itemCount > 1) { - // Below this line is wrong. Gotta generate a switch-case to call - // the correct template to apply_min over the contents of a glmArray - PyGLMTypeObject* pti = (PyGLMTypeObject*)type; + // // Below this line is wrong. Gotta generate a switch-case to call + // // the correct template to apply_min over the contents of a glmArray + // PyGLMTypeObject* pti = (PyGLMTypeObject*)type; - // switch (pti->C) { - // case 1: - // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(1); - // break; - // case 2: - // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(2); - // break; - // case 3: - // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(3); - // break; - // case 4: - // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(4); - // break; - // } + // // switch (pti->C) { + // // case 1: + // // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(1); + // // break; + // // case 2: + // // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(2); + // // break; + // // case 3: + // // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(3); + // // break; + // // case 4: + // // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(4); + // // break; + // // } - // if (arr1->glmType == PyGLM_TYPE_VEC) { - // switch (arr1->format) { - // case 'f': - // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, float); - // case 'd': - // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, double); - // case 'i': - // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, int32); - // case 'I': - // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, uint32); - // case 'b': - // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, int8); - // case 'B': - // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, uint8); - // case 'h': - // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, int16); - // case 'H': - // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, uint16); - // case 'q': - // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, int64); - // case 'Q': - // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, uint64); - // case '?': - // GLM_ARRAY_MIN_IF_IS_VEC(min_internal, bool); - // default: - // PyGLM_ASSERT(0, "Invalid format specifier. This should not have happened."); - // } - // } + // printf("min_ %d %d\n", arr1->glmType, PyGLM_TYPE_VEC); + if (arr1->glmType == PyGLM_TYPE_VEC) { + switch (arr1->format) { + case 'f': + switch (arr1->shape[0]) { + case 1: + return pack<1, float>(min_internal>(reinterpret_cast*>(arr1->data), arr1->itemCount)); + case 2: + // printf("min for vec2\n"); + return pack<2, float>(min_internal>(reinterpret_cast*>(arr1->data), arr1->itemCount)); + case 3: + return pack<3, float>(min_internal>(reinterpret_cast*>(arr1->data), arr1->itemCount)); + case 4: + return pack<4, float>(min_internal>(reinterpret_cast*>(arr1->data), arr1->itemCount)); + default: + PyGLM_ASSERT(0, "Invalid shape occured. This should not have happened."); + } + // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, float); + // case 'd': + // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, double); + // case 'i': + // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, int32); + // case 'I': + // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, uint32); + // case 'b': + // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, int8); + // case 'B': + // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, uint8); + // case 'h': + // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, int16); + // case 'H': + // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, uint16); + // case 'q': + // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, int64); + // case 'Q': + // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, uint64); + // case '?': + // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, bool); + default: + PyGLM_ASSERT(0, "Invalid format specifier. This should not have happened."); + } + } + if (arr1->glmType == PyGLM_TYPE_CTYPES) { + switch (arr1->format) { + case 'f': + // printf("min for floats\n"); + return pack(min_internal(reinterpret_cast(arr1->data), arr1->itemCount)); + default: + PyGLM_ASSERT(0, "Invalid format specifier. This should not have happened."); + } + } + } } if (PyObject_IterCheck(arg1)) { PyObject* iterator = PyObject_GetIter(arg1); diff --git a/test_min_glm.py b/test_min_glm.py new file mode 100644 index 0000000..bb78162 --- /dev/null +++ b/test_min_glm.py @@ -0,0 +1,14 @@ +import glm +from glm import min as glm_min + +a = glm.array([glm.vec2(x, x + 1) for x in range(0, 10000, 2)]) +a_x, a_y = a.split_components() + +for i in range(99999): + # PyGLM + glm_min(a_x) + glm_min(a_y) + + # Python + # min(a_x) + # min(a_y) \ No newline at end of file diff --git a/test_min_py.py b/test_min_py.py new file mode 100644 index 0000000..f0380ca --- /dev/null +++ b/test_min_py.py @@ -0,0 +1,14 @@ +import glm +from glm import min as glm_min + +a = glm.array([glm.vec2(x, x + 1) for x in range(0, 10000, 2)]) +a_x, a_y = a.split_components() + +for i in range(99999): + # PyGLM + # glm_min(a_x) + # glm_min(a_y) + + # Python + min(a_x) + min(a_y) \ No newline at end of file From 5695087d3e58eb34ae8cf00562e5a7726780dbeb Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Wed, 1 Mar 2023 17:40:46 -0500 Subject: [PATCH 4/4] WIP --- PyGLM/functions/detail/func_common.h | 136 +++++++++++++++------------ 1 file changed, 77 insertions(+), 59 deletions(-) diff --git a/PyGLM/functions/detail/func_common.h b/PyGLM/functions/detail/func_common.h index c93a0a4..d76448e 100644 --- a/PyGLM/functions/detail/func_common.h +++ b/PyGLM/functions/detail/func_common.h @@ -268,7 +268,6 @@ case get_format_specifier(): \ case 1:\ return pack<1, T>(F>(reinterpret_cast*>(A->data), A->itemCount));\ case 2:\ - // printf("min for vec2\n");\ return pack<2, T>(F>(reinterpret_cast*>(A->data), A->itemCount));\ case 3:\ return pack<3, T>(F>(reinterpret_cast*>(A->data), A->itemCount));\ @@ -291,77 +290,53 @@ min_internal(T* items, Py_ssize_t count) { } return minimum; } +template +static T +max_internal(T* items, Py_ssize_t count) { + T maximum = items[0]; + for (Py_ssize_t i = 0; i < count; i++) { + T item = items[i]; + // if (item == minimum) { + // continue; + // } + maximum = glm::max(item, maximum); + } + return maximum; +} static PyObject* min_(PyObject*, PyObject* args) { PyObject *arg1, *arg2 = NULL, *arg3 = NULL, *arg4 = NULL; if (!PyArg_UnpackTuple(args, "min", 1, 4, &arg1, &arg2, &arg3, &arg4)) return NULL; - // printf("min_\n"); if (arg2 == NULL) { - // printf("min_ A\n"); if (PyObject_TypeCheck(arg1, &glmArrayType)) { - // printf("min_ B\n"); // arg1 is a pyglm array glmArray* arr1 = (glmArray*)arg1; if (arr1->itemCount > 1) { - - // // Below this line is wrong. Gotta generate a switch-case to call - // // the correct template to apply_min over the contents of a glmArray - // PyGLMTypeObject* pti = (PyGLMTypeObject*)type; - - // // switch (pti->C) { - // // case 1: - // // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(1); - // // break; - // // case 2: - // // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(2); - // // break; - // // case 3: - // // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(3); - // // break; - // // case 4: - // // min_GEN_TYPE_SWITCH_STATEMENT_FOR_VECTOR(4); - // // break; - // // } - - // printf("min_ %d %d\n", arr1->glmType, PyGLM_TYPE_VEC); if (arr1->glmType == PyGLM_TYPE_VEC) { switch (arr1->format) { case 'f': - switch (arr1->shape[0]) { - case 1: - return pack<1, float>(min_internal>(reinterpret_cast*>(arr1->data), arr1->itemCount)); - case 2: - // printf("min for vec2\n"); - return pack<2, float>(min_internal>(reinterpret_cast*>(arr1->data), arr1->itemCount)); - case 3: - return pack<3, float>(min_internal>(reinterpret_cast*>(arr1->data), arr1->itemCount)); - case 4: - return pack<4, float>(min_internal>(reinterpret_cast*>(arr1->data), arr1->itemCount)); - default: - PyGLM_ASSERT(0, "Invalid shape occured. This should not have happened."); - } - // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, float); - // case 'd': - // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, double); - // case 'i': - // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, int32); - // case 'I': - // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, uint32); - // case 'b': - // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, int8); - // case 'B': - // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, uint8); - // case 'h': - // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, int16); - // case 'H': - // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, uint16); - // case 'q': - // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, int64); - // case 'Q': - // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, uint64); - // case '?': - // GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, bool); + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, float); + case 'd': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, double); + case 'i': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, int32); + case 'I': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, uint32); + case 'b': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, int8); + case 'B': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, uint8); + case 'h': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, int16); + case 'H': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, uint16); + case 'q': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, int64); + case 'Q': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, uint64); + case '?': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, min_internal, bool); default: PyGLM_ASSERT(0, "Invalid format specifier. This should not have happened."); } @@ -1064,6 +1039,49 @@ max_(PyObject*, PyObject* args) { PyObject *arg1, *arg2 = NULL, *arg3 = NULL, *arg4 = NULL; if (!PyArg_UnpackTuple(args, "max", 1, 4, &arg1, &arg2, &arg3, &arg4)) return NULL; if (arg2 == NULL) { + if (PyObject_TypeCheck(arg1, &glmArrayType)) { + // arg1 is a pyglm array + glmArray* arr1 = (glmArray*)arg1; + if (arr1->itemCount > 1) { + if (arr1->glmType == PyGLM_TYPE_VEC) { + switch (arr1->format) { + case 'f': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, max_internal, float); + case 'd': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, max_internal, double); + case 'i': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, max_internal, int32); + case 'I': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, max_internal, uint32); + case 'b': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, max_internal, int8); + case 'B': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, max_internal, uint8); + case 'h': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, max_internal, int16); + case 'H': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, max_internal, uint16); + case 'q': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, max_internal, int64); + case 'Q': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, max_internal, uint64); + case '?': + GLM_ARRAY_RETURN_CALL_IF_IS_VEC(arr1, max_internal, bool); + default: + PyGLM_ASSERT(0, "Invalid format specifier. This should not have happened."); + } + } + if (arr1->glmType == PyGLM_TYPE_CTYPES) { + switch (arr1->format) { + case 'f': + // printf("min for floats\n"); + return pack(max_internal(reinterpret_cast(arr1->data), arr1->itemCount)); + default: + PyGLM_ASSERT(0, "Invalid format specifier. This should not have happened."); + } + } + } + } if (PyObject_IterCheck(arg1)) { PyObject* iterator = PyObject_GetIter(arg1);