linalg.h 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. #pragma once
  2. #include <cmath>
  3. #include "cffi.h"
  4. namespace pkpy{
  5. static constexpr float kEpsilon = 1e-4f;
  6. inline static bool isclose(float a, float b){ return fabsf(a - b) < kEpsilon; }
  7. struct Vec2{
  8. float x, y;
  9. Vec2() : x(0.0f), y(0.0f) {}
  10. Vec2(float x, float y) : x(x), y(y) {}
  11. Vec2(const Vec2& v) : x(v.x), y(v.y) {}
  12. Vec2 operator+(const Vec2& v) const { return Vec2(x + v.x, y + v.y); }
  13. Vec2& operator+=(const Vec2& v) { x += v.x; y += v.y; return *this; }
  14. Vec2 operator-(const Vec2& v) const { return Vec2(x - v.x, y - v.y); }
  15. Vec2& operator-=(const Vec2& v) { x -= v.x; y -= v.y; return *this; }
  16. Vec2 operator*(float s) const { return Vec2(x * s, y * s); }
  17. Vec2& operator*=(float s) { x *= s; y *= s; return *this; }
  18. Vec2 operator/(float s) const { return Vec2(x / s, y / s); }
  19. Vec2& operator/=(float s) { x /= s; y /= s; return *this; }
  20. Vec2 operator-() const { return Vec2(-x, -y); }
  21. bool operator==(const Vec2& v) const { return isclose(x, v.x) && isclose(y, v.y); }
  22. bool operator!=(const Vec2& v) const { return !isclose(x, v.x) || !isclose(y, v.y); }
  23. float dot(const Vec2& v) const { return x * v.x + y * v.y; }
  24. float cross(const Vec2& v) const { return x * v.y - y * v.x; }
  25. float length() const { return sqrtf(x * x + y * y); }
  26. float length_squared() const { return x * x + y * y; }
  27. Vec2 normalize() const { float l = length(); return Vec2(x / l, y / l); }
  28. };
  29. struct Vec3{
  30. float x, y, z;
  31. Vec3() : x(0.0f), y(0.0f), z(0.0f) {}
  32. Vec3(float x, float y, float z) : x(x), y(y), z(z) {}
  33. Vec3(const Vec3& v) : x(v.x), y(v.y), z(v.z) {}
  34. Vec3 operator+(const Vec3& v) const { return Vec3(x + v.x, y + v.y, z + v.z); }
  35. Vec3& operator+=(const Vec3& v) { x += v.x; y += v.y; z += v.z; return *this; }
  36. Vec3 operator-(const Vec3& v) const { return Vec3(x - v.x, y - v.y, z - v.z); }
  37. Vec3& operator-=(const Vec3& v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
  38. Vec3 operator*(float s) const { return Vec3(x * s, y * s, z * s); }
  39. Vec3& operator*=(float s) { x *= s; y *= s; z *= s; return *this; }
  40. Vec3 operator/(float s) const { return Vec3(x / s, y / s, z / s); }
  41. Vec3& operator/=(float s) { x /= s; y /= s; z /= s; return *this; }
  42. Vec3 operator-() const { return Vec3(-x, -y, -z); }
  43. bool operator==(const Vec3& v) const { return isclose(x, v.x) && isclose(y, v.y) && isclose(z, v.z); }
  44. bool operator!=(const Vec3& v) const { return !isclose(x, v.x) || !isclose(y, v.y) || !isclose(z, v.z); }
  45. float dot(const Vec3& v) const { return x * v.x + y * v.y + z * v.z; }
  46. Vec3 cross(const Vec3& v) const { return Vec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); }
  47. float length() const { return sqrtf(x * x + y * y + z * z); }
  48. float length_squared() const { return x * x + y * y + z * z; }
  49. Vec3 normalize() const { float l = length(); return Vec3(x / l, y / l, z / l); }
  50. };
  51. struct Mat3x3{
  52. union {
  53. struct {
  54. float _11, _12, _13;
  55. float _21, _22, _23;
  56. float _31, _32, _33;
  57. };
  58. float m[3][3];
  59. float v[9];
  60. };
  61. Mat3x3() {}
  62. Mat3x3(float _11, float _12, float _13,
  63. float _21, float _22, float _23,
  64. float _31, float _32, float _33)
  65. : _11(_11), _12(_12), _13(_13)
  66. , _21(_21), _22(_22), _23(_23)
  67. , _31(_31), _32(_32), _33(_33) {}
  68. void set_zeros(){ for (int i=0; i<9; ++i) v[i] = 0.0f; }
  69. void set_ones(){ for (int i=0; i<9; ++i) v[i] = 1.0f; }
  70. void set_identity(){ set_zeros(); _11 = _22 = _33 = 1.0f; }
  71. static Mat3x3 zeros(){
  72. static Mat3x3 ret(0, 0, 0, 0, 0, 0, 0, 0, 0);
  73. return ret;
  74. }
  75. static Mat3x3 ones(){
  76. static Mat3x3 ret(1, 1, 1, 1, 1, 1, 1, 1, 1);
  77. return ret;
  78. }
  79. static Mat3x3 identity(){
  80. static Mat3x3 ret(1, 0, 0, 0, 1, 0, 0, 0, 1);
  81. return ret;
  82. }
  83. Mat3x3 operator+(const Mat3x3& other) const{
  84. Mat3x3 ret;
  85. for (int i=0; i<9; ++i) ret.v[i] = v[i] + other.v[i];
  86. return ret;
  87. }
  88. Mat3x3 operator-(const Mat3x3& other) const{
  89. Mat3x3 ret;
  90. for (int i=0; i<9; ++i) ret.v[i] = v[i] - other.v[i];
  91. return ret;
  92. }
  93. Mat3x3 operator*(float scalar) const{
  94. Mat3x3 ret;
  95. for (int i=0; i<9; ++i) ret.v[i] = v[i] * scalar;
  96. return ret;
  97. }
  98. Mat3x3 operator/(float scalar) const{
  99. Mat3x3 ret;
  100. for (int i=0; i<9; ++i) ret.v[i] = v[i] / scalar;
  101. return ret;
  102. }
  103. Mat3x3& operator+=(const Mat3x3& other){
  104. for (int i=0; i<9; ++i) v[i] += other.v[i];
  105. return *this;
  106. }
  107. Mat3x3& operator-=(const Mat3x3& other){
  108. for (int i=0; i<9; ++i) v[i] -= other.v[i];
  109. return *this;
  110. }
  111. Mat3x3& operator*=(float scalar){
  112. for (int i=0; i<9; ++i) v[i] *= scalar;
  113. return *this;
  114. }
  115. Mat3x3& operator/=(float scalar){
  116. for (int i=0; i<9; ++i) v[i] /= scalar;
  117. return *this;
  118. }
  119. Mat3x3 matmul(const Mat3x3& other) const{
  120. Mat3x3 ret;
  121. ret._11 = _11 * other._11 + _12 * other._21 + _13 * other._31;
  122. ret._12 = _11 * other._12 + _12 * other._22 + _13 * other._32;
  123. ret._13 = _11 * other._13 + _12 * other._23 + _13 * other._33;
  124. ret._21 = _21 * other._11 + _22 * other._21 + _23 * other._31;
  125. ret._22 = _21 * other._12 + _22 * other._22 + _23 * other._32;
  126. ret._23 = _21 * other._13 + _22 * other._23 + _23 * other._33;
  127. ret._31 = _31 * other._11 + _32 * other._21 + _33 * other._31;
  128. ret._32 = _31 * other._12 + _32 * other._22 + _33 * other._32;
  129. ret._33 = _31 * other._13 + _32 * other._23 + _33 * other._33;
  130. return ret;
  131. }
  132. Vec3 matmul(const Vec3& other) const{
  133. Vec3 ret;
  134. ret.x = _11 * other.x + _12 * other.y + _13 * other.z;
  135. ret.y = _21 * other.x + _22 * other.y + _23 * other.z;
  136. ret.z = _31 * other.x + _32 * other.y + _33 * other.z;
  137. return ret;
  138. }
  139. bool operator==(const Mat3x3& other) const{
  140. for (int i=0; i<9; ++i){
  141. if (!isclose(v[i], other.v[i])) return false;
  142. }
  143. return true;
  144. }
  145. bool operator!=(const Mat3x3& other) const{
  146. for (int i=0; i<9; ++i){
  147. if (!isclose(v[i], other.v[i])) return true;
  148. }
  149. return false;
  150. }
  151. float determinant() const{
  152. return _11 * _22 * _33 + _12 * _23 * _31 + _13 * _21 * _32
  153. - _11 * _23 * _32 - _12 * _21 * _33 - _13 * _22 * _31;
  154. }
  155. Mat3x3 transpose() const{
  156. Mat3x3 ret;
  157. ret._11 = _11; ret._12 = _21; ret._13 = _31;
  158. ret._21 = _12; ret._22 = _22; ret._23 = _32;
  159. ret._31 = _13; ret._32 = _23; ret._33 = _33;
  160. return ret;
  161. }
  162. bool inverse(Mat3x3& ret) const{
  163. float det = determinant();
  164. if (fabsf(det) < kEpsilon) return false;
  165. float inv_det = 1.0f / det;
  166. ret._11 = (_22 * _33 - _23 * _32) * inv_det;
  167. ret._12 = (_13 * _32 - _12 * _33) * inv_det;
  168. ret._13 = (_12 * _23 - _13 * _22) * inv_det;
  169. ret._21 = (_23 * _31 - _21 * _33) * inv_det;
  170. ret._22 = (_11 * _33 - _13 * _31) * inv_det;
  171. ret._23 = (_13 * _21 - _11 * _23) * inv_det;
  172. ret._31 = (_21 * _32 - _22 * _31) * inv_det;
  173. ret._32 = (_12 * _31 - _11 * _32) * inv_det;
  174. ret._33 = (_11 * _22 - _12 * _21) * inv_det;
  175. return true;
  176. }
  177. /*************** affine transformations ***************/
  178. static Mat3x3 translate(Vec2 v){
  179. return Mat3x3(1.0f, 0.0f, v.x,
  180. 0.0f, 1.0f, v.y,
  181. 0.0f, 0.0f, 1.0f);
  182. }
  183. static Mat3x3 rotate(float radian){
  184. float cr = cosf(radian);
  185. float sr = sinf(radian);
  186. return Mat3x3(cr, -sr, 0.0f,
  187. sr, cr, 0.0f,
  188. 0.0f, 0.0f, 1.0f);
  189. }
  190. static Mat3x3 scale(Vec2 s){
  191. return Mat3x3(s.x, 0.0f, 0.0f,
  192. 0.0f, s.y, 0.0f,
  193. 0.0f, 0.0f, 1.0f);
  194. }
  195. static Mat3x3 trs(Vec2 t, float radian, Vec2 s){
  196. float cr = cosf(radian);
  197. float sr = sinf(radian);
  198. return Mat3x3(s.x * cr, -s.y * sr, t.x,
  199. s.x * sr, s.y * cr, t.y,
  200. 0.0f, 0.0f, 1.0f);
  201. }
  202. bool is_affine() const{
  203. float det = _11 * _22 - _12 * _21;
  204. if(fabsf(det) < kEpsilon) return false;
  205. return _31 == 0.0f && _32 == 0.0f && _33 == 1.0f;
  206. }
  207. Mat3x3 inverse_affine() const{
  208. Mat3x3 ret;
  209. float det = _11 * _22 - _12 * _21;
  210. float inv_det = 1.0f / det;
  211. ret._11 = _22 * inv_det;
  212. ret._12 = -_12 * inv_det;
  213. ret._13 = (_12 * _23 - _13 * _22) * inv_det;
  214. ret._21 = -_21 * inv_det;
  215. ret._22 = _11 * inv_det;
  216. ret._23 = (_13 * _21 - _11 * _23) * inv_det;
  217. ret._31 = 0.0f;
  218. ret._32 = 0.0f;
  219. ret._33 = 1.0f;
  220. return ret;
  221. }
  222. Mat3x3 matmul_affine(const Mat3x3& other) const{
  223. Mat3x3 ret;
  224. ret._11 = _11 * other._11 + _12 * other._21;
  225. ret._12 = _11 * other._12 + _12 * other._22;
  226. ret._13 = _11 * other._13 + _12 * other._23 + _13;
  227. ret._21 = _21 * other._11 + _22 * other._21;
  228. ret._22 = _21 * other._12 + _22 * other._22;
  229. ret._23 = _21 * other._13 + _22 * other._23 + _23;
  230. ret._31 = 0.0f;
  231. ret._32 = 0.0f;
  232. ret._33 = 1.0f;
  233. return ret;
  234. }
  235. Vec2 translation() const { return Vec2(_13, _23); }
  236. float rotation() const { return atan2f(_21, _11); }
  237. Vec2 scale() const {
  238. return Vec2(
  239. sqrtf(_11 * _11 + _21 * _21),
  240. sqrtf(_12 * _12 + _22 * _22)
  241. );
  242. }
  243. Vec2 transform_point(Vec2 v) const {
  244. return Vec2(_11 * v.x + _12 * v.y + _13, _21 * v.x + _22 * v.y + _23);
  245. }
  246. Vec2 transform_vector(Vec2 v) const {
  247. return Vec2(_11 * v.x + _12 * v.y, _21 * v.x + _22 * v.y);
  248. }
  249. };
  250. struct PyVec2;
  251. struct PyVec3;
  252. struct PyMat3x3;
  253. PyObject* py_var(VM*, Vec2);
  254. PyObject* py_var(VM*, const PyVec2&);
  255. PyObject* py_var(VM*, Vec3);
  256. PyObject* py_var(VM*, const PyVec3&);
  257. PyObject* py_var(VM*, const Mat3x3&);
  258. PyObject* py_var(VM*, const PyMat3x3&);
  259. #define BIND_VEC_VEC_OP(D, name, op) \
  260. vm->bind_method<1>(type, #name, [](VM* vm, ArgsView args){ \
  261. PyVec##D& self = _CAST(PyVec##D&, args[0]); \
  262. PyVec##D& other = CAST(PyVec##D&, args[1]); \
  263. return VAR(self op other); \
  264. });
  265. #define BIND_VEC_FLOAT_OP(D, name, op) \
  266. vm->bind_method<1>(type, #name, [](VM* vm, ArgsView args){ \
  267. PyVec##D& self = _CAST(PyVec##D&, args[0]); \
  268. f64 other = vm->num_to_float(args[1]); \
  269. return VAR(self op other); \
  270. });
  271. #define BIND_VEC_FUNCTION_0(D, name) \
  272. vm->bind_method<0>(type, #name, [](VM* vm, ArgsView args){ \
  273. PyVec##D& self = _CAST(PyVec##D&, args[0]); \
  274. return VAR(self.name()); \
  275. });
  276. #define BIND_VEC_FUNCTION_1(D, name) \
  277. vm->bind_method<0>(type, #name, [](VM* vm, ArgsView args){ \
  278. PyVec##D& self = _CAST(PyVec##D&, args[0]); \
  279. PyVec##D& other = CAST(PyVec##D&, args[1]); \
  280. return VAR(self.name(other)); \
  281. });
  282. #define BIND_VEC_FIELD(D, name) \
  283. type->attr().set(#name, vm->property([](VM* vm, ArgsView args){ \
  284. PyVec##D& self = _CAST(PyVec##D&, args[0]); \
  285. return VAR(self.name); \
  286. }, [](VM* vm, ArgsView args){ \
  287. PyVec##D& self = _CAST(PyVec##D&, args[0]); \
  288. self.name = vm->num_to_float(args[1]); \
  289. return vm->None; \
  290. }));
  291. struct PyVec2: Vec2 {
  292. PY_CLASS(PyVec2, linalg, vec2)
  293. PyVec2() : Vec2() {}
  294. PyVec2(const Vec2& v) : Vec2(v) {}
  295. PyVec2(const PyVec2& v) : Vec2(v) {}
  296. static void _register(VM* vm, PyObject* mod, PyObject* type){
  297. vm->bind_constructor<3>(type, [](VM* vm, ArgsView args){
  298. float x = VAR_F(args[1]);
  299. float y = VAR_F(args[2]);
  300. return VAR(Vec2(x, y));
  301. });
  302. vm->bind__repr__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
  303. PyVec2& self = _CAST(PyVec2&, obj);
  304. std::stringstream ss;
  305. ss << "vec2(" << self.x << ", " << self.y << ")";
  306. return VAR(ss.str());
  307. });
  308. vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){
  309. PyVec2& self = _CAST(PyVec2&, args[0]);
  310. return VAR_T(PyVec2, self);
  311. });
  312. vm->bind_method<1>(type, "rotate", [](VM* vm, ArgsView args){
  313. Vec2 self = _CAST(PyVec2&, args[0]);
  314. float radian = vm->num_to_float(args[1]);
  315. self = Mat3x3::rotate(radian).transform_vector(self);
  316. return VAR(self);
  317. });
  318. BIND_VEC_VEC_OP(2, __add__, +)
  319. BIND_VEC_VEC_OP(2, __sub__, -)
  320. BIND_VEC_FLOAT_OP(2, __mul__, *)
  321. BIND_VEC_FLOAT_OP(2, __truediv__, /)
  322. BIND_VEC_VEC_OP(2, __eq__, ==)
  323. BIND_VEC_VEC_OP(2, __ne__, !=)
  324. BIND_VEC_FIELD(2, x)
  325. BIND_VEC_FIELD(2, y)
  326. BIND_VEC_FUNCTION_1(2, dot)
  327. BIND_VEC_FUNCTION_1(2, cross)
  328. BIND_VEC_FUNCTION_0(2, length)
  329. BIND_VEC_FUNCTION_0(2, length_squared)
  330. BIND_VEC_FUNCTION_0(2, normalize)
  331. }
  332. };
  333. struct PyVec3: Vec3 {
  334. PY_CLASS(PyVec3, linalg, vec3)
  335. PyVec3() : Vec3() {}
  336. PyVec3(const Vec3& v) : Vec3(v) {}
  337. PyVec3(const PyVec3& v) : Vec3(v) {}
  338. static void _register(VM* vm, PyObject* mod, PyObject* type){
  339. vm->bind_constructor<4>(type, [](VM* vm, ArgsView args){
  340. float x = VAR_F(args[1]);
  341. float y = VAR_F(args[2]);
  342. float z = VAR_F(args[3]);
  343. return VAR(Vec3(x, y, z));
  344. });
  345. vm->bind__repr__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
  346. PyVec3& self = _CAST(PyVec3&, obj);
  347. std::stringstream ss;
  348. ss << "vec3(" << self.x << ", " << self.y << ", " << self.z << ")";
  349. return VAR(ss.str());
  350. });
  351. vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){
  352. PyVec3& self = _CAST(PyVec3&, args[0]);
  353. return VAR_T(PyVec3, self);
  354. });
  355. BIND_VEC_VEC_OP(3, __add__, +)
  356. BIND_VEC_VEC_OP(3, __sub__, -)
  357. BIND_VEC_FLOAT_OP(3, __mul__, *)
  358. BIND_VEC_FLOAT_OP(3, __truediv__, /)
  359. BIND_VEC_VEC_OP(3, __eq__, ==)
  360. BIND_VEC_VEC_OP(3, __ne__, !=)
  361. BIND_VEC_FIELD(3, x)
  362. BIND_VEC_FIELD(3, y)
  363. BIND_VEC_FIELD(3, z)
  364. BIND_VEC_FUNCTION_1(3, dot)
  365. BIND_VEC_FUNCTION_1(3, cross)
  366. BIND_VEC_FUNCTION_0(3, length)
  367. BIND_VEC_FUNCTION_0(3, length_squared)
  368. BIND_VEC_FUNCTION_0(3, normalize)
  369. }
  370. };
  371. struct PyMat3x3: Mat3x3{
  372. PY_CLASS(PyMat3x3, linalg, mat3x3)
  373. PyMat3x3(): Mat3x3(){}
  374. PyMat3x3(const Mat3x3& other): Mat3x3(other){}
  375. PyMat3x3(const PyMat3x3& other): Mat3x3(other){}
  376. static void _register(VM* vm, PyObject* mod, PyObject* type){
  377. vm->bind_constructor<-1>(type, [](VM* vm, ArgsView args){
  378. if(args.size() == 1+0) return VAR_T(PyMat3x3, Mat3x3::zeros());
  379. if(args.size() == 1+9){
  380. Mat3x3 mat;
  381. for(int i=0; i<9; i++) mat.v[i] = VAR_F(args[1+i]);
  382. return VAR_T(PyMat3x3, mat);
  383. }
  384. if(args.size() == 1+1){
  385. List& a = CAST(List&, args[1]);
  386. if(a.size() != 3) vm->ValueError("Mat3x3.__new__ takes 3x3 list");
  387. Mat3x3 mat;
  388. for(int i=0; i<3; i++){
  389. List& b = CAST(List&, a[i]);
  390. if(b.size() != 3) vm->ValueError("Mat3x3.__new__ takes 3x3 list");
  391. for(int j=0; j<3; j++){
  392. mat.m[i][j] = VAR_F(b[j]);
  393. }
  394. }
  395. return VAR_T(PyMat3x3, mat);
  396. }
  397. vm->TypeError("Mat3x3.__new__ takes 0 or 1 arguments");
  398. return vm->None;
  399. });
  400. #define METHOD_PROXY_NONE(name) \
  401. vm->bind_method<0>(type, #name, [](VM* vm, ArgsView args){ \
  402. PyMat3x3& self = _CAST(PyMat3x3&, args[0]); \
  403. self.name(); \
  404. return vm->None; \
  405. });
  406. METHOD_PROXY_NONE(set_zeros)
  407. METHOD_PROXY_NONE(set_ones)
  408. METHOD_PROXY_NONE(set_identity)
  409. #undef METHOD_PROXY_NONE
  410. vm->bind__repr__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
  411. PyMat3x3& self = _CAST(PyMat3x3&, obj);
  412. std::stringstream ss;
  413. ss << std::fixed << std::setprecision(4);
  414. ss << "mat3x3([[" << self._11 << ", " << self._12 << ", " << self._13 << "],\n";
  415. ss << " [" << self._21 << ", " << self._22 << ", " << self._23 << "],\n";
  416. ss << " [" << self._31 << ", " << self._32 << ", " << self._33 << "]])";
  417. return VAR(ss.str());
  418. });
  419. vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){
  420. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  421. return VAR_T(PyMat3x3, self);
  422. });
  423. vm->bind__getitem__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj, PyObject* index){
  424. PyMat3x3& self = _CAST(PyMat3x3&, obj);
  425. Tuple& t = CAST(Tuple&, index);
  426. if(t.size() != 2){
  427. vm->TypeError("Mat3x3.__getitem__ takes a tuple of 2 integers");
  428. return vm->None;
  429. }
  430. i64 i = CAST(i64, t[0]);
  431. i64 j = CAST(i64, t[1]);
  432. if(i < 0 || i >= 3 || j < 0 || j >= 3){
  433. vm->IndexError("index out of range");
  434. return vm->None;
  435. }
  436. return VAR(self.m[i][j]);
  437. });
  438. vm->bind_method<2>(type, "__setitem__", [](VM* vm, ArgsView args){
  439. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  440. Tuple& t = CAST(Tuple&, args[1]);
  441. if(t.size() != 2){
  442. vm->TypeError("Mat3x3.__setitem__ takes a tuple of 2 integers");
  443. return vm->None;
  444. }
  445. i64 i = CAST(i64, t[0]);
  446. i64 j = CAST(i64, t[1]);
  447. if(i < 0 || i >= 3 || j < 0 || j >= 3){
  448. vm->IndexError("index out of range");
  449. return vm->None;
  450. }
  451. self.m[i][j] = VAR_F(args[2]);
  452. return vm->None;
  453. });
  454. #define PROPERTY_FIELD(field) \
  455. type->attr().set(#field, vm->property([](VM* vm, ArgsView args){ \
  456. PyMat3x3& self = _CAST(PyMat3x3&, args[0]); \
  457. return VAR(self.field); \
  458. }, [](VM* vm, ArgsView args){ \
  459. PyMat3x3& self = _CAST(PyMat3x3&, args[0]); \
  460. self.field = vm->num_to_float(args[1]); \
  461. return vm->None; \
  462. }));
  463. PROPERTY_FIELD(_11)
  464. PROPERTY_FIELD(_12)
  465. PROPERTY_FIELD(_13)
  466. PROPERTY_FIELD(_21)
  467. PROPERTY_FIELD(_22)
  468. PROPERTY_FIELD(_23)
  469. PROPERTY_FIELD(_31)
  470. PROPERTY_FIELD(_32)
  471. PROPERTY_FIELD(_33)
  472. #undef PROPERTY_FIELD
  473. vm->bind_method<1>(type, "__add__", [](VM* vm, ArgsView args){
  474. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  475. PyMat3x3& other = CAST(PyMat3x3&, args[1]);
  476. return VAR_T(PyMat3x3, self + other);
  477. });
  478. vm->bind_method<1>(type, "__sub__", [](VM* vm, ArgsView args){
  479. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  480. PyMat3x3& other = CAST(PyMat3x3&, args[1]);
  481. return VAR_T(PyMat3x3, self - other);
  482. });
  483. vm->bind_method<1>(type, "__mul__", [](VM* vm, ArgsView args){
  484. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  485. f64 other = VAR_F(args[1]);
  486. return VAR_T(PyMat3x3, self * other);
  487. });
  488. vm->bind_method<1>(type, "__truediv__", [](VM* vm, ArgsView args){
  489. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  490. f64 other = VAR_F(args[1]);
  491. return VAR_T(PyMat3x3, self / other);
  492. });
  493. auto f_mm = [](VM* vm, ArgsView args){
  494. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  495. if(is_non_tagged_type(args[1], PyMat3x3::_type(vm))){
  496. PyMat3x3& other = _CAST(PyMat3x3&, args[1]);
  497. return VAR_T(PyMat3x3, self.matmul(other));
  498. }
  499. if(is_non_tagged_type(args[1], PyVec3::_type(vm))){
  500. PyVec3& other = _CAST(PyVec3&, args[1]);
  501. return VAR_T(PyVec3, self.matmul(other));
  502. }
  503. vm->TypeError("unsupported operand type(s) for @");
  504. return vm->None;
  505. };
  506. vm->bind_method<1>(type, "__matmul__", f_mm);
  507. vm->bind_method<1>(type, "matmul", f_mm);
  508. vm->bind_method<1>(type, "__eq__", [](VM* vm, ArgsView args){
  509. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  510. PyMat3x3& other = CAST(PyMat3x3&, args[1]);
  511. return VAR(self == other);
  512. });
  513. vm->bind_method<1>(type, "__ne__", [](VM* vm, ArgsView args){
  514. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  515. PyMat3x3& other = CAST(PyMat3x3&, args[1]);
  516. return VAR(self != other);
  517. });
  518. vm->bind_method<0>(type, "determinant", [](VM* vm, ArgsView args){
  519. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  520. return VAR(self.determinant());
  521. });
  522. vm->bind_method<0>(type, "transpose", [](VM* vm, ArgsView args){
  523. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  524. return VAR_T(PyMat3x3, self.transpose());
  525. });
  526. vm->bind_method<0>(type, "inverse", [](VM* vm, ArgsView args){
  527. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  528. Mat3x3 ret;
  529. bool ok = self.inverse(ret);
  530. if(!ok) vm->ValueError("matrix is not invertible");
  531. return VAR_T(PyMat3x3, ret);
  532. });
  533. vm->bind_func<0>(type, "zeros", [](VM* vm, ArgsView args){
  534. return VAR_T(PyMat3x3, Mat3x3::zeros());
  535. });
  536. vm->bind_func<0>(type, "ones", [](VM* vm, ArgsView args){
  537. return VAR_T(PyMat3x3, Mat3x3::ones());
  538. });
  539. vm->bind_func<0>(type, "identity", [](VM* vm, ArgsView args){
  540. return VAR_T(PyMat3x3, Mat3x3::identity());
  541. });
  542. /*************** affine transformations ***************/
  543. vm->bind_func<3>(type, "trs", [](VM* vm, ArgsView args){
  544. PyVec2& t = CAST(PyVec2&, args[0]);
  545. f64 r = VAR_F(args[1]);
  546. PyVec2& s = CAST(PyVec2&, args[2]);
  547. return VAR_T(PyMat3x3, Mat3x3::trs(t, r, s));
  548. });
  549. vm->bind_method<0>(type, "is_affine", [](VM* vm, ArgsView args){
  550. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  551. return VAR(self.is_affine());
  552. });
  553. vm->bind_method<0>(type, "inverse_affine", [](VM* vm, ArgsView args){
  554. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  555. return VAR_T(PyMat3x3, self.inverse_affine());
  556. });
  557. vm->bind_method<1>(type, "matmul_affine", [](VM* vm, ArgsView args){
  558. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  559. PyMat3x3& other = CAST(PyMat3x3&, args[1]);
  560. return VAR_T(PyMat3x3, self.matmul_affine(other));
  561. });
  562. vm->bind_method<0>(type, "translation", [](VM* vm, ArgsView args){
  563. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  564. return VAR_T(PyVec2, self.translation());
  565. });
  566. vm->bind_method<0>(type, "rotation", [](VM* vm, ArgsView args){
  567. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  568. return VAR(self.rotation());
  569. });
  570. vm->bind_method<0>(type, "scale", [](VM* vm, ArgsView args){
  571. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  572. return VAR_T(PyVec2, self.scale());
  573. });
  574. vm->bind_method<1>(type, "transform_point", [](VM* vm, ArgsView args){
  575. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  576. PyVec2& v = CAST(PyVec2&, args[1]);
  577. return VAR_T(PyVec2, self.transform_point(v));
  578. });
  579. vm->bind_method<1>(type, "transform_vector", [](VM* vm, ArgsView args){
  580. PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
  581. PyVec2& v = CAST(PyVec2&, args[1]);
  582. return VAR_T(PyVec2, self.transform_vector(v));
  583. });
  584. }
  585. };
  586. inline PyObject* py_var(VM* vm, Vec2 obj){ return VAR_T(PyVec2, obj); }
  587. inline PyObject* py_var(VM* vm, const PyVec2& obj){ return VAR_T(PyVec2, obj);}
  588. inline PyObject* py_var(VM* vm, Vec3 obj){ return VAR_T(PyVec3, obj); }
  589. inline PyObject* py_var(VM* vm, const PyVec3& obj){ return VAR_T(PyVec3, obj);}
  590. inline PyObject* py_var(VM* vm, const Mat3x3& obj){ return VAR_T(PyMat3x3, obj); }
  591. inline PyObject* py_var(VM* vm, const PyMat3x3& obj){ return VAR_T(PyMat3x3, obj); }
  592. inline void add_module_linalg(VM* vm){
  593. PyObject* linalg = vm->new_module("linalg");
  594. PyVec2::register_class(vm, linalg);
  595. PyVec3::register_class(vm, linalg);
  596. PyMat3x3::register_class(vm, linalg);
  597. }
  598. static_assert(sizeof(Py_<PyMat3x3>) <= 64);
  599. } // namespace pkpy