linmath: Backport support for floor division to 1.10

Backport of 89447378440e9b9472a7290facbd8949f41a64ae

(Also fixes return type of `__pow__` to always be derived class)
This commit is contained in:
rdb 2021-06-01 10:44:39 +02:00
parent 4e0e945279
commit 2386e80448
12 changed files with 321 additions and 24 deletions

View File

@ -200,11 +200,78 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) {
/** /**
* *
*/ */
INLINE_LINMATH FLOATNAME(LVecBase2) Extension<FLOATNAME(LVecBase2)>:: INLINE_LINMATH PyObject *Extension<FLOATNAME(LVecBase2)>::
__pow__(FLOATTYPE exponent) const { __floordiv__(PyObject *self, FLOATTYPE scalar) const {
return FLOATNAME(LVecBase2)( if (scalar == (FLOATTYPE)0) {
cpow(_this->_v(0), exponent), return PyErr_Format(PyExc_ZeroDivisionError, "floor division by zero");
cpow(_this->_v(1), exponent)); }
#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<FLOATNAME(LVecBase2)>::
__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<FLOATNAME(LVecBase2)>::
__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;
} }
/** /**

View File

@ -23,7 +23,10 @@ public:
INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign); INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign);
INLINE_LINMATH std::string __repr__() const; 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 *__ipow__(PyObject *self, FLOATTYPE exponent);
INLINE_LINMATH PyObject *__round__(PyObject *self) const; INLINE_LINMATH PyObject *__round__(PyObject *self) const;

View File

@ -133,7 +133,10 @@ PUBLISHED:
INLINE_LINMATH void componentwise_mult(const FLOATNAME(LVecBase2) &other); 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 *__ipow__(PyObject *self, FLOATTYPE exponent));
EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self)); EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self));

View File

@ -201,12 +201,85 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) {
/** /**
* *
*/ */
INLINE_LINMATH FLOATNAME(LVecBase3) Extension<FLOATNAME(LVecBase3)>:: INLINE_LINMATH PyObject *Extension<FLOATNAME(LVecBase3)>::
__pow__(FLOATTYPE exponent) const { __floordiv__(PyObject *self, FLOATTYPE scalar) const {
return FLOATNAME(LVecBase3)( if (scalar == (FLOATTYPE)0) {
cpow(_this->_v(0), exponent), return PyErr_Format(PyExc_ZeroDivisionError, "floor division by zero");
cpow(_this->_v(1), exponent), }
cpow(_this->_v(2), exponent));
#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<FLOATNAME(LVecBase3)>::
__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<FLOATNAME(LVecBase3)>::
__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;
} }
/** /**

View File

@ -23,7 +23,10 @@ public:
INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign); INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign);
INLINE_LINMATH std::string __repr__() const; 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 *__ipow__(PyObject *self, FLOATTYPE exponent);
INLINE_LINMATH PyObject *__round__(PyObject *self) const; INLINE_LINMATH PyObject *__round__(PyObject *self) const;

View File

@ -152,7 +152,10 @@ PUBLISHED:
INLINE_LINMATH void componentwise_mult(const FLOATNAME(LVecBase3) &other); 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 *__ipow__(PyObject *self, FLOATTYPE exponent));
EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self)); EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self));

View File

@ -207,13 +207,92 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) {
/** /**
* *
*/ */
INLINE_LINMATH FLOATNAME(LVecBase4) Extension<FLOATNAME(LVecBase4)>:: INLINE_LINMATH PyObject *Extension<FLOATNAME(LVecBase4)>::
__pow__(FLOATTYPE exponent) const { __floordiv__(PyObject *self, FLOATTYPE scalar) const {
return FLOATNAME(LVecBase4)( if (scalar == (FLOATTYPE)0) {
cpow(_this->_v(0), exponent), return PyErr_Format(PyExc_ZeroDivisionError, "floor division by zero");
cpow(_this->_v(1), exponent), }
cpow(_this->_v(2), exponent),
cpow(_this->_v(3), exponent)); #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<FLOATNAME(LVecBase4)>::
__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<FLOATNAME(LVecBase4)>::
__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;
} }
/** /**

View File

@ -23,7 +23,10 @@ public:
INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign); INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign);
INLINE_LINMATH std::string __repr__() const; 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 *__ipow__(PyObject *self, FLOATTYPE exponent);
INLINE_LINMATH PyObject *__round__(PyObject *self) const; INLINE_LINMATH PyObject *__round__(PyObject *self) const;

View File

@ -160,7 +160,10 @@ PUBLISHED:
INLINE_LINMATH void componentwise_mult(const FLOATNAME(LVecBase4) &other); 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 *__ipow__(PyObject *self, FLOATTYPE exponent));
EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self)); EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self));

View File

@ -2,6 +2,7 @@ from math import floor, ceil
import sys import sys
from panda3d.core import Vec2, Vec3, Vec4, Vec2F, Vec2D from panda3d.core import Vec2, Vec3, Vec4, Vec2F, Vec2D
from panda3d import core
import pytest import pytest
@ -121,3 +122,22 @@ def test_vec2_ceil():
rounded_vector = ceil(original_vector) rounded_vector = ceil(original_vector)
assert rounded_vector.x == 3 assert rounded_vector.x == 3
assert rounded_vector.y == -2 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

View File

@ -2,6 +2,7 @@ from math import floor, ceil
import sys import sys
from panda3d.core import Vec2, Vec3, Vec3F, Vec3D from panda3d.core import Vec2, Vec3, Vec3F, Vec3D
from panda3d import core
import pytest import pytest
@ -106,3 +107,22 @@ def test_vec3_ceil():
assert rounded_vector.x == 3 assert rounded_vector.x == 3
assert rounded_vector.y == -2 assert rounded_vector.y == -2
assert rounded_vector.z == 4 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

View File

@ -2,6 +2,7 @@ from math import floor, ceil
import sys import sys
from panda3d.core import Vec2, Vec3, Vec4, Vec4F, Vec4D from panda3d.core import Vec2, Vec3, Vec4, Vec4F, Vec4D
from panda3d import core
import pytest import pytest
@ -122,3 +123,22 @@ def test_vec4_ceil():
assert rounded_vector.y == -2 assert rounded_vector.y == -2
assert rounded_vector.z == 4 assert rounded_vector.z == 4
assert rounded_vector.w == 1 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