From 229ec355a71094fadb692792239690bed7217bd7 Mon Sep 17 00:00:00 2001 From: itzpr3d4t0r Date: Mon, 1 Apr 2024 19:47:46 +0200 Subject: [PATCH 1/5] optimized rect multi-collision methods --- src_c/rect_impl.h | 123 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 109 insertions(+), 14 deletions(-) diff --git a/src_c/rect_impl.h b/src_c/rect_impl.h index e10947cac6..297765bfcf 100644 --- a/src_c/rect_impl.h +++ b/src_c/rect_impl.h @@ -1292,17 +1292,32 @@ RectExport_colliderect(RectObject *self, PyObject *const *args, return PyBool_FromLong(_pg_do_rects_intersect(&self->r, argrect)); } +#ifndef OPTIMIZED_COLLIDERECT(r) +#define OPTIMIZED_COLLIDERECT(r) \ + (a < MAX(r->x, r->x + r->w) && b < MAX(r->y, r->y + r->h) && \ + c > MIN(r->x, r->x + r->w) && d > MIN(r->y, r->y + r->h)) +#endif + static PyObject * RectExport_collidelist(RectObject *self, PyObject *arg) { InnerRect *argrect, *srect = &self->r, temp; int loop; + if (srect->w == 0 || srect->h == 0) { + return PyLong_FromLong(-1); + } + if (!PySequence_Check(arg)) { return RAISE(PyExc_TypeError, "Argument must be a sequence of rectstyle objects."); } + const PrimitiveType a = MIN(srect->x, srect->x + srect->w); + const PrimitiveType b = MIN(srect->y, srect->y + srect->h); + const PrimitiveType c = MAX(srect->x, srect->x + srect->w); + const PrimitiveType d = MAX(srect->y, srect->y + srect->h); + /* If the sequence is a fast sequence, we can use the faster * PySequence_Fast_ITEMS() function to get the items. */ if (pgSequenceFast_Check(arg)) { @@ -1313,7 +1328,12 @@ RectExport_collidelist(RectObject *self, PyObject *arg) PyExc_TypeError, "Argument must be a sequence of rectstyle objects."); } - if (_pg_do_rects_intersect(srect, argrect)) { + + if (argrect->w == 0 || argrect->h == 0) { + continue; + } + + if (OPTIMIZED_COLLIDERECT(argrect)) { return PyLong_FromLong(loop); } } @@ -1322,7 +1342,7 @@ RectExport_collidelist(RectObject *self, PyObject *arg) * PySequence_GetItem() function to get the items. */ else { for (loop = 0; loop < PySequence_Length(arg); loop++) { - PyObject *obj = PySequence_GetItem(arg, loop); + PyObject *obj = PySequence_ITEM(arg, loop); if (!obj || !(argrect = RectFromObject(obj, &temp))) { Py_XDECREF(obj); @@ -1333,7 +1353,11 @@ RectExport_collidelist(RectObject *self, PyObject *arg) Py_DECREF(obj); - if (_pg_do_rects_intersect(srect, argrect)) { + if (argrect->w == 0 || argrect->h == 0) { + continue; + } + + if (OPTIMIZED_COLLIDERECT(argrect)) { return PyLong_FromLong(loop); } } @@ -1358,6 +1382,15 @@ RectExport_collidelistall(RectObject *self, PyObject *arg) return NULL; } + if (srect->w == 0 || srect->h == 0) { + return ret; + } + + const PrimitiveType a = MIN(srect->x, srect->x + srect->w); + const PrimitiveType b = MIN(srect->y, srect->y + srect->h); + const PrimitiveType c = MAX(srect->x, srect->x + srect->w); + const PrimitiveType d = MAX(srect->y, srect->y + srect->h); + /* If the sequence is a fast sequence, we can use the faster * PySequence_Fast_ITEMS() function to get the items. */ if (pgSequenceFast_Check(arg)) { @@ -1370,7 +1403,11 @@ RectExport_collidelistall(RectObject *self, PyObject *arg) "Argument must be a sequence of rectstyle objects."); } - if (_pg_do_rects_intersect(srect, argrect)) { + if (argrect->w == 0 || argrect->h == 0) { + continue; + } + + if (OPTIMIZED_COLLIDERECT(argrect)) { PyObject *num = PyLong_FromLong(loop); if (!num) { Py_DECREF(ret); @@ -1400,7 +1437,11 @@ RectExport_collidelistall(RectObject *self, PyObject *arg) Py_DECREF(obj); - if (_pg_do_rects_intersect(srect, argrect)) { + if (argrect->w == 0 || argrect->h == 0) { + continue; + } + + if (OPTIMIZED_COLLIDERECT(argrect)) { PyObject *num = PyLong_FromLong(loop); if (!num) { Py_DECREF(ret); @@ -1452,7 +1493,7 @@ static PyObject * RectExport_collideobjectsall(RectObject *self, PyObject *args, PyObject *kwargs) { - InnerRect *argrect; + InnerRect *argrect, *srect = &self->r; InnerRect temp; Py_ssize_t size; int loop; @@ -1485,6 +1526,15 @@ RectExport_collideobjectsall(RectObject *self, PyObject *args, return NULL; } + if (srect->w == 0 || srect->h == 0) { + return ret; + } + + const PrimitiveType a = MIN(srect->x, srect->x + srect->w); + const PrimitiveType b = MIN(srect->y, srect->y + srect->h); + const PrimitiveType c = MAX(srect->x, srect->x + srect->w); + const PrimitiveType d = MAX(srect->y, srect->y + srect->h); + size = PySequence_Length(list); if (size == -1) { Py_DECREF(ret); @@ -1506,7 +1556,12 @@ RectExport_collideobjectsall(RectObject *self, PyObject *args, return NULL; } - if (_pg_do_rects_intersect(&self->r, argrect)) { + if (argrect->w == 0 || argrect->h == 0) { + Py_DECREF(obj); + continue; + } + + if (OPTIMIZED_COLLIDERECT(argrect)) { if (0 != PyList_Append(ret, obj)) { Py_DECREF(ret); Py_DECREF(obj); @@ -1522,7 +1577,7 @@ RectExport_collideobjectsall(RectObject *self, PyObject *args, static PyObject * RectExport_collideobjects(RectObject *self, PyObject *args, PyObject *kwargs) { - InnerRect *argrect; + InnerRect *argrect, *srect = &self->r; InnerRect temp; Py_ssize_t size; int loop; @@ -1549,13 +1604,22 @@ RectExport_collideobjects(RectObject *self, PyObject *args, PyObject *kwargs) "Key function must be callable with one argument."); } + if (srect->w == 0 || srect->h == 0) { + Py_RETURN_NONE; + } + + const PrimitiveType a = MIN(srect->x, srect->x + srect->w); + const PrimitiveType b = MIN(srect->y, srect->y + srect->h); + const PrimitiveType c = MAX(srect->x, srect->x + srect->w); + const PrimitiveType d = MAX(srect->y, srect->y + srect->h); + size = PySequence_Length(list); if (size == -1) { return NULL; } for (loop = 0; loop < size; ++loop) { - obj = PySequence_GetItem(list, loop); + obj = PySequence_ITEM(list, loop); if (!obj) { return NULL; @@ -1567,7 +1631,12 @@ RectExport_collideobjects(RectObject *self, PyObject *args, PyObject *kwargs) return NULL; } - if (_pg_do_rects_intersect(&self->r, argrect)) { + if (argrect->w == 0 || argrect->h == 0) { + Py_DECREF(obj); + continue; + } + + if (OPTIMIZED_COLLIDERECT(argrect)) { return obj; } Py_DECREF(obj); @@ -1579,7 +1648,7 @@ RectExport_collideobjects(RectObject *self, PyObject *args, PyObject *kwargs) static PyObject * RectExport_collidedict(RectObject *self, PyObject *args, PyObject *kwargs) { - InnerRect *argrect, temp; + InnerRect *argrect, temp, *srect = &self->r; Py_ssize_t loop = 0; Py_ssize_t values = 0; /* Defaults to expecting keys as rects. */ PyObject *dict, *key, *val; @@ -1596,6 +1665,15 @@ RectExport_collidedict(RectObject *self, PyObject *args, PyObject *kwargs) return RAISE(PyExc_TypeError, "first argument must be a dict"); } + if (srect->w == 0 || srect->h == 0) { + Py_RETURN_NONE; + } + + const PrimitiveType a = MIN(srect->x, srect->x + srect->w); + const PrimitiveType b = MIN(srect->y, srect->y + srect->h); + const PrimitiveType c = MAX(srect->x, srect->x + srect->w); + const PrimitiveType d = MAX(srect->y, srect->y + srect->h); + while (PyDict_Next(dict, &loop, &key, &val)) { if (values) { if (!(argrect = RectFromObject(val, &temp))) { @@ -1609,7 +1687,11 @@ RectExport_collidedict(RectObject *self, PyObject *args, PyObject *kwargs) } } - if (_pg_do_rects_intersect(&self->r, argrect)) { + if (argrect->w == 0 || argrect->h == 0) { + continue; + } + + if (OPTIMIZED_COLLIDERECT(argrect)) { ret = Py_BuildValue("(OO)", key, val); break; } @@ -1624,7 +1706,7 @@ RectExport_collidedict(RectObject *self, PyObject *args, PyObject *kwargs) static PyObject * RectExport_collidedictall(RectObject *self, PyObject *args, PyObject *kwargs) { - InnerRect *argrect, temp; + InnerRect *argrect, temp, *srect = &self->r; Py_ssize_t loop = 0; Py_ssize_t values = 0; /* Defaults to expecting keys as rects. */ PyObject *dict, *key, *val; @@ -1645,6 +1727,15 @@ RectExport_collidedictall(RectObject *self, PyObject *args, PyObject *kwargs) if (!ret) return NULL; + if (srect->w == 0 || srect->h == 0) { + return ret; + } + + const PrimitiveType a = MIN(srect->x, srect->x + srect->w); + const PrimitiveType b = MIN(srect->y, srect->y + srect->h); + const PrimitiveType c = MAX(srect->x, srect->x + srect->w); + const PrimitiveType d = MAX(srect->y, srect->y + srect->h); + while (PyDict_Next(dict, &loop, &key, &val)) { if (values) { if (!(argrect = RectFromObject(val, &temp))) { @@ -1660,7 +1751,11 @@ RectExport_collidedictall(RectObject *self, PyObject *args, PyObject *kwargs) } } - if (_pg_do_rects_intersect(&self->r, argrect)) { + if (argrect->w == 0 || argrect->h == 0) { + continue; + } + + if (OPTIMIZED_COLLIDERECT(argrect)) { PyObject *num = Py_BuildValue("(OO)", key, val); if (!num) { Py_DECREF(ret); From cb0234eb5b1090999adef44e1abb954d30bb194d Mon Sep 17 00:00:00 2001 From: itzpr3d4t0r Date: Mon, 1 Apr 2024 20:39:46 +0200 Subject: [PATCH 2/5] fix --- src_c/rect_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_c/rect_impl.h b/src_c/rect_impl.h index 297765bfcf..de4926e580 100644 --- a/src_c/rect_impl.h +++ b/src_c/rect_impl.h @@ -1292,7 +1292,7 @@ RectExport_colliderect(RectObject *self, PyObject *const *args, return PyBool_FromLong(_pg_do_rects_intersect(&self->r, argrect)); } -#ifndef OPTIMIZED_COLLIDERECT(r) +#ifndef OPTIMIZED_COLLIDERECT #define OPTIMIZED_COLLIDERECT(r) \ (a < MAX(r->x, r->x + r->w) && b < MAX(r->y, r->y + r->h) && \ c > MIN(r->x, r->x + r->w) && d > MIN(r->y, r->y + r->h)) From 75c7dcc8df2c26a352fca8c6b143ee84514249f4 Mon Sep 17 00:00:00 2001 From: itzpr3d4t0r Date: Thu, 4 Apr 2024 12:33:18 +0200 Subject: [PATCH 3/5] Addressed reviews, added more comments, swapped Py_BuildValue for PyTuple_Pack. --- src_c/rect_impl.h | 103 ++++++++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/src_c/rect_impl.h b/src_c/rect_impl.h index de4926e580..fcb7b20446 100644 --- a/src_c/rect_impl.h +++ b/src_c/rect_impl.h @@ -1293,9 +1293,9 @@ RectExport_colliderect(RectObject *self, PyObject *const *args, } #ifndef OPTIMIZED_COLLIDERECT -#define OPTIMIZED_COLLIDERECT(r) \ - (a < MAX(r->x, r->x + r->w) && b < MAX(r->y, r->y + r->h) && \ - c > MIN(r->x, r->x + r->w) && d > MIN(r->y, r->y + r->h)) +#define OPTIMIZED_COLLIDERECT(r) \ + (left < MAX(r->x, r->x + r->w) && top < MAX(r->y, r->y + r->h) && \ + right > MIN(r->x, r->x + r->w) && bottom > MIN(r->y, r->y + r->h)) #endif static PyObject * @@ -1304,6 +1304,8 @@ RectExport_collidelist(RectObject *self, PyObject *arg) InnerRect *argrect, *srect = &self->r, temp; int loop; + /* If the calling rect has 0 width or height, it cannot collide with + * anything, hence return -1 directly. */ if (srect->w == 0 || srect->h == 0) { return PyLong_FromLong(-1); } @@ -1313,10 +1315,10 @@ RectExport_collidelist(RectObject *self, PyObject *arg) "Argument must be a sequence of rectstyle objects."); } - const PrimitiveType a = MIN(srect->x, srect->x + srect->w); - const PrimitiveType b = MIN(srect->y, srect->y + srect->h); - const PrimitiveType c = MAX(srect->x, srect->x + srect->w); - const PrimitiveType d = MAX(srect->y, srect->y + srect->h); + const PrimitiveType left = MIN(srect->x, srect->x + srect->w); + const PrimitiveType top = MIN(srect->y, srect->y + srect->h); + const PrimitiveType right = MAX(srect->x, srect->x + srect->w); + const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); /* If the sequence is a fast sequence, we can use the faster * PySequence_Fast_ITEMS() function to get the items. */ @@ -1329,9 +1331,10 @@ RectExport_collidelist(RectObject *self, PyObject *arg) "Argument must be a sequence of rectstyle objects."); } - if (argrect->w == 0 || argrect->h == 0) { + /* If 0 width or height, skip, preserves previous behaviour with + * _pg_do_rects_intersect */ + if (argrect->w == 0 || argrect->h == 0) continue; - } if (OPTIMIZED_COLLIDERECT(argrect)) { return PyLong_FromLong(loop); @@ -1353,9 +1356,10 @@ RectExport_collidelist(RectObject *self, PyObject *arg) Py_DECREF(obj); - if (argrect->w == 0 || argrect->h == 0) { + /* If 0 width or height, skip, preserves previous behaviour with + * _pg_do_rects_intersect */ + if (argrect->w == 0 || argrect->h == 0) continue; - } if (OPTIMIZED_COLLIDERECT(argrect)) { return PyLong_FromLong(loop); @@ -1382,14 +1386,16 @@ RectExport_collidelistall(RectObject *self, PyObject *arg) return NULL; } + /* If the calling rect has 0 width or height, it cannot collide with + * anything, hence return an empty list directly. */ if (srect->w == 0 || srect->h == 0) { return ret; } - const PrimitiveType a = MIN(srect->x, srect->x + srect->w); - const PrimitiveType b = MIN(srect->y, srect->y + srect->h); - const PrimitiveType c = MAX(srect->x, srect->x + srect->w); - const PrimitiveType d = MAX(srect->y, srect->y + srect->h); + const PrimitiveType left = MIN(srect->x, srect->x + srect->w); + const PrimitiveType top = MIN(srect->y, srect->y + srect->h); + const PrimitiveType right = MAX(srect->x, srect->x + srect->w); + const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); /* If the sequence is a fast sequence, we can use the faster * PySequence_Fast_ITEMS() function to get the items. */ @@ -1403,9 +1409,10 @@ RectExport_collidelistall(RectObject *self, PyObject *arg) "Argument must be a sequence of rectstyle objects."); } - if (argrect->w == 0 || argrect->h == 0) { + /* If 0 width or height, skip, preserves previous behaviour with + * _pg_do_rects_intersect */ + if (!argrect->w || !argrect->h) continue; - } if (OPTIMIZED_COLLIDERECT(argrect)) { PyObject *num = PyLong_FromLong(loop); @@ -1437,9 +1444,10 @@ RectExport_collidelistall(RectObject *self, PyObject *arg) Py_DECREF(obj); - if (argrect->w == 0 || argrect->h == 0) { + /* If 0 width or height, skip, preserves previous behaviour with + * _pg_do_rects_intersect */ + if (argrect->w == 0 || argrect->h == 0) continue; - } if (OPTIMIZED_COLLIDERECT(argrect)) { PyObject *num = PyLong_FromLong(loop); @@ -1526,14 +1534,16 @@ RectExport_collideobjectsall(RectObject *self, PyObject *args, return NULL; } + /* If the calling rect has 0 width or height, it cannot collide with + * anything, hence return an empty list directly. */ if (srect->w == 0 || srect->h == 0) { return ret; } - const PrimitiveType a = MIN(srect->x, srect->x + srect->w); - const PrimitiveType b = MIN(srect->y, srect->y + srect->h); - const PrimitiveType c = MAX(srect->x, srect->x + srect->w); - const PrimitiveType d = MAX(srect->y, srect->y + srect->h); + const PrimitiveType left = MIN(srect->x, srect->x + srect->w); + const PrimitiveType top = MIN(srect->y, srect->y + srect->h); + const PrimitiveType right = MAX(srect->x, srect->x + srect->w); + const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); size = PySequence_Length(list); if (size == -1) { @@ -1542,7 +1552,7 @@ RectExport_collideobjectsall(RectObject *self, PyObject *args, } for (loop = 0; loop < size; ++loop) { - obj = PySequence_GetItem(list, loop); + obj = PySequence_ITEM(list, loop); if (!obj) { Py_DECREF(ret); @@ -1556,6 +1566,8 @@ RectExport_collideobjectsall(RectObject *self, PyObject *args, return NULL; } + /* If 0 width or height, skip, preserves previous behaviour with + * _pg_do_rects_intersect */ if (argrect->w == 0 || argrect->h == 0) { Py_DECREF(obj); continue; @@ -1604,14 +1616,16 @@ RectExport_collideobjects(RectObject *self, PyObject *args, PyObject *kwargs) "Key function must be callable with one argument."); } + /* If the calling rect has 0 width or height, it cannot collide with + * anything, hence return None directly. */ if (srect->w == 0 || srect->h == 0) { Py_RETURN_NONE; } - const PrimitiveType a = MIN(srect->x, srect->x + srect->w); - const PrimitiveType b = MIN(srect->y, srect->y + srect->h); - const PrimitiveType c = MAX(srect->x, srect->x + srect->w); - const PrimitiveType d = MAX(srect->y, srect->y + srect->h); + const PrimitiveType left = MIN(srect->x, srect->x + srect->w); + const PrimitiveType top = MIN(srect->y, srect->y + srect->h); + const PrimitiveType right = MAX(srect->x, srect->x + srect->w); + const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); size = PySequence_Length(list); if (size == -1) { @@ -1631,6 +1645,8 @@ RectExport_collideobjects(RectObject *self, PyObject *args, PyObject *kwargs) return NULL; } + /* If 0 width or height, skip, preserves previous behaviour with + * _pg_do_rects_intersect */ if (argrect->w == 0 || argrect->h == 0) { Py_DECREF(obj); continue; @@ -1665,14 +1681,16 @@ RectExport_collidedict(RectObject *self, PyObject *args, PyObject *kwargs) return RAISE(PyExc_TypeError, "first argument must be a dict"); } + /* If the calling rect has 0 width or height, it cannot collide with + * anything, hence return None directly. */ if (srect->w == 0 || srect->h == 0) { Py_RETURN_NONE; } - const PrimitiveType a = MIN(srect->x, srect->x + srect->w); - const PrimitiveType b = MIN(srect->y, srect->y + srect->h); - const PrimitiveType c = MAX(srect->x, srect->x + srect->w); - const PrimitiveType d = MAX(srect->y, srect->y + srect->h); + const PrimitiveType left = MIN(srect->x, srect->x + srect->w); + const PrimitiveType top = MIN(srect->y, srect->y + srect->h); + const PrimitiveType right = MAX(srect->x, srect->x + srect->w); + const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); while (PyDict_Next(dict, &loop, &key, &val)) { if (values) { @@ -1687,12 +1705,14 @@ RectExport_collidedict(RectObject *self, PyObject *args, PyObject *kwargs) } } + /* If 0 width or height, skip, preserves previous behaviour with + * _pg_do_rects_intersect */ if (argrect->w == 0 || argrect->h == 0) { continue; } if (OPTIMIZED_COLLIDERECT(argrect)) { - ret = Py_BuildValue("(OO)", key, val); + ret = PyTuple_Pack(2, key, val); break; } } @@ -1727,14 +1747,16 @@ RectExport_collidedictall(RectObject *self, PyObject *args, PyObject *kwargs) if (!ret) return NULL; + /* If the calling rect has 0 width or height, it cannot collide with + * anything, hence return an empty list directly. */ if (srect->w == 0 || srect->h == 0) { return ret; } - const PrimitiveType a = MIN(srect->x, srect->x + srect->w); - const PrimitiveType b = MIN(srect->y, srect->y + srect->h); - const PrimitiveType c = MAX(srect->x, srect->x + srect->w); - const PrimitiveType d = MAX(srect->y, srect->y + srect->h); + const PrimitiveType left = MIN(srect->x, srect->x + srect->w); + const PrimitiveType top = MIN(srect->y, srect->y + srect->h); + const PrimitiveType right = MAX(srect->x, srect->x + srect->w); + const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); while (PyDict_Next(dict, &loop, &key, &val)) { if (values) { @@ -1751,12 +1773,13 @@ RectExport_collidedictall(RectObject *self, PyObject *args, PyObject *kwargs) } } - if (argrect->w == 0 || argrect->h == 0) { + /* If 0 width or height, skip, preserves previous behaviour with + * _pg_do_rects_intersect */ + if (argrect->w == 0 || argrect->h == 0) continue; - } if (OPTIMIZED_COLLIDERECT(argrect)) { - PyObject *num = Py_BuildValue("(OO)", key, val); + PyObject *num = PyTuple_Pack(2, key, val); if (!num) { Py_DECREF(ret); return NULL; From 18acdd380548e811a67a92246af482d49135ef4f Mon Sep 17 00:00:00 2001 From: itzpr3d4t0r <103119829+itzpr3d4t0r@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:57:48 +0200 Subject: [PATCH 4/5] addressed review --- src_c/rect_impl.h | 56 +++++++---------------------------------------- 1 file changed, 8 insertions(+), 48 deletions(-) diff --git a/src_c/rect_impl.h b/src_c/rect_impl.h index fcb7b20446..1d0d356eb8 100644 --- a/src_c/rect_impl.h +++ b/src_c/rect_impl.h @@ -1293,9 +1293,14 @@ RectExport_colliderect(RectObject *self, PyObject *const *args, } #ifndef OPTIMIZED_COLLIDERECT -#define OPTIMIZED_COLLIDERECT(r) \ - (left < MAX(r->x, r->x + r->w) && top < MAX(r->y, r->y + r->h) && \ - right > MIN(r->x, r->x + r->w) && bottom > MIN(r->y, r->y + r->h)) +/* This macro is used to optimize the colliderect function. Makes use of + * precalculated values to avoid unnecessary calculations. It also checks + * whether the other rect has 0 width or height, in which case we don't + * collide. */ +#define OPTIMIZED_COLLIDERECT(r) \ + (r->w && r->h && left < MAX(r->x, r->x + r->w) && \ + top < MAX(r->y, r->y + r->h) && right > MIN(r->x, r->x + r->w) && \ + bottom > MIN(r->y, r->y + r->h)) #endif static PyObject * @@ -1331,11 +1336,6 @@ RectExport_collidelist(RectObject *self, PyObject *arg) "Argument must be a sequence of rectstyle objects."); } - /* If 0 width or height, skip, preserves previous behaviour with - * _pg_do_rects_intersect */ - if (argrect->w == 0 || argrect->h == 0) - continue; - if (OPTIMIZED_COLLIDERECT(argrect)) { return PyLong_FromLong(loop); } @@ -1356,11 +1356,6 @@ RectExport_collidelist(RectObject *self, PyObject *arg) Py_DECREF(obj); - /* If 0 width or height, skip, preserves previous behaviour with - * _pg_do_rects_intersect */ - if (argrect->w == 0 || argrect->h == 0) - continue; - if (OPTIMIZED_COLLIDERECT(argrect)) { return PyLong_FromLong(loop); } @@ -1409,11 +1404,6 @@ RectExport_collidelistall(RectObject *self, PyObject *arg) "Argument must be a sequence of rectstyle objects."); } - /* If 0 width or height, skip, preserves previous behaviour with - * _pg_do_rects_intersect */ - if (!argrect->w || !argrect->h) - continue; - if (OPTIMIZED_COLLIDERECT(argrect)) { PyObject *num = PyLong_FromLong(loop); if (!num) { @@ -1444,11 +1434,6 @@ RectExport_collidelistall(RectObject *self, PyObject *arg) Py_DECREF(obj); - /* If 0 width or height, skip, preserves previous behaviour with - * _pg_do_rects_intersect */ - if (argrect->w == 0 || argrect->h == 0) - continue; - if (OPTIMIZED_COLLIDERECT(argrect)) { PyObject *num = PyLong_FromLong(loop); if (!num) { @@ -1566,13 +1551,6 @@ RectExport_collideobjectsall(RectObject *self, PyObject *args, return NULL; } - /* If 0 width or height, skip, preserves previous behaviour with - * _pg_do_rects_intersect */ - if (argrect->w == 0 || argrect->h == 0) { - Py_DECREF(obj); - continue; - } - if (OPTIMIZED_COLLIDERECT(argrect)) { if (0 != PyList_Append(ret, obj)) { Py_DECREF(ret); @@ -1645,13 +1623,6 @@ RectExport_collideobjects(RectObject *self, PyObject *args, PyObject *kwargs) return NULL; } - /* If 0 width or height, skip, preserves previous behaviour with - * _pg_do_rects_intersect */ - if (argrect->w == 0 || argrect->h == 0) { - Py_DECREF(obj); - continue; - } - if (OPTIMIZED_COLLIDERECT(argrect)) { return obj; } @@ -1705,12 +1676,6 @@ RectExport_collidedict(RectObject *self, PyObject *args, PyObject *kwargs) } } - /* If 0 width or height, skip, preserves previous behaviour with - * _pg_do_rects_intersect */ - if (argrect->w == 0 || argrect->h == 0) { - continue; - } - if (OPTIMIZED_COLLIDERECT(argrect)) { ret = PyTuple_Pack(2, key, val); break; @@ -1773,11 +1738,6 @@ RectExport_collidedictall(RectObject *self, PyObject *args, PyObject *kwargs) } } - /* If 0 width or height, skip, preserves previous behaviour with - * _pg_do_rects_intersect */ - if (argrect->w == 0 || argrect->h == 0) - continue; - if (OPTIMIZED_COLLIDERECT(argrect)) { PyObject *num = PyTuple_Pack(2, key, val); if (!num) { From 2a0782442a342907b80e60f61edc2306a5705e7f Mon Sep 17 00:00:00 2001 From: itzpr3d4t0r <103119829+itzpr3d4t0r@users.noreply.github.com> Date: Sun, 21 Apr 2024 16:00:26 +0200 Subject: [PATCH 5/5] addressed reviews --- src_c/rect_impl.h | 43 ++++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/src_c/rect_impl.h b/src_c/rect_impl.h index 1d0d356eb8..eeea78af8f 100644 --- a/src_c/rect_impl.h +++ b/src_c/rect_impl.h @@ -1292,6 +1292,17 @@ RectExport_colliderect(RectObject *self, PyObject *const *args, return PyBool_FromLong(_pg_do_rects_intersect(&self->r, argrect)); } +#ifndef OPTIMIZED_COLLIDERECT_SETUP +/* This macro is used to optimize the colliderect function. It calculates + * the left, top, right and bottom values of the calling rect only once + * and uses them in the OPTIMIZED_COLLIDERECT macro. */ +#define OPTIMIZED_COLLIDERECT_SETUP \ + const PrimitiveType left = MIN(srect->x, srect->x + srect->w); \ + const PrimitiveType top = MIN(srect->y, srect->y + srect->h); \ + const PrimitiveType right = MAX(srect->x, srect->x + srect->w); \ + const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); +#endif + #ifndef OPTIMIZED_COLLIDERECT /* This macro is used to optimize the colliderect function. Makes use of * precalculated values to avoid unnecessary calculations. It also checks @@ -1320,10 +1331,7 @@ RectExport_collidelist(RectObject *self, PyObject *arg) "Argument must be a sequence of rectstyle objects."); } - const PrimitiveType left = MIN(srect->x, srect->x + srect->w); - const PrimitiveType top = MIN(srect->y, srect->y + srect->h); - const PrimitiveType right = MAX(srect->x, srect->x + srect->w); - const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); + OPTIMIZED_COLLIDERECT_SETUP; /* If the sequence is a fast sequence, we can use the faster * PySequence_Fast_ITEMS() function to get the items. */ @@ -1342,7 +1350,7 @@ RectExport_collidelist(RectObject *self, PyObject *arg) } } /* If the sequence is not a fast sequence, we have to use the slower - * PySequence_GetItem() function to get the items. */ + * PySequence_ITEM() function to get the items. */ else { for (loop = 0; loop < PySequence_Length(arg); loop++) { PyObject *obj = PySequence_ITEM(arg, loop); @@ -1387,10 +1395,7 @@ RectExport_collidelistall(RectObject *self, PyObject *arg) return ret; } - const PrimitiveType left = MIN(srect->x, srect->x + srect->w); - const PrimitiveType top = MIN(srect->y, srect->y + srect->h); - const PrimitiveType right = MAX(srect->x, srect->x + srect->w); - const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); + OPTIMIZED_COLLIDERECT_SETUP; /* If the sequence is a fast sequence, we can use the faster * PySequence_Fast_ITEMS() function to get the items. */ @@ -1525,10 +1530,7 @@ RectExport_collideobjectsall(RectObject *self, PyObject *args, return ret; } - const PrimitiveType left = MIN(srect->x, srect->x + srect->w); - const PrimitiveType top = MIN(srect->y, srect->y + srect->h); - const PrimitiveType right = MAX(srect->x, srect->x + srect->w); - const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); + OPTIMIZED_COLLIDERECT_SETUP; size = PySequence_Length(list); if (size == -1) { @@ -1600,10 +1602,7 @@ RectExport_collideobjects(RectObject *self, PyObject *args, PyObject *kwargs) Py_RETURN_NONE; } - const PrimitiveType left = MIN(srect->x, srect->x + srect->w); - const PrimitiveType top = MIN(srect->y, srect->y + srect->h); - const PrimitiveType right = MAX(srect->x, srect->x + srect->w); - const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); + OPTIMIZED_COLLIDERECT_SETUP; size = PySequence_Length(list); if (size == -1) { @@ -1658,10 +1657,7 @@ RectExport_collidedict(RectObject *self, PyObject *args, PyObject *kwargs) Py_RETURN_NONE; } - const PrimitiveType left = MIN(srect->x, srect->x + srect->w); - const PrimitiveType top = MIN(srect->y, srect->y + srect->h); - const PrimitiveType right = MAX(srect->x, srect->x + srect->w); - const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); + OPTIMIZED_COLLIDERECT_SETUP; while (PyDict_Next(dict, &loop, &key, &val)) { if (values) { @@ -1718,10 +1714,7 @@ RectExport_collidedictall(RectObject *self, PyObject *args, PyObject *kwargs) return ret; } - const PrimitiveType left = MIN(srect->x, srect->x + srect->w); - const PrimitiveType top = MIN(srect->y, srect->y + srect->h); - const PrimitiveType right = MAX(srect->x, srect->x + srect->w); - const PrimitiveType bottom = MAX(srect->y, srect->y + srect->h); + OPTIMIZED_COLLIDERECT_SETUP; while (PyDict_Next(dict, &loop, &key, &val)) { if (values) {