| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- #include "pocketpy/linalg.h"
- namespace pkpy{
- #define BIND_VEC_VEC_OP(D, name, op) \
- vm->bind_method<1>(type, #name, [](VM* vm, ArgsView args){ \
- PyVec##D& self = _CAST(PyVec##D&, args[0]); \
- PyVec##D& other = CAST(PyVec##D&, args[1]); \
- return VAR(self op other); \
- });
- #define BIND_VEC_FLOAT_OP(D, name, op) \
- vm->bind_method<1>(type, #name, [](VM* vm, ArgsView args){ \
- PyVec##D& self = _CAST(PyVec##D&, args[0]); \
- f64 other = CAST(f64, args[1]); \
- return VAR(self op other); \
- });
- #define BIND_VEC_FUNCTION_0(D, name) \
- vm->bind_method<0>(type, #name, [](VM* vm, ArgsView args){ \
- PyVec##D& self = _CAST(PyVec##D&, args[0]); \
- return VAR(self.name()); \
- });
- #define BIND_VEC_FUNCTION_1(D, name) \
- vm->bind_method<1>(type, #name, [](VM* vm, ArgsView args){ \
- PyVec##D& self = _CAST(PyVec##D&, args[0]); \
- PyVec##D& other = CAST(PyVec##D&, args[1]); \
- return VAR(self.name(other)); \
- });
- #define BIND_VEC_FIELD(D, name) \
- vm->bind_property(type, #name, \
- [](VM* vm, ArgsView args){ \
- PyVec##D& self = _CAST(PyVec##D&, args[0]); \
- return VAR(self.name); \
- }, [](VM* vm, ArgsView args){ \
- PyVec##D& self = _CAST(PyVec##D&, args[0]); \
- self.name = CAST(f64, args[1]); \
- return vm->None; \
- });
- void PyVec2::_register(VM* vm, PyObject* mod, PyObject* type){
- PY_STRUCT_LIKE(PyVec2)
- vm->bind_constructor<3>(type, [](VM* vm, ArgsView args){
- float x = CAST_F(args[1]);
- float y = CAST_F(args[2]);
- return VAR(Vec2(x, y));
- });
- vm->bind_method<0>(type, "__getnewargs__", [](VM* vm, ArgsView args){
- PyVec2& self = _CAST(PyVec2&, args[0]);
- return VAR(Tuple({ VAR(self.x), VAR(self.y) }));
- });
- vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
- PyVec2& self = _CAST(PyVec2&, obj);
- SStream ss;
- ss << "vec2(" << self.x << ", " << self.y << ")";
- return VAR(ss.str());
- });
- vm->bind_method<1>(type, "rotate", [](VM* vm, ArgsView args){
- Vec2 self = _CAST(PyVec2&, args[0]);
- float radian = CAST(f64, args[1]);
- float cr = cosf(radian);
- float sr = sinf(radian);
- Mat3x3 rotate(cr, -sr, 0.0f,
- sr, cr, 0.0f,
- 0.0f, 0.0f, 1.0f);
- self = rotate.transform_vector(self);
- return VAR(self);
- });
- vm->bind_method<1>(type, "rotate_", [](VM* vm, ArgsView args){
- Vec2& self = _CAST(PyVec2&, args[0]);
- float radian = CAST(f64, args[1]);
- float cr = cosf(radian);
- float sr = sinf(radian);
- Mat3x3 rotate(cr, -sr, 0.0f,
- sr, cr, 0.0f,
- 0.0f, 0.0f, 1.0f);
- self = rotate.transform_vector(self);
- return vm->None;
- });
- BIND_VEC_VEC_OP(2, __add__, +)
- BIND_VEC_VEC_OP(2, __sub__, -)
- BIND_VEC_FLOAT_OP(2, __mul__, *)
- BIND_VEC_FLOAT_OP(2, __rmul__, *)
- BIND_VEC_FLOAT_OP(2, __truediv__, /)
- BIND_VEC_FIELD(2, x)
- BIND_VEC_FIELD(2, y)
- BIND_VEC_FUNCTION_1(2, dot)
- BIND_VEC_FUNCTION_1(2, cross)
- BIND_VEC_FUNCTION_0(2, length)
- BIND_VEC_FUNCTION_0(2, length_squared)
- BIND_VEC_FUNCTION_0(2, normalize)
- }
- void PyVec3::_register(VM* vm, PyObject* mod, PyObject* type){
- PY_STRUCT_LIKE(PyVec3)
- vm->bind_constructor<4>(type, [](VM* vm, ArgsView args){
- float x = CAST_F(args[1]);
- float y = CAST_F(args[2]);
- float z = CAST_F(args[3]);
- return VAR(Vec3(x, y, z));
- });
- vm->bind_method<0>(type, "__getnewargs__", [](VM* vm, ArgsView args){
- PyVec3& self = _CAST(PyVec3&, args[0]);
- return VAR(Tuple({ VAR(self.x), VAR(self.y), VAR(self.z) }));
- });
- vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
- PyVec3& self = _CAST(PyVec3&, obj);
- SStream ss;
- ss << "vec3(" << self.x << ", " << self.y << ", " << self.z << ")";
- return VAR(ss.str());
- });
- BIND_VEC_VEC_OP(3, __add__, +)
- BIND_VEC_VEC_OP(3, __sub__, -)
- BIND_VEC_FLOAT_OP(3, __mul__, *)
- BIND_VEC_FLOAT_OP(3, __rmul__, *)
- BIND_VEC_FLOAT_OP(3, __truediv__, /)
- BIND_VEC_FIELD(3, x)
- BIND_VEC_FIELD(3, y)
- BIND_VEC_FIELD(3, z)
- BIND_VEC_FUNCTION_1(3, dot)
- BIND_VEC_FUNCTION_1(3, cross)
- BIND_VEC_FUNCTION_0(3, length)
- BIND_VEC_FUNCTION_0(3, length_squared)
- BIND_VEC_FUNCTION_0(3, normalize)
- }
- void PyVec4::_register(VM* vm, PyObject* mod, PyObject* type){
- PY_STRUCT_LIKE(PyVec4)
- vm->bind_constructor<1+4>(type, [](VM* vm, ArgsView args){
- float x = CAST_F(args[1]);
- float y = CAST_F(args[2]);
- float z = CAST_F(args[3]);
- float w = CAST_F(args[4]);
- return VAR(Vec4(x, y, z, w));
- });
- vm->bind_method<0>(type, "__getnewargs__", [](VM* vm, ArgsView args){
- PyVec4& self = _CAST(PyVec4&, args[0]);
- return VAR(Tuple({ VAR(self.x), VAR(self.y), VAR(self.z), VAR(self.w) }));
- });
- vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
- PyVec4& self = _CAST(PyVec4&, obj);
- SStream ss;
- ss << "vec4(" << self.x << ", " << self.y << ", " << self.z << ", " << self.w << ")";
- return VAR(ss.str());
- });
- BIND_VEC_VEC_OP(4, __add__, +)
- BIND_VEC_VEC_OP(4, __sub__, -)
- BIND_VEC_FLOAT_OP(4, __mul__, *)
- BIND_VEC_FLOAT_OP(4, __rmul__, *)
- BIND_VEC_FLOAT_OP(4, __truediv__, /)
- BIND_VEC_FIELD(4, x)
- BIND_VEC_FIELD(4, y)
- BIND_VEC_FIELD(4, z)
- BIND_VEC_FIELD(4, w)
- BIND_VEC_FUNCTION_1(4, dot)
- BIND_VEC_FUNCTION_0(4, length)
- BIND_VEC_FUNCTION_0(4, length_squared)
- BIND_VEC_FUNCTION_0(4, normalize)
- }
- #undef BIND_VEC_ADDR
- #undef BIND_VEC_VEC_OP
- #undef BIND_VEC_FLOAT_OP
- #undef BIND_VEC_FIELD
- #undef BIND_VEC_FUNCTION_0
- #undef BIND_VEC_FUNCTION_1
- void PyMat3x3::_register(VM* vm, PyObject* mod, PyObject* type){
- PY_STRUCT_LIKE(PyMat3x3)
- vm->bind_constructor<-1>(type, [](VM* vm, ArgsView args){
- if(args.size() == 1+0) return VAR_T(PyMat3x3, Mat3x3::zeros());
- if(args.size() == 1+9){
- Mat3x3 mat;
- for(int i=0; i<9; i++) mat.v[i] = CAST_F(args[1+i]);
- return VAR_T(PyMat3x3, mat);
- }
- if(args.size() == 1+1){
- List& a = CAST(List&, args[1]);
- if(a.size() != 3) vm->ValueError("Mat3x3.__new__ takes 3x3 list");
- Mat3x3 mat;
- for(int i=0; i<3; i++){
- List& b = CAST(List&, a[i]);
- if(b.size() != 3) vm->ValueError("Mat3x3.__new__ takes 3x3 list");
- for(int j=0; j<3; j++){
- mat.m[i][j] = CAST_F(b[j]);
- }
- }
- return VAR_T(PyMat3x3, mat);
- }
- vm->TypeError(fmt("Mat3x3.__new__ takes 0 or 1 or 9 arguments, got ", args.size()-1));
- return vm->None;
- });
- vm->bind_method<0>(type, "__getnewargs__", [](VM* vm, ArgsView args){
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
- Tuple t(9);
- for(int i=0; i<9; i++) t[i] = VAR(self.v[i]);
- return VAR(std::move(t));
- });
- #define METHOD_PROXY_NONE(name) \
- vm->bind_method<0>(type, #name, [](VM* vm, ArgsView args){ \
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]); \
- self.name(); \
- return vm->None; \
- });
- METHOD_PROXY_NONE(set_zeros)
- METHOD_PROXY_NONE(set_ones)
- METHOD_PROXY_NONE(set_identity)
- #undef METHOD_PROXY_NONE
- vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
- PyMat3x3& self = _CAST(PyMat3x3&, obj);
- std::stringstream ss;
- ss << std::fixed << std::setprecision(4);
- ss << "mat3x3([[" << self._11 << ", " << self._12 << ", " << self._13 << "],\n";
- ss << " [" << self._21 << ", " << self._22 << ", " << self._23 << "],\n";
- ss << " [" << self._31 << ", " << self._32 << ", " << self._33 << "]])";
- return VAR(ss.str());
- });
- vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj, PyObject* index){
- PyMat3x3& self = _CAST(PyMat3x3&, obj);
- Tuple& t = CAST(Tuple&, index);
- if(t.size() != 2){
- vm->TypeError("Mat3x3.__getitem__ takes a tuple of 2 integers");
- return vm->None;
- }
- i64 i = CAST(i64, t[0]);
- i64 j = CAST(i64, t[1]);
- if(i < 0 || i >= 3 || j < 0 || j >= 3){
- vm->IndexError("index out of range");
- return vm->None;
- }
- return VAR(self.m[i][j]);
- });
- vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj, PyObject* index, PyObject* value){
- PyMat3x3& self = _CAST(PyMat3x3&, obj);
- Tuple& t = CAST(Tuple&, index);
- if(t.size() != 2){
- vm->TypeError("Mat3x3.__setitem__ takes a tuple of 2 integers");
- return;
- }
- i64 i = CAST(i64, t[0]);
- i64 j = CAST(i64, t[1]);
- if(i < 0 || i >= 3 || j < 0 || j >= 3){
- vm->IndexError("index out of range");
- return;
- }
- self.m[i][j] = CAST_F(value);
- });
- #define PROPERTY_FIELD(field) \
- vm->bind_property(type, #field ": float", \
- [](VM* vm, ArgsView args){ \
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]); \
- return VAR(self.field); \
- }, [](VM* vm, ArgsView args){ \
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]); \
- self.field = CAST(f64, args[1]); \
- return vm->None; \
- });
- PROPERTY_FIELD(_11)
- PROPERTY_FIELD(_12)
- PROPERTY_FIELD(_13)
- PROPERTY_FIELD(_21)
- PROPERTY_FIELD(_22)
- PROPERTY_FIELD(_23)
- PROPERTY_FIELD(_31)
- PROPERTY_FIELD(_32)
- PROPERTY_FIELD(_33)
- #undef PROPERTY_FIELD
- vm->bind__add__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
- PyMat3x3& self = _CAST(PyMat3x3&, _0);
- PyMat3x3& other = CAST(PyMat3x3&, _1);
- return VAR_T(PyMat3x3, self + other);
- });
- vm->bind__sub__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
- PyMat3x3& self = _CAST(PyMat3x3&, _0);
- PyMat3x3& other = CAST(PyMat3x3&, _1);
- return VAR_T(PyMat3x3, self - other);
- });
- vm->bind__mul__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
- PyMat3x3& self = _CAST(PyMat3x3&, _0);
- f64 other = CAST_F(_1);
- return VAR_T(PyMat3x3, self * other);
- });
- vm->bind_method<1>(type, "__rmul__", [](VM* vm, ArgsView args){
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
- f64 other = CAST_F(args[1]);
- return VAR_T(PyMat3x3, self * other);
- });
- vm->bind__truediv__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
- PyMat3x3& self = _CAST(PyMat3x3&, _0);
- f64 other = CAST_F(_1);
- return VAR_T(PyMat3x3, self / other);
- });
- vm->bind__matmul__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
- PyMat3x3& self = _CAST(PyMat3x3&, _0);
- if(is_non_tagged_type(_1, PyMat3x3::_type(vm))){
- PyMat3x3& other = _CAST(PyMat3x3&, _1);
- return VAR_T(PyMat3x3, self.matmul(other));
- }
- if(is_non_tagged_type(_1, PyVec3::_type(vm))){
- PyVec3& other = _CAST(PyVec3&, _1);
- return VAR_T(PyVec3, self.matmul(other));
- }
- return vm->NotImplemented;
- });
- vm->bind_method<0>(type, "determinant", [](VM* vm, ArgsView args){
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
- return VAR(self.determinant());
- });
- vm->bind_method<0>(type, "transpose", [](VM* vm, ArgsView args){
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
- return VAR_T(PyMat3x3, self.transpose());
- });
- vm->bind__invert__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
- PyMat3x3& self = _CAST(PyMat3x3&, obj);
- Mat3x3 ret;
- bool ok = self.inverse(ret);
- if(!ok) vm->ValueError("matrix is not invertible");
- return VAR_T(PyMat3x3, ret);
- });
- vm->bind_func<0>(type, "zeros", [](VM* vm, ArgsView args){
- PK_UNUSED(args);
- return VAR_T(PyMat3x3, Mat3x3::zeros());
- });
- vm->bind_func<0>(type, "ones", [](VM* vm, ArgsView args){
- PK_UNUSED(args);
- return VAR_T(PyMat3x3, Mat3x3::ones());
- });
- vm->bind_func<0>(type, "identity", [](VM* vm, ArgsView args){
- PK_UNUSED(args);
- return VAR_T(PyMat3x3, Mat3x3::identity());
- });
- /*************** affine transformations ***************/
- vm->bind_func<3>(type, "trs", [](VM* vm, ArgsView args){
- PyVec2& t = CAST(PyVec2&, args[0]);
- f64 r = CAST_F(args[1]);
- PyVec2& s = CAST(PyVec2&, args[2]);
- return VAR_T(PyMat3x3, Mat3x3::trs(t, r, s));
- });
- vm->bind_method<0>(type, "is_affine", [](VM* vm, ArgsView args){
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
- return VAR(self.is_affine());
- });
- vm->bind_method<0>(type, "_t", [](VM* vm, ArgsView args){
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
- return VAR_T(PyVec2, self._t());
- });
- vm->bind_method<0>(type, "_r", [](VM* vm, ArgsView args){
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
- return VAR(self._r());
- });
- vm->bind_method<0>(type, "_s", [](VM* vm, ArgsView args){
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
- return VAR_T(PyVec2, self._s());
- });
- vm->bind_method<1>(type, "transform_point", [](VM* vm, ArgsView args){
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
- PyVec2& v = CAST(PyVec2&, args[1]);
- return VAR_T(PyVec2, self.transform_point(v));
- });
- vm->bind_method<1>(type, "transform_vector", [](VM* vm, ArgsView args){
- PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
- PyVec2& v = CAST(PyVec2&, args[1]);
- return VAR_T(PyVec2, self.transform_vector(v));
- });
- }
- void add_module_linalg(VM* vm){
- PyObject* linalg = vm->new_module("linalg");
- PyVec2::register_class(vm, linalg);
- PyVec3::register_class(vm, linalg);
- PyVec4::register_class(vm, linalg);
- PyMat3x3::register_class(vm, linalg);
- PyObject* float_p = vm->_modules["c"]->attr("float_p");
- linalg->attr().set("vec2_p", float_p);
- linalg->attr().set("vec3_p", float_p);
- linalg->attr().set("vec4_p", float_p);
- linalg->attr().set("mat3x3_p", float_p);
- }
- } // namespace pkpy
|