linmath: Add __rmul__ operator for left scalar multiplication

Fixes #1048
This commit is contained in:
rdb 2021-07-05 14:13:46 +02:00
parent 98054d1bbd
commit f27e9b2a86
36 changed files with 190 additions and 0 deletions

View File

@ -34,6 +34,14 @@ __reduce__(PyObject *self) const {
return result;
}
/**
*
*/
INLINE_LINMATH FLOATNAME(LMatrix3) Extension<FLOATNAME(LMatrix3)>::
__rmul__(FLOATTYPE scalar) const {
return *_this * scalar;
}
/**
*
*/

View File

@ -19,6 +19,9 @@ template<>
class Extension<FLOATNAME(LMatrix3)> : public ExtensionBase<FLOATNAME(LMatrix3)> {
public:
INLINE_LINMATH PyObject *__reduce__(PyObject *self) const;
INLINE_LINMATH FLOATNAME(LMatrix3) __rmul__(FLOATTYPE scalar) const;
INLINE_LINMATH std::string __repr__() const;
};

View File

@ -183,6 +183,8 @@ PUBLISHED:
INLINE_LINMATH FLOATNAME(LMatrix3) &operator *= (FLOATTYPE scalar);
INLINE_LINMATH FLOATNAME(LMatrix3) &operator /= (FLOATTYPE scalar);
EXTENSION(INLINE_LINMATH FLOATNAME(LMatrix3) __rmul__(FLOATTYPE scalar) const);
INLINE_LINMATH void componentwise_mult(const FLOATNAME(LMatrix3) &other);
INLINE_LINMATH FLOATTYPE determinant() const;

View File

@ -35,6 +35,14 @@ __reduce__(PyObject *self) const {
return result;
}
/**
*
*/
INLINE_LINMATH FLOATNAME(LMatrix4) Extension<FLOATNAME(LMatrix4)>::
__rmul__(FLOATTYPE scalar) const {
return *_this * scalar;
}
/**
*
*/

View File

@ -19,6 +19,9 @@ template<>
class Extension<FLOATNAME(LMatrix4)> : public ExtensionBase<FLOATNAME(LMatrix4)> {
public:
INLINE_LINMATH PyObject *__reduce__(PyObject *self) const;
INLINE_LINMATH FLOATNAME(LMatrix4) __rmul__(FLOATTYPE scalar) const;
INLINE_LINMATH std::string __repr__() const;
};

View File

@ -189,6 +189,8 @@ PUBLISHED:
INLINE_LINMATH FLOATNAME(LMatrix4) &operator *= (FLOATTYPE scalar);
INLINE_LINMATH FLOATNAME(LMatrix4) &operator /= (FLOATTYPE scalar);
EXTENSION(INLINE_LINMATH FLOATNAME(LMatrix4) __rmul__(FLOATTYPE scalar) const);
INLINE_LINMATH void componentwise_mult(const FLOATNAME(LMatrix4) &other);
INLINE_LINMATH void transpose_from(const FLOATNAME(LMatrix4) &other);

View File

@ -79,3 +79,11 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) {
// Upcall to LVecBase2.
return invoke_extension<FLOATNAME(LVecBase2)>(_this).__setattr__(self, attr_name, assign);
}
/**
*
*/
INLINE_LINMATH FLOATNAME(LPoint2) Extension<FLOATNAME(LPoint2)>::
__rmul__(FLOATTYPE scalar) const {
return *_this * scalar;
}

View File

@ -20,6 +20,9 @@ class Extension<FLOATNAME(LPoint2)> : public ExtensionBase<FLOATNAME(LPoint2)> {
public:
INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const;
INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign);
INLINE_LINMATH FLOATNAME(LPoint2) __rmul__(FLOATTYPE scalar) const;
INLINE_LINMATH std::string __repr__() const;
};

View File

@ -46,6 +46,8 @@ PUBLISHED:
INLINE_LINMATH FLOATNAME(LPoint2) operator * (FLOATTYPE scalar) const;
INLINE_LINMATH FLOATNAME(LPoint2) operator / (FLOATTYPE scalar) const;
EXTENSION(INLINE_LINMATH FLOATNAME(LPoint2) __rmul__(FLOATTYPE scalar) const);
#ifndef FLOATTYPE_IS_INT
INLINE_LINMATH FLOATNAME(LPoint2) normalized() const;
INLINE_LINMATH FLOATNAME(LPoint2) project(const FLOATNAME(LVecBase2) &onto) const;

View File

@ -80,3 +80,11 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) {
// Upcall to LVecBase2.
return invoke_extension<FLOATNAME(LVecBase3)>(_this).__setattr__(self, attr_name, assign);
}
/**
*
*/
INLINE_LINMATH FLOATNAME(LPoint3) Extension<FLOATNAME(LPoint3)>::
__rmul__(FLOATTYPE scalar) const {
return *_this * scalar;
}

View File

@ -20,6 +20,9 @@ class Extension<FLOATNAME(LPoint3)> : public ExtensionBase<FLOATNAME(LPoint3)> {
public:
INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const;
INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign);
INLINE_LINMATH FLOATNAME(LPoint3) __rmul__(FLOATTYPE scalar) const;
INLINE_LINMATH std::string __repr__() const;
};

View File

@ -66,6 +66,8 @@ PUBLISHED:
INLINE_LINMATH FLOATNAME(LPoint3) operator * (FLOATTYPE scalar) const;
INLINE_LINMATH FLOATNAME(LPoint3) operator / (FLOATTYPE scalar) const;
EXTENSION(INLINE_LINMATH FLOATNAME(LPoint3) __rmul__(FLOATTYPE scalar) const);
// Some special named constructors for LPoint3.
INLINE_LINMATH static const FLOATNAME(LPoint3) &origin(CoordinateSystem cs = CS_default);

View File

@ -85,3 +85,11 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) {
// Upcall to LVecBase4.
return invoke_extension<FLOATNAME(LVecBase4)>(_this).__setattr__(self, attr_name, assign);
}
/**
*
*/
INLINE_LINMATH FLOATNAME(LPoint4) Extension<FLOATNAME(LPoint4)>::
__rmul__(FLOATTYPE scalar) const {
return *_this * scalar;
}

View File

@ -20,6 +20,9 @@ class Extension<FLOATNAME(LPoint4)> : public ExtensionBase<FLOATNAME(LPoint4)> {
public:
INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const;
INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign);
INLINE_LINMATH FLOATNAME(LPoint4) __rmul__(FLOATTYPE scalar) const;
INLINE_LINMATH std::string __repr__() const;
};

View File

@ -54,6 +54,8 @@ PUBLISHED:
INLINE_LINMATH FLOATNAME(LPoint4) operator * (FLOATTYPE scalar) const;
INLINE_LINMATH FLOATNAME(LPoint4) operator / (FLOATTYPE scalar) const;
EXTENSION(INLINE_LINMATH FLOATNAME(LPoint4) __rmul__(FLOATTYPE scalar) const);
#ifndef FLOATTYPE_IS_INT
INLINE_LINMATH FLOATNAME(LPoint4) normalized() const;
INLINE_LINMATH FLOATNAME(LPoint4) project(const FLOATNAME(LVecBase4) &onto) const;

View File

@ -192,6 +192,25 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) {
return 0;
}
/**
*
*/
INLINE_LINMATH PyObject *Extension<FLOATNAME(LVecBase2)>::
__rmul__(PyObject *self, FLOATTYPE scalar) 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) = _this->_v(0) * scalar;
vec->_v(1) = _this->_v(1) * scalar;
}
return py_vec;
}
/**
*
*/

View File

@ -23,6 +23,8 @@ public:
INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign);
INLINE_LINMATH std::string __repr__() const;
INLINE_LINMATH PyObject *__rmul__(PyObject *self, FLOATTYPE scalar) const;
INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const;
INLINE_LINMATH PyObject *__ifloordiv__(PyObject *self, FLOATTYPE scalar);

View File

@ -133,6 +133,8 @@ PUBLISHED:
INLINE_LINMATH void componentwise_mult(const FLOATNAME(LVecBase2) &other);
EXTENSION(INLINE_LINMATH PyObject *__rmul__(PyObject *self, FLOATTYPE scalar) const);
EXTENSION(INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const);
EXTENSION(INLINE_LINMATH PyObject *__ifloordiv__(PyObject *self, FLOATTYPE scalar));

View File

@ -193,6 +193,27 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) {
return 0;
}
/**
*
*/
INLINE_LINMATH PyObject *Extension<FLOATNAME(LVecBase3)>::
__rmul__(PyObject *self, FLOATTYPE scalar) 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) = _this->_v(0) * scalar;
vec->_v(1) = _this->_v(1) * scalar;
vec->_v(2) = _this->_v(2) * scalar;
}
return py_vec;
}
/**
*
*/

View File

@ -23,6 +23,8 @@ public:
INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign);
INLINE_LINMATH std::string __repr__() const;
INLINE_LINMATH PyObject *__rmul__(PyObject *self, FLOATTYPE scalar) const;
INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const;
INLINE_LINMATH PyObject *__ifloordiv__(PyObject *self, FLOATTYPE scalar);

View File

@ -152,6 +152,8 @@ PUBLISHED:
INLINE_LINMATH void componentwise_mult(const FLOATNAME(LVecBase3) &other);
EXTENSION(INLINE_LINMATH PyObject *__rmul__(PyObject *self, FLOATTYPE scalar) const);
EXTENSION(INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const);
EXTENSION(INLINE_LINMATH PyObject *__ifloordiv__(PyObject *self, FLOATTYPE scalar));

View File

@ -199,6 +199,28 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) {
return 0;
}
/**
*
*/
INLINE_LINMATH PyObject *Extension<FLOATNAME(LVecBase4)>::
__rmul__(PyObject *self, FLOATTYPE scalar) 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) = _this->_v(0) * scalar;
vec->_v(1) = _this->_v(1) * scalar;
vec->_v(2) = _this->_v(2) * scalar;
vec->_v(3) = _this->_v(3) * scalar;
}
return py_vec;
}
/**
*
*/

View File

@ -23,6 +23,8 @@ public:
INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign);
INLINE_LINMATH std::string __repr__() const;
INLINE_LINMATH PyObject *__rmul__(PyObject *self, FLOATTYPE scalar) const;
INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const;
INLINE_LINMATH PyObject *__ifloordiv__(PyObject *self, FLOATTYPE scalar);

View File

@ -160,6 +160,8 @@ PUBLISHED:
INLINE_LINMATH void componentwise_mult(const FLOATNAME(LVecBase4) &other);
EXTENSION(INLINE_LINMATH PyObject *__rmul__(PyObject *self, FLOATTYPE scalar) const);
EXTENSION(INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const);
EXTENSION(INLINE_LINMATH PyObject *__ifloordiv__(PyObject *self, FLOATTYPE scalar));

View File

@ -79,3 +79,11 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) {
// Upcall to LVecBase2.
return invoke_extension<FLOATNAME(LVecBase2)>(_this).__setattr__(self, attr_name, assign);
}
/**
*
*/
INLINE_LINMATH FLOATNAME(LVector2) Extension<FLOATNAME(LVector2)>::
__rmul__(FLOATTYPE scalar) const {
return *_this * scalar;
}

View File

@ -20,6 +20,9 @@ class Extension<FLOATNAME(LVector2)> : public ExtensionBase<FLOATNAME(LVector2)>
public:
INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const;
INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign);
INLINE_LINMATH FLOATNAME(LVector2) __rmul__(FLOATTYPE scalar) const;
INLINE_LINMATH std::string __repr__() const;
};

View File

@ -40,6 +40,8 @@ PUBLISHED:
INLINE_LINMATH FLOATNAME(LVector2) operator * (FLOATTYPE scalar) const;
INLINE_LINMATH FLOATNAME(LVector2) operator / (FLOATTYPE scalar) const;
EXTENSION(INLINE_LINMATH FLOATNAME(LVector2) __rmul__(FLOATTYPE scalar) const);
#ifndef FLOATTYPE_IS_INT
INLINE_LINMATH FLOATNAME(LVector2) normalized() const;
INLINE_LINMATH FLOATNAME(LVector2) project(const FLOATNAME(LVecBase2) &onto) const;

View File

@ -80,3 +80,11 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) {
// Upcall to LVecBase3.
return invoke_extension<FLOATNAME(LVecBase3)>(_this).__setattr__(self, attr_name, assign);
}
/**
*
*/
INLINE_LINMATH FLOATNAME(LVector3) Extension<FLOATNAME(LVector3)>::
__rmul__(FLOATTYPE scalar) const {
return *_this * scalar;
}

View File

@ -20,6 +20,9 @@ class Extension<FLOATNAME(LVector3)> : public ExtensionBase<FLOATNAME(LVector3)>
public:
INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const;
INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign);
INLINE_LINMATH FLOATNAME(LVector3) __rmul__(FLOATTYPE scalar) const;
INLINE_LINMATH std::string __repr__() const;
};

View File

@ -71,6 +71,8 @@ PUBLISHED:
INLINE_LINMATH FLOATNAME(LVector3) operator * (FLOATTYPE scalar) const;
INLINE_LINMATH FLOATNAME(LVector3) operator / (FLOATTYPE scalar) const;
EXTENSION(INLINE_LINMATH FLOATNAME(LVector3) __rmul__(FLOATTYPE scalar) const);
// Some special named constructors for LVector3.
INLINE_LINMATH static FLOATNAME(LVector3) up(CoordinateSystem cs = CS_default);

View File

@ -85,3 +85,11 @@ __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign) {
// Upcall to LVecBase4.
return invoke_extension<FLOATNAME(LVecBase4)>(_this).__setattr__(self, attr_name, assign);
}
/**
*
*/
INLINE_LINMATH FLOATNAME(LVector4) Extension<FLOATNAME(LVector4)>::
__rmul__(FLOATTYPE scalar) const {
return *_this * scalar;
}

View File

@ -20,6 +20,9 @@ class Extension<FLOATNAME(LVector4)> : public ExtensionBase<FLOATNAME(LVector4)>
public:
INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const;
INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign);
INLINE_LINMATH FLOATNAME(LVector4) __rmul__(FLOATTYPE scalar) const;
INLINE_LINMATH std::string __repr__() const;
};

View File

@ -48,6 +48,8 @@ PUBLISHED:
INLINE_LINMATH FLOATNAME(LVector4) operator * (FLOATTYPE scalar) const;
INLINE_LINMATH FLOATNAME(LVector4) operator / (FLOATTYPE scalar) const;
EXTENSION(INLINE_LINMATH FLOATNAME(LVector4) __rmul__(FLOATTYPE scalar) const);
#ifndef FLOATTYPE_IS_INT
INLINE_LINMATH FLOATNAME(LVector4) normalized() const;
INLINE_LINMATH FLOATNAME(LVector4) project(const FLOATNAME(LVecBase4) &onto) const;

View File

@ -120,6 +120,10 @@ def test_vec2_ceil():
assert rounded_vector.y == -2
def test_vec2_rmul():
assert 2 * Vec2(3, -4) == Vec2(6, -8)
@pytest.mark.parametrize("type", (core.LVecBase2f, core.LVecBase2d, core.LVecBase2i))
def test_vec2_floordiv(type):
with pytest.raises(ZeroDivisionError):

View File

@ -105,6 +105,10 @@ def test_vec3_ceil():
assert rounded_vector.z == 4
def test_vec3_rmul():
assert 2 * Vec3(0, 3, -4) == Vec3(0, 6, -8)
@pytest.mark.parametrize("type", (core.LVecBase3f, core.LVecBase3d, core.LVecBase3i))
def test_vec3_floordiv(type):
with pytest.raises(ZeroDivisionError):

View File

@ -121,6 +121,10 @@ def test_vec4_ceil():
assert rounded_vector.w == 1
def test_vec4_rmul():
assert 2 * Vec4(0, 3, -4, 0.5) == Vec4(0, 6, -8, 1)
@pytest.mark.parametrize("type", (core.LVecBase4f, core.LVecBase4d, core.LVecBase4i))
def test_vec4_floordiv(type):
with pytest.raises(ZeroDivisionError):