- Notifications
You must be signed in to change notification settings - Fork3.9k
Fix Vector subclass methods to return the correct subtype instance#3088
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Merged
Uh oh!
There was an error while loading.Please reload this page.
Merged
Changes fromall commits
Commits
Show all changes
18 commits Select commitHold shift + click to select a range
8d9f050 created _vector_subtype_new()
andrewhong045e64858 code cleanup
andrewhong040d419f7 added unittests + docs + black formatting
andrewhong040538972 add more subtyping
andrewhong0403678e5 github workflow tests fix
andrewhong04bb08ffd Commented out pgVector_NEW()
andrewhong046091fbd hopefully, this fixes everythinf
andrewhong04ee89fcc Fixed segfault
andrewhong04289458a Update math.c
andrewhong048a23a8e Update math.c
andrewhong04ee34e7a Update math.c
andrewhong04f84c76b Update math.c
andrewhong04064e7b4 segfault fixes and etc
andrewhong0455cc9a2 Bring back pgVector_NEW() & swizzling return fix
andrewhong0448ce90b Merge branch 'vector-subclass' of https://github.com/novialriptide/py…
andrewhong04b57feef code cleanup
andrewhong04583f9b4 more tests
andrewhong040953c24 Update src_c/math.c
andrewhong04File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
8 changes: 8 additions & 0 deletionsdocs/reST/ref/math.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -60,6 +60,10 @@ Multiple coordinates can be set using slices or swizzling | ||
| Some general information about the ``Vector2`` class. | ||
| .. versionchanged:: 2.1.3 | ||
| Inherited methods of vector subclasses now correctly return an instance of the | ||
| subclass instead of the superclass | ||
andrewhong04 marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| .. method:: dot | ||
| | :sl:`calculates the dot- or scalar-product with the other vector` | ||
| @@ -435,6 +439,10 @@ Multiple coordinates can be set using slices or swizzling | ||
| Some general information about the Vector3 class. | ||
| .. versionchanged:: 2.1.3 | ||
| Inherited methods of vector subclasses now correctly return an instance of the | ||
| subclass instead of the superclass | ||
| .. method:: dot | ||
| | :sl:`calculates the dot- or scalar-product with the other vector` | ||
106 changes: 71 additions & 35 deletionssrc_c/math.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -133,6 +133,8 @@ _vector_move_towards_helper(Py_ssize_t dim, double *origin_coords, | ||
| double *target_coords, double max_distance); | ||
| /* generic vector functions */ | ||
| static pgVector * | ||
| _vector_subtype_new(pgVector *base); | ||
| static PyObject * | ||
| pgVector_NEW(Py_ssize_t dim); | ||
| static void | ||
| @@ -550,6 +552,28 @@ static PyMemberDef vector_members[] = { | ||
| {NULL} /* Sentinel */ | ||
| }; | ||
| static pgVector * | ||
| _vector_subtype_new(pgVector *base) | ||
| { | ||
| pgVector *vec; | ||
| PyTypeObject *type = Py_TYPE(base); | ||
| Py_ssize_t dim = base->dim; | ||
| vec = (pgVector *)(type->tp_new(type, NULL, NULL)); | ||
| if (vec) { | ||
andrewhong04 marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| vec->dim = dim; | ||
| vec->epsilon = VECTOR_EPSILON; | ||
| vec->coords = PyMem_New(double, dim); | ||
| if (vec->coords == NULL) { | ||
| Py_DECREF(vec); | ||
| return (pgVector *)PyErr_NoMemory(); | ||
| } | ||
| } | ||
| return vec; | ||
| } | ||
| static PyObject * | ||
| pgVector_NEW(Py_ssize_t dim) | ||
| { | ||
| @@ -639,7 +663,7 @@ vector_generic_math(PyObject *o1, PyObject *o2, int op) | ||
| } | ||
| else if (op != (OP_MUL | OP_ARG_VECTOR) && | ||
| op != (OP_MUL | OP_ARG_VECTOR | OP_ARG_REVERSE)) { | ||
| ret =_vector_subtype_new(vec); | ||
| if (ret == NULL) | ||
| return NULL; | ||
| } | ||
| @@ -760,8 +784,9 @@ vector_inplace_floor_div(pgVector *o1, PyObject *o2) | ||
| static PyObject * | ||
| vector_neg(pgVector *self) | ||
| { | ||
| pgVector *ret = _vector_subtype_new(self); | ||
| if (ret) { | ||
| Py_ssize_t i; | ||
| for (i = 0; i < self->dim; i++) { | ||
| @@ -774,8 +799,9 @@ vector_neg(pgVector *self) | ||
| static PyObject * | ||
| vector_pos(pgVector *self) | ||
| { | ||
| pgVector *ret = _vector_subtype_new(self); | ||
| if (ret) { | ||
| memcpy(ret->coords, self->coords, sizeof(ret->coords[0]) * ret->dim); | ||
| } | ||
| return (PyObject *)ret; | ||
| @@ -796,8 +822,13 @@ vector_nonzero(pgVector *self) | ||
| static PyObject * | ||
| vector_copy(pgVector *self, PyObject *_null) | ||
| { | ||
| Py_ssize_t i; | ||
| pgVector *ret = _vector_subtype_new(self); | ||
| if (!ret) { | ||
| return NULL; | ||
| } | ||
andrewhong04 marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| for (i = 0; i < self->dim; i++) { | ||
| ret->coords[i] = self->coords[i]; | ||
| } | ||
| @@ -810,7 +841,7 @@ vector_clamp_magnitude(pgVector *self, PyObject *args, PyObject *kwargs) | ||
| Py_ssize_t i; | ||
| pgVector *ret; | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL) | ||
| return NULL; | ||
| @@ -1261,9 +1292,7 @@ vector_length_squared(pgVector *self, PyObject *_null) | ||
| static PyObject * | ||
| vector_normalize(pgVector *self, PyObject *_null) | ||
| { | ||
| pgVector *ret = _vector_subtype_new(self); | ||
| if (ret == NULL) { | ||
| return NULL; | ||
| } | ||
| @@ -1399,7 +1428,7 @@ vector_move_towards(pgVector *self, PyObject *args) | ||
| return NULL; | ||
| } | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL) | ||
| return NULL; | ||
| @@ -1481,7 +1510,7 @@ vector_slerp(pgVector *self, PyObject *args) | ||
| if (self->coords[0] * other_coords[1] < self->coords[1] * other_coords[0]) | ||
| angle *= -1; | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL) { | ||
| return NULL; | ||
| } | ||
| @@ -1533,7 +1562,7 @@ vector_lerp(pgVector *self, PyObject *args) | ||
| return NULL; | ||
| } | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL) { | ||
| return NULL; | ||
| } | ||
| @@ -1578,7 +1607,8 @@ _vector_reflect_helper(double *dst_coords, const double *src_coords, | ||
| static PyObject * | ||
| vector_reflect(pgVector *self, PyObject *normal) | ||
| { | ||
| pgVector *ret = _vector_subtype_new(self); | ||
| if (ret == NULL) { | ||
| return NULL; | ||
| } | ||
| @@ -1733,7 +1763,7 @@ vector_project_onto(pgVector *self, PyObject *other) | ||
| return NULL; | ||
| } | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL) { | ||
| return NULL; | ||
| } | ||
| @@ -2175,7 +2205,7 @@ vector2_rotate_rad(pgVector *self, PyObject *angleObject) | ||
| return NULL; | ||
| } | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL || !_vector2_rotate_helper(ret->coords, self->coords, | ||
| angle, self->epsilon)) { | ||
| Py_XDECREF(ret); | ||
| @@ -2228,7 +2258,7 @@ vector2_rotate(pgVector *self, PyObject *angleObject) | ||
| } | ||
| angle = DEG2RAD(angle); | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL || !_vector2_rotate_helper(ret->coords, self->coords, | ||
| angle, self->epsilon)) { | ||
| Py_XDECREF(ret); | ||
| @@ -2680,7 +2710,7 @@ vector3_rotate_rad(pgVector *self, PyObject *args) | ||
| return NULL; | ||
| } | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL || | ||
| !_vector3_rotate_helper(ret->coords, self->coords, axis_coords, angle, | ||
| self->epsilon)) { | ||
| @@ -2750,7 +2780,7 @@ vector3_rotate(pgVector *self, PyObject *args) | ||
| return NULL; | ||
| } | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL || | ||
| !_vector3_rotate_helper(ret->coords, self->coords, axis_coords, angle, | ||
| self->epsilon)) { | ||
| @@ -2802,7 +2832,7 @@ vector3_rotate_x_rad(pgVector *self, PyObject *angleObject) | ||
| sinValue = sin(angle); | ||
| cosValue = cos(angle); | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL) { | ||
| return NULL; | ||
| } | ||
| @@ -2861,7 +2891,7 @@ vector3_rotate_x(pgVector *self, PyObject *angleObject) | ||
| sinValue = sin(angle); | ||
| cosValue = cos(angle); | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL) { | ||
| return NULL; | ||
| } | ||
| @@ -2906,7 +2936,7 @@ vector3_rotate_y_rad(pgVector *self, PyObject *angleObject) | ||
| sinValue = sin(angle); | ||
| cosValue = cos(angle); | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL) { | ||
| return NULL; | ||
| } | ||
| @@ -2966,7 +2996,7 @@ vector3_rotate_y(pgVector *self, PyObject *angleObject) | ||
| sinValue = sin(angle); | ||
| cosValue = cos(angle); | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL) { | ||
| return NULL; | ||
| } | ||
| @@ -3012,7 +3042,7 @@ vector3_rotate_z_rad(pgVector *self, PyObject *angleObject) | ||
| sinValue = sin(angle); | ||
| cosValue = cos(angle); | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL) { | ||
| return NULL; | ||
| } | ||
| @@ -3072,7 +3102,7 @@ vector3_rotate_z(pgVector *self, PyObject *angleObject) | ||
| sinValue = sin(angle); | ||
| cosValue = cos(angle); | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL) { | ||
| return NULL; | ||
| } | ||
| @@ -3133,7 +3163,7 @@ vector3_cross(pgVector *self, PyObject *other) | ||
| } | ||
| } | ||
| ret =_vector_subtype_new(self); | ||
| if (ret == NULL) { | ||
| if (!pgVector_Check(other)) | ||
| PyMem_Free(other_coords); | ||
| @@ -3645,7 +3675,8 @@ vector_elementwiseproxy_generic_math(PyObject *o1, PyObject *o2, int op) | ||
| else | ||
| op |= OP_ARG_UNKNOWN; | ||
| ret = _vector_subtype_new(vec); | ||
| if (ret == NULL) { | ||
| return NULL; | ||
| } | ||
| @@ -3655,8 +3686,9 @@ vector_elementwiseproxy_generic_math(PyObject *o1, PyObject *o2, int op) | ||
| switch (op) { | ||
| case OP_ADD | OP_ARG_NUMBER: | ||
| case OP_ADD | OP_ARG_NUMBER | OP_ARG_REVERSE: | ||
| for (i = 0; i < dim; i++) { | ||
| ret->coords[i] = vec->coords[i] + other_value; | ||
| } | ||
| break; | ||
| case OP_SUB | OP_ARG_NUMBER: | ||
| for (i = 0; i < dim; i++) | ||
| @@ -3844,6 +3876,7 @@ vector_elementwiseproxy_pow(PyObject *baseObj, PyObject *expoObj, | ||
| PyObject *mod) | ||
| { | ||
| Py_ssize_t i, dim; | ||
| pgVector *vec; | ||
| double *tmp; | ||
| PyObject *bases[VECTOR_MAX_SIZE] = {NULL}; | ||
| PyObject *expos[VECTOR_MAX_SIZE] = {NULL}; | ||
| @@ -3856,8 +3889,9 @@ vector_elementwiseproxy_pow(PyObject *baseObj, PyObject *expoObj, | ||
| } | ||
| if (vector_elementwiseproxy_Check(baseObj)) { | ||
| vec = ((vector_elementwiseproxy *)baseObj)->vec; | ||
| dim = vec->dim; | ||
| tmp = vec->coords; | ||
| for (i = 0; i < dim; ++i) | ||
| bases[i] = PyFloat_FromDouble(tmp[i]); | ||
| if (vector_elementwiseproxy_Check(expoObj)) { | ||
| @@ -3883,8 +3917,9 @@ vector_elementwiseproxy_pow(PyObject *baseObj, PyObject *expoObj, | ||
| } | ||
| } | ||
| else { | ||
| vec = ((vector_elementwiseproxy *)expoObj)->vec; | ||
| dim = vec->dim; | ||
| tmp = vec->coords; | ||
| for (i = 0; i < dim; ++i) | ||
| expos[i] = PyFloat_FromDouble(tmp[i]); | ||
| if (pgVectorCompatible_Check(baseObj, dim)) { | ||
| @@ -3909,7 +3944,7 @@ vector_elementwiseproxy_pow(PyObject *baseObj, PyObject *expoObj, | ||
| goto clean_up; | ||
| } | ||
| ret =(PyObject *)_vector_subtype_new(vec); | ||
| if (ret == NULL) | ||
| goto clean_up; | ||
| /* there are many special cases so we let python do the work for us */ | ||
| @@ -3942,8 +3977,8 @@ vector_elementwiseproxy_pow(PyObject *baseObj, PyObject *expoObj, | ||
| static PyObject * | ||
| vector_elementwiseproxy_abs(vector_elementwiseproxy *self) | ||
| { | ||
| pgVector *ret =_vector_subtype_new(self->vec); | ||
| if (ret) { | ||
| Py_ssize_t i; | ||
| for (i = 0; i < self->vec->dim; i++) { | ||
| @@ -4011,6 +4046,7 @@ vector_elementwise(pgVector *vec, PyObject *_null) | ||
| return NULL; | ||
| Py_INCREF(vec); | ||
| proxy->vec = (pgVector *)vec; | ||
| return (PyObject *)proxy; | ||
| } | ||
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.