diff --git a/PyGLM/functions/detail/func_common.h b/PyGLM/functions/detail/func_common.h index 2069bb5e..d76448ef 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,11 +264,94 @@ case get_format_specifier(): \ return apply_min_from_PyObject_vector_vector(items); \ } +#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:\ + 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, 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; +} +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; 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, 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); @@ -954,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); diff --git a/test_min_glm.py b/test_min_glm.py new file mode 100644 index 00000000..bb781623 --- /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 00000000..f0380cab --- /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