From 2386e80448a78dca898cdcb2007a02bbebb6a310 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 1 Jun 2021 10:44:39 +0200 Subject: [PATCH] linmath: Backport support for floor division to 1.10 Backport of 89447378440e9b9472a7290facbd8949f41a64ae (Also fixes return type of `__pow__` to always be derived class) --- panda/src/linmath/lvecBase2_ext_src.I | 77 ++++++++++++++++++++-- panda/src/linmath/lvecBase2_ext_src.h | 5 +- panda/src/linmath/lvecBase2_src.h | 5 +- panda/src/linmath/lvecBase3_ext_src.I | 85 ++++++++++++++++++++++-- panda/src/linmath/lvecBase3_ext_src.h | 5 +- panda/src/linmath/lvecBase3_src.h | 5 +- panda/src/linmath/lvecBase4_ext_src.I | 93 +++++++++++++++++++++++++-- panda/src/linmath/lvecBase4_ext_src.h | 5 +- panda/src/linmath/lvecBase4_src.h | 5 +- tests/linmath/test_lvector2.py | 20 ++++++ tests/linmath/test_lvector3.py | 20 ++++++ tests/linmath/test_lvector4.py | 20 ++++++ 12 files changed, 321 insertions(+), 24 deletions(-) diff --git a/panda/src/linmath/lvecBase2_ext_src.I b/panda/src/linmath/lvecBase2_ext_src.I index 7f1980d52f..da9f52388d 100644 --- a/panda/src/linmath/lvecBase2_ext_src.I +++ b/panda/src/linmath/lvecBase2_ext_src.I @@ -200,11 +200,78 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) { /** * */ -INLINE_LINMATH FLOATNAME(LVecBase2) Extension:: -__pow__(FLOATTYPE exponent) const { - return FLOATNAME(LVecBase2)( - cpow(_this->_v(0), exponent), - cpow(_this->_v(1), exponent)); +INLINE_LINMATH PyObject *Extension:: +__floordiv__(PyObject *self, FLOATTYPE scalar) const { + if (scalar == (FLOATTYPE)0) { + return PyErr_Format(PyExc_ZeroDivisionError, "floor division by zero"); + } + +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase2); +#endif + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase2) *vec = (FLOATNAME(LVecBase2) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase2)); + nassertr(vec != nullptr, nullptr); + +#ifdef FLOATTYPE_IS_INT + if (scalar > 0) { + vec->_v(0) = (_this->_v(0) >= 0) ? _this->_v(0) / scalar : -1 - (-1 - _this->_v(0)) / scalar; + vec->_v(1) = (_this->_v(1) >= 0) ? _this->_v(1) / scalar : -1 - (-1 - _this->_v(1)) / scalar; + } else { + vec->_v(0) = (_this->_v(0) <= 0) ? _this->_v(0) / scalar : -1 + (1 - _this->_v(0)) / -scalar; + vec->_v(1) = (_this->_v(1) <= 0) ? _this->_v(1) / scalar : -1 + (1 - _this->_v(1)) / -scalar; + } +#else + vec->_v(0) = std::floor(_this->_v(0) / scalar); + vec->_v(1) = std::floor(_this->_v(1) / scalar); +#endif + } + return py_vec; +} + +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__ifloordiv__(PyObject *self, FLOATTYPE scalar) { + if (scalar == (FLOATTYPE)0) { + return PyErr_Format(PyExc_ZeroDivisionError, "floor division by zero"); + } + +#ifdef FLOATTYPE_IS_INT + if (scalar > 0) { + _this->_v(0) = (_this->_v(0) >= 0) ? _this->_v(0) / scalar : -1 - (-1 - _this->_v(0)) / scalar; + _this->_v(1) = (_this->_v(1) >= 0) ? _this->_v(1) / scalar : -1 - (-1 - _this->_v(1)) / scalar; + } else { + _this->_v(0) = (_this->_v(0) <= 0) ? _this->_v(0) / scalar : -1 + (1 - _this->_v(0)) / -scalar; + _this->_v(1) = (_this->_v(1) <= 0) ? _this->_v(1) / scalar : -1 + (1 - _this->_v(1)) / -scalar; + } +#else + _this->_v(0) = std::floor(_this->_v(0) / scalar); + _this->_v(1) = std::floor(_this->_v(1) / scalar); +#endif + Py_INCREF(self); + return self; +} + +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__pow__(PyObject *self, FLOATTYPE exponent) const { +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase2); +#endif + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase2) *vec = (FLOATNAME(LVecBase2) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase2)); + nassertr(vec != nullptr, nullptr); + + vec->_v(0) = cpow(_this->_v(0), exponent); + vec->_v(1) = cpow(_this->_v(1), exponent); + } + return py_vec; } /** diff --git a/panda/src/linmath/lvecBase2_ext_src.h b/panda/src/linmath/lvecBase2_ext_src.h index 59349980f1..c57dc15504 100644 --- a/panda/src/linmath/lvecBase2_ext_src.h +++ b/panda/src/linmath/lvecBase2_ext_src.h @@ -23,7 +23,10 @@ public: INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign); INLINE_LINMATH std::string __repr__() const; - INLINE_LINMATH FLOATNAME(LVecBase2) __pow__(FLOATTYPE exponent) const; + INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const; + INLINE_LINMATH PyObject *__ifloordiv__(PyObject *self, FLOATTYPE scalar); + + INLINE_LINMATH PyObject *__pow__(PyObject *self, FLOATTYPE exponent) const; INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent); INLINE_LINMATH PyObject *__round__(PyObject *self) const; diff --git a/panda/src/linmath/lvecBase2_src.h b/panda/src/linmath/lvecBase2_src.h index b58a22bd42..6e41088706 100644 --- a/panda/src/linmath/lvecBase2_src.h +++ b/panda/src/linmath/lvecBase2_src.h @@ -133,7 +133,10 @@ PUBLISHED: INLINE_LINMATH void componentwise_mult(const FLOATNAME(LVecBase2) &other); - EXTENSION(INLINE_LINMATH FLOATNAME(LVecBase2) __pow__(FLOATTYPE exponent) const); + EXTENSION(INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const); + EXTENSION(INLINE_LINMATH PyObject *__ifloordiv__(PyObject *self, FLOATTYPE scalar)); + + EXTENSION(INLINE_LINMATH PyObject *__pow__(PyObject *self, FLOATTYPE exponent) const); EXTENSION(INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent)); EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self)); diff --git a/panda/src/linmath/lvecBase3_ext_src.I b/panda/src/linmath/lvecBase3_ext_src.I index 1eda4d2534..e59a032b89 100644 --- a/panda/src/linmath/lvecBase3_ext_src.I +++ b/panda/src/linmath/lvecBase3_ext_src.I @@ -201,12 +201,85 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) { /** * */ -INLINE_LINMATH FLOATNAME(LVecBase3) Extension:: -__pow__(FLOATTYPE exponent) const { - return FLOATNAME(LVecBase3)( - cpow(_this->_v(0), exponent), - cpow(_this->_v(1), exponent), - cpow(_this->_v(2), exponent)); +INLINE_LINMATH PyObject *Extension:: +__floordiv__(PyObject *self, FLOATTYPE scalar) const { + if (scalar == (FLOATTYPE)0) { + return PyErr_Format(PyExc_ZeroDivisionError, "floor division by zero"); + } + +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3); +#endif + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase3) *vec = (FLOATNAME(LVecBase3) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase3)); + nassertr(vec != nullptr, nullptr); + +#ifdef FLOATTYPE_IS_INT + if (scalar > 0) { + vec->_v(0) = (_this->_v(0) >= 0) ? _this->_v(0) / scalar : -1 - (-1 - _this->_v(0)) / scalar; + vec->_v(1) = (_this->_v(1) >= 0) ? _this->_v(1) / scalar : -1 - (-1 - _this->_v(1)) / scalar; + vec->_v(2) = (_this->_v(2) >= 0) ? _this->_v(2) / scalar : -1 - (-1 - _this->_v(2)) / scalar; + } else { + vec->_v(0) = (_this->_v(0) <= 0) ? _this->_v(0) / scalar : -1 + (1 - _this->_v(0)) / -scalar; + vec->_v(1) = (_this->_v(1) <= 0) ? _this->_v(1) / scalar : -1 + (1 - _this->_v(1)) / -scalar; + vec->_v(2) = (_this->_v(2) <= 0) ? _this->_v(2) / scalar : -1 + (1 - _this->_v(2)) / -scalar; + } +#else + vec->_v(0) = std::floor(_this->_v(0) / scalar); + vec->_v(1) = std::floor(_this->_v(1) / scalar); + vec->_v(2) = std::floor(_this->_v(2) / scalar); +#endif + } + return py_vec; +} + +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__ifloordiv__(PyObject *self, FLOATTYPE scalar) { + if (scalar == (FLOATTYPE)0) { + return PyErr_Format(PyExc_ZeroDivisionError, "floor division by zero"); + } + +#ifdef FLOATTYPE_IS_INT + if (scalar > 0) { + _this->_v(0) = (_this->_v(0) >= 0) ? _this->_v(0) / scalar : -1 - (-1 - _this->_v(0)) / scalar; + _this->_v(1) = (_this->_v(1) >= 0) ? _this->_v(1) / scalar : -1 - (-1 - _this->_v(1)) / scalar; + _this->_v(2) = (_this->_v(2) >= 0) ? _this->_v(2) / scalar : -1 - (-1 - _this->_v(2)) / scalar; + } else { + _this->_v(0) = (_this->_v(0) <= 0) ? _this->_v(0) / scalar : -1 + (1 - _this->_v(0)) / -scalar; + _this->_v(1) = (_this->_v(1) <= 0) ? _this->_v(1) / scalar : -1 + (1 - _this->_v(1)) / -scalar; + _this->_v(2) = (_this->_v(2) <= 0) ? _this->_v(2) / scalar : -1 + (1 - _this->_v(2)) / -scalar; + } +#else + _this->_v(0) = std::floor(_this->_v(0) / scalar); + _this->_v(1) = std::floor(_this->_v(1) / scalar); + _this->_v(2) = std::floor(_this->_v(2) / scalar); +#endif + Py_INCREF(self); + return self; +} + +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__pow__(PyObject *self, FLOATTYPE exponent) const { +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3); +#endif + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase3) *vec = (FLOATNAME(LVecBase3) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase3)); + nassertr(vec != nullptr, nullptr); + + vec->_v(0) = cpow(_this->_v(0), exponent); + vec->_v(1) = cpow(_this->_v(1), exponent); + vec->_v(2) = cpow(_this->_v(2), exponent); + } + return py_vec; } /** diff --git a/panda/src/linmath/lvecBase3_ext_src.h b/panda/src/linmath/lvecBase3_ext_src.h index a80733c6a7..09b6c30234 100644 --- a/panda/src/linmath/lvecBase3_ext_src.h +++ b/panda/src/linmath/lvecBase3_ext_src.h @@ -23,7 +23,10 @@ public: INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign); INLINE_LINMATH std::string __repr__() const; - INLINE_LINMATH FLOATNAME(LVecBase3) __pow__(FLOATTYPE exponent) const; + INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const; + INLINE_LINMATH PyObject *__ifloordiv__(PyObject *self, FLOATTYPE scalar); + + INLINE_LINMATH PyObject *__pow__(PyObject *self, FLOATTYPE exponent) const; INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent); INLINE_LINMATH PyObject *__round__(PyObject *self) const; diff --git a/panda/src/linmath/lvecBase3_src.h b/panda/src/linmath/lvecBase3_src.h index 00575a71a7..72f5ffdf00 100644 --- a/panda/src/linmath/lvecBase3_src.h +++ b/panda/src/linmath/lvecBase3_src.h @@ -152,7 +152,10 @@ PUBLISHED: INLINE_LINMATH void componentwise_mult(const FLOATNAME(LVecBase3) &other); - EXTENSION(INLINE_LINMATH FLOATNAME(LVecBase3) __pow__(FLOATTYPE exponent) const); + EXTENSION(INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const); + EXTENSION(INLINE_LINMATH PyObject *__ifloordiv__(PyObject *self, FLOATTYPE scalar)); + + EXTENSION(INLINE_LINMATH PyObject *__pow__(PyObject *self, FLOATTYPE exponent) const); EXTENSION(INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent)); EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self)); diff --git a/panda/src/linmath/lvecBase4_ext_src.I b/panda/src/linmath/lvecBase4_ext_src.I index 5436f28f6d..9db21d73ee 100644 --- a/panda/src/linmath/lvecBase4_ext_src.I +++ b/panda/src/linmath/lvecBase4_ext_src.I @@ -207,13 +207,92 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) { /** * */ -INLINE_LINMATH FLOATNAME(LVecBase4) Extension:: -__pow__(FLOATTYPE exponent) const { - return FLOATNAME(LVecBase4)( - cpow(_this->_v(0), exponent), - cpow(_this->_v(1), exponent), - cpow(_this->_v(2), exponent), - cpow(_this->_v(3), exponent)); +INLINE_LINMATH PyObject *Extension:: +__floordiv__(PyObject *self, FLOATTYPE scalar) const { + if (scalar == (FLOATTYPE)0) { + return PyErr_Format(PyExc_ZeroDivisionError, "floor division by zero"); + } + +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); +#endif + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase4) *vec = (FLOATNAME(LVecBase4) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase4)); + nassertr(vec != nullptr, nullptr); + +#ifdef FLOATTYPE_IS_INT + if (scalar > 0) { + vec->_v(0) = (_this->_v(0) >= 0) ? _this->_v(0) / scalar : -1 - (-1 - _this->_v(0)) / scalar; + vec->_v(1) = (_this->_v(1) >= 0) ? _this->_v(1) / scalar : -1 - (-1 - _this->_v(1)) / scalar; + vec->_v(2) = (_this->_v(2) >= 0) ? _this->_v(2) / scalar : -1 - (-1 - _this->_v(2)) / scalar; + vec->_v(3) = (_this->_v(3) >= 0) ? _this->_v(3) / scalar : -1 - (-1 - _this->_v(3)) / scalar; + } else { + vec->_v(0) = (_this->_v(0) <= 0) ? _this->_v(0) / scalar : -1 + (1 - _this->_v(0)) / -scalar; + vec->_v(1) = (_this->_v(1) <= 0) ? _this->_v(1) / scalar : -1 + (1 - _this->_v(1)) / -scalar; + vec->_v(2) = (_this->_v(2) <= 0) ? _this->_v(2) / scalar : -1 + (1 - _this->_v(2)) / -scalar; + vec->_v(3) = (_this->_v(3) <= 0) ? _this->_v(3) / scalar : -1 + (1 - _this->_v(3)) / -scalar; + } +#else + vec->_v(0) = std::floor(_this->_v(0) / scalar); + vec->_v(1) = std::floor(_this->_v(1) / scalar); + vec->_v(2) = std::floor(_this->_v(2) / scalar); + vec->_v(3) = std::floor(_this->_v(3) / scalar); +#endif + } + return py_vec; +} + +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__ifloordiv__(PyObject *self, FLOATTYPE scalar) { + if (scalar == (FLOATTYPE)0) { + return PyErr_Format(PyExc_ZeroDivisionError, "floor division by zero"); + } + +#ifdef FLOATTYPE_IS_INT + if (scalar > 0) { + _this->_v(0) = (_this->_v(0) >= 0) ? _this->_v(0) / scalar : -1 - (-1 - _this->_v(0)) / scalar; + _this->_v(1) = (_this->_v(1) >= 0) ? _this->_v(1) / scalar : -1 - (-1 - _this->_v(1)) / scalar; + _this->_v(2) = (_this->_v(2) >= 0) ? _this->_v(2) / scalar : -1 - (-1 - _this->_v(2)) / scalar; + _this->_v(3) = (_this->_v(3) >= 0) ? _this->_v(3) / scalar : -1 - (-1 - _this->_v(3)) / scalar; + } else { + _this->_v(0) = (_this->_v(0) <= 0) ? _this->_v(0) / scalar : -1 + (1 - _this->_v(0)) / -scalar; + _this->_v(1) = (_this->_v(1) <= 0) ? _this->_v(1) / scalar : -1 + (1 - _this->_v(1)) / -scalar; + _this->_v(2) = (_this->_v(2) <= 0) ? _this->_v(2) / scalar : -1 + (1 - _this->_v(2)) / -scalar; + _this->_v(3) = (_this->_v(3) <= 0) ? _this->_v(3) / scalar : -1 + (1 - _this->_v(3)) / -scalar; + } +#else + _this->_v(0) = std::floor(_this->_v(0) / scalar); + _this->_v(1) = std::floor(_this->_v(1) / scalar); + _this->_v(2) = std::floor(_this->_v(2) / scalar); + _this->_v(3) = std::floor(_this->_v(3) / scalar); +#endif + Py_INCREF(self); + return self; +} + +/** + * + */ +INLINE_LINMATH PyObject *Extension:: +__pow__(PyObject *self, FLOATTYPE exponent) const { +#ifndef CPPPARSER + extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); +#endif + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); + if (py_vec != nullptr) { + FLOATNAME(LVecBase4) *vec = (FLOATNAME(LVecBase4) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase4)); + nassertr(vec != nullptr, nullptr); + + vec->_v(0) = cpow(_this->_v(0), exponent); + vec->_v(1) = cpow(_this->_v(1), exponent); + vec->_v(2) = cpow(_this->_v(2), exponent); + vec->_v(3) = cpow(_this->_v(3), exponent); + } + return py_vec; } /** diff --git a/panda/src/linmath/lvecBase4_ext_src.h b/panda/src/linmath/lvecBase4_ext_src.h index e5115fb2df..693c07e111 100644 --- a/panda/src/linmath/lvecBase4_ext_src.h +++ b/panda/src/linmath/lvecBase4_ext_src.h @@ -23,7 +23,10 @@ public: INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign); INLINE_LINMATH std::string __repr__() const; - INLINE_LINMATH FLOATNAME(LVecBase4) __pow__(FLOATTYPE exponent) const; + INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const; + INLINE_LINMATH PyObject *__ifloordiv__(PyObject *self, FLOATTYPE scalar); + + INLINE_LINMATH PyObject *__pow__(PyObject *self, FLOATTYPE exponent) const; INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent); INLINE_LINMATH PyObject *__round__(PyObject *self) const; diff --git a/panda/src/linmath/lvecBase4_src.h b/panda/src/linmath/lvecBase4_src.h index ab98ba88dc..fd73d5dbed 100644 --- a/panda/src/linmath/lvecBase4_src.h +++ b/panda/src/linmath/lvecBase4_src.h @@ -160,7 +160,10 @@ PUBLISHED: INLINE_LINMATH void componentwise_mult(const FLOATNAME(LVecBase4) &other); - EXTENSION(INLINE_LINMATH FLOATNAME(LVecBase4) __pow__(FLOATTYPE exponent) const); + EXTENSION(INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const); + EXTENSION(INLINE_LINMATH PyObject *__ifloordiv__(PyObject *self, FLOATTYPE scalar)); + + EXTENSION(INLINE_LINMATH PyObject *__pow__(PyObject *self, FLOATTYPE exponent) const); EXTENSION(INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent)); EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self)); diff --git a/tests/linmath/test_lvector2.py b/tests/linmath/test_lvector2.py index e97529d116..d955fe8d8e 100644 --- a/tests/linmath/test_lvector2.py +++ b/tests/linmath/test_lvector2.py @@ -2,6 +2,7 @@ from math import floor, ceil import sys from panda3d.core import Vec2, Vec3, Vec4, Vec2F, Vec2D +from panda3d import core import pytest @@ -121,3 +122,22 @@ def test_vec2_ceil(): rounded_vector = ceil(original_vector) assert rounded_vector.x == 3 assert rounded_vector.y == -2 + + +@pytest.mark.parametrize("type", (core.LVecBase2f, core.LVecBase2d, core.LVecBase2i)) +def test_vec2_floordiv(type): + with pytest.raises(ZeroDivisionError): + type(1, 2) // 0 + + for i in range(-100, 100): + for j in range(1, 100): + assert (type(i) // j).x == i // j + assert (type(i) // -j).x == i // -j + + v = type(i) + v //= j + assert v.x == i // j + + v = type(i) + v //= -j + assert v.x == i // -j diff --git a/tests/linmath/test_lvector3.py b/tests/linmath/test_lvector3.py index ee4b6069de..31f1ff5fe8 100644 --- a/tests/linmath/test_lvector3.py +++ b/tests/linmath/test_lvector3.py @@ -2,6 +2,7 @@ from math import floor, ceil import sys from panda3d.core import Vec2, Vec3, Vec3F, Vec3D +from panda3d import core import pytest @@ -106,3 +107,22 @@ def test_vec3_ceil(): assert rounded_vector.x == 3 assert rounded_vector.y == -2 assert rounded_vector.z == 4 + + +@pytest.mark.parametrize("type", (core.LVecBase3f, core.LVecBase3d, core.LVecBase3i)) +def test_vec3_floordiv(type): + with pytest.raises(ZeroDivisionError): + type(1, 2, 3) // 0 + + for i in range(-100, 100): + for j in range(1, 100): + assert (type(i) // j).x == i // j + assert (type(i) // -j).x == i // -j + + v = type(i) + v //= j + assert v.x == i // j + + v = type(i) + v //= -j + assert v.x == i // -j diff --git a/tests/linmath/test_lvector4.py b/tests/linmath/test_lvector4.py index edecfdf689..7cf375589e 100644 --- a/tests/linmath/test_lvector4.py +++ b/tests/linmath/test_lvector4.py @@ -2,6 +2,7 @@ from math import floor, ceil import sys from panda3d.core import Vec2, Vec3, Vec4, Vec4F, Vec4D +from panda3d import core import pytest @@ -122,3 +123,22 @@ def test_vec4_ceil(): assert rounded_vector.y == -2 assert rounded_vector.z == 4 assert rounded_vector.w == 1 + + +@pytest.mark.parametrize("type", (core.LVecBase4f, core.LVecBase4d, core.LVecBase4i)) +def test_vec4_floordiv(type): + with pytest.raises(ZeroDivisionError): + type(1, 2, 3, 4) // 0 + + for i in range(-100, 100): + for j in range(1, 100): + assert (type(i) // j).x == i // j + assert (type(i) // -j).x == i // -j + + v = type(i) + v //= j + assert v.x == i // j + + v = type(i) + v //= -j + assert v.x == i // -j