{"id":19397915,"url":"https://github.com/velipso/nvqm","last_synced_at":"2025-04-24T05:31:14.012Z","repository":{"id":48055827,"uuid":"82939505","full_name":"velipso/nvqm","owner":"velipso","description":"Numeric, Vector, Quaternion, and Matrix functions, consistent across multiple programming languages","archived":false,"fork":false,"pushed_at":"2023-05-25T13:18:59.000Z","size":197,"stargazers_count":10,"open_issues_count":4,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-18T05:15:14.276Z","etag":null,"topics":["matrix-functions","matrix-library","quaternion","vector","vector-library"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/velipso.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-23T15:13:31.000Z","updated_at":"2024-11-21T03:30:56.000Z","dependencies_parsed_at":"2022-08-12T17:40:20.205Z","dependency_job_id":null,"html_url":"https://github.com/velipso/nvqm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/velipso%2Fnvqm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/velipso%2Fnvqm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/velipso%2Fnvqm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/velipso%2Fnvqm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/velipso","download_url":"https://codeload.github.com/velipso/nvqm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250572251,"owners_count":21452327,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["matrix-functions","matrix-library","quaternion","vector","vector-library"],"created_at":"2024-11-10T11:03:38.478Z","updated_at":"2025-04-24T05:31:13.722Z","avatar_url":"https://github.com/velipso.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"nvqm\n====\n\nNumeric, Vector, Quaternion, and Matrix functions, consistent across multiple programming languages.\n\nThe number of times I've had to lookup a simple vector operation is too damn high.  Here is my\nattempt to pick a single reasonable API to consistently apply across any programming language I\nhappen to be using.\n\nImplementations\n---------------\n\n* C99 (`nvqm.h`+`nvqm.c`)\n  * Values stored as structured arrays to facilitate pass-by-value\n  * Pass-by-value functions are `static inline`\n  * Q16.16 fixed-point implementation (see notes below)\n* JavaScript (`nvqm.js`)\n  * Values stored as a flat array of numbers\n  * Pass-by-value functions return new arrays, vs. pass-by-reference functions which modify and\n    return the `out` parameter\n  * When `require`d in node.js, functions are exported into global namespace\n* [TypeScript](http://www.typescriptlang.org/) (`nvqm.ts`)\n  * Typed version of JavaScript using tuples\n* [Sink](https://github.com/voidqk/sink) (`sink_vqm.js`, `sink_vqm.h`+`sink_vqm.c`)\n  * Values are stored as a flat array of numbers\n  * Pass-by-value functions return new arrays, vs. pass-by-reference functions which modify and\n    return the `out` parameter\n  * `num.*` functions aren't included due to them being native to sink itself\n\nFixed-Point\n-----------\n\nThe C files also contains a signed Q16.16 fixed-point implementation.  It is deterministic and never\nfails -- but will give incorrect results if numbers overflow.  Angles are not stored in radians, but\ninstead as 12 bit number (0 to 4095).\n\nThe implementation is okay for most functions, but is pretty terrible for `xint_pow`, and I suspect\nslow for `xint_sqrt`.  I would love help, if anyone knows better.\n\n\nFunctions\n---------\n\nThe `num`, `vec2`, `vec3`, `vec4`, `quat`, `mat2`, and `mat3x2` functions operate using\npass-by-value semantics, while `mat3` and `mat4` use pass-by-reference semantics.\n\n```c\nconst float  TAU; // 2 * PI\nconst double TAUd;\n\n// num (scalars)\nfloat num_abs  (float a);\nfloat num_acos (float a);\nfloat num_asin (float a);\nfloat num_atan2(float a, float b);\nfloat num_atan (float a);\nfloat num_ceil (float a);\nfloat num_clamp(float a, float min, float max);\nfloat num_cos  (float a);\nfloat num_exp  (float a);\nfloat num_floor(float a);\nfloat num_lerp (float a, float b, float t);\nfloat num_log  (float a);\nfloat num_max  (float a, float b);\nfloat num_min  (float a, float b);\nfloat num_mod  (float a, float b);\nfloat num_pow  (float a, float b);\nfloat num_round(float a);\nfloat num_sin  (float a);\nfloat num_sqrt (float a);\nfloat num_tan  (float a);\n\n// vec2  [x, y]\nvec2  vec2_add        (vec2 a, vec2 b);\nvec2  vec2_applymat2  (vec2 a, mat2 b);\nvec2  vec2_applymat3x2(vec2 a, mat3x2 b);\nvec2  vec2_applymat3  (vec2 a, mat3 *b);\nvec2  vec2_applymat4  (vec2 a, mat4 *b);\nvec2  vec2_clamp      (vec2 a, vec2 min, vec2 max);\nvec2  vec2_cross      (vec2 a, vec2 b);\nfloat vec2_dist       (vec2 a, vec2 b);\nfloat vec2_dist2      (vec2 a, vec2 b); // distance squared\nvec2  vec2_div        (vec2 a, vec2 b);\nfloat vec2_dot        (vec2 a, vec2 b);\nvec2  vec2_inverse    (vec2 a);\nfloat vec2_len        (vec2 a);\nfloat vec2_len2       (vec2 a); // length squared\nvec2  vec2_lerp       (vec2 a, vec2 b, float t);\nvec2  vec2_max        (vec2 a, vec2 b);\nvec2  vec2_min        (vec2 a, vec2 b);\nvec2  vec2_mul        (vec2 a, vec2 b);\nvec2  vec2_neg        (vec2 a);\nvec2  vec2_normal     (vec2 a);\nvec2  vec2_scale      (vec2 a, float s);\nvec2  vec2_sub        (vec2 a, vec2 b);\n\n// vec3  [x, y, z]\nvec3  vec3_add        (vec3 a, vec3 b);\nfloat vec3_angle      (vec3 a, vec3 b);\nvec3  vec3_applymat3x2(vec3 a, mat3x2 b);\nvec3  vec3_applymat3  (vec3 a, mat3 *b);\nvec3  vec3_applymat4  (vec3 a, mat4 *b);\nvec3  vec3_applyquat  (vec3 a, quat b);\nvec3  vec3_clamp      (vec3 a, vec3 min, vec3 max);\nvec3  vec3_cross      (vec3 a, vec3 b);\nfloat vec3_dist       (vec3 a, vec3 b);\nfloat vec3_dist2      (vec3 a, vec3 b);\nvec3  vec3_div        (vec3 a, vec3 b);\nfloat vec3_dot        (vec3 a, vec3 b);\nvec3  vec3_inverse    (vec3 a);\nfloat vec3_len        (vec3 a);\nfloat vec3_len2       (vec3 a);\nvec3  vec3_lerp       (vec3 a, vec3 b, float t);\nvec3  vec3_max        (vec3 a, vec3 b);\nvec3  vec3_min        (vec3 a, vec3 b);\nvec3  vec3_mul        (vec3 a, vec3 b);\nfloat vec3_nangle     (vec3 a, vec3 b); // a and b are normalized\nvec3  vec3_neg        (vec3 a);\nvec3  vec3_normal     (vec3 a);\nvec3  vec3_orthogonal (vec3 a, vec3 b); // normal(cross(a, b))\nvec3  vec3_scale      (vec3 a, float s);\nvec3  vec3_sub        (vec3 a, vec3 b);\n\n// vec4  [x, y, z, w]\nvec4  vec4_add      (vec4 a, vec4 b);\nvec4  vec4_applymat4(vec4 a, mat4 *b);\nvec4  vec4_applyquat(vec4 a, quat b);\nvec4  vec4_clamp    (vec4 a, vec4 min, vec4 max);\nvec4  vec4_div      (vec4 a, vec4 b);\nfloat vec4_dist     (vec4 a, vec4 b);\nfloat vec4_dist2    (vec4 a, vec4 b);\nfloat vec4_dot      (vec4 a, vec4 b);\nvec4  vec4_inverse  (vec4 a);\nfloat vec4_len      (vec4 a);\nfloat vec4_len2     (vec4 a);\nvec4  vec4_lerp     (vec4 a, vec4 b, float t);\nvec4  vec4_max      (vec4 a, vec4 b);\nvec4  vec4_min      (vec4 a, vec4 b);\nvec4  vec4_mul      (vec4 a, vec4 b);\nvec4  vec4_neg      (vec4 a);\nvec4  vec4_normal   (vec4 a);\nvec4  vec4_scale    (vec4 a, float s);\nvec4  vec4_sub      (vec4 a, vec4 b);\n\n// quat  [x, y, z, w]\nquat  quat_axisang  (vec3 axis, float ang);\nquat  quat_between  (vec3 from, vec3 to);\nfloat quat_dot      (quat a, quat b);\nquat  quat_euler_xyz(vec3 rot);\nquat  quat_euler_xzy(vec3 rot);\nquat  quat_euler_yxz(vec3 rot);\nquat  quat_euler_yzx(vec3 rot);\nquat  quat_euler_zxy(vec3 rot);\nquat  quat_euler_zyx(vec3 rot);\nquat  quat_identity ();\nquat  quat_invert   (quat a);\nquat  quat_lerp     (quat a, quat b, float t);\nquat  quat_mul      (quat a, quat b);\nquat  quat_naxisang (vec3 axis, float ang); // axis is normalized\nquat  quat_nbetween (vec3 from, vec3 to); // from/to are normalized\nquat  quat_neg      (quat a);\nquat  quat_nlerp    (quat a, quat b, float t);\nquat  quat_normal   (quat a);\nquat  quat_slerp    (quat a, quat b, float t);\n\n// mat2\n// [a, b, c, d] = | a c |\n//                | b d |\nmat2  mat2_add      (mat2 a, mat2 b);\nmat2  mat2_adjoint  (mat2 a);\nmat2  mat2_compmul  (mat2 a, mat2 b);\nfloat mat2_det      (mat2 a);\nmat2  mat2_identity ();\nmat2  mat2_invert   (mat2 a);\nmat2  mat2_mul      (mat2 a, mat2 b);\nmat2  mat2_rotate   (mat2 a, float ang);\nmat2  mat2_rotation (float ang);\nmat2  mat2_scale    (mat2 a, vec2 b);\nmat2  mat2_scaling  (vec2 a);\nmat2  mat2_sub      (mat2 a, mat2 b);\nmat2  mat2_transpose(mat2 a);\n\n// mat3x2\n//                      | a c e |\n// [a, b, c, d, e, f] = | b d f |\n//                      | 0 0 1 |\nmat3x2 mat3x2_add        (mat3x2 a, mat3x2 b);\nmat3x2 mat3x2_compmul    (mat3x2 a, mat3x2 b);\nfloat  mat3x2_det        (mat3x2 a);\nmat3x2 mat3x2_identity   ();\nmat3x2 mat3x2_invert     (mat3x2 a);\nmat3x2 mat3x2_mul        (mat3x2 a, mat3x2 b);\nmat3x2 mat3x2_rotate     (mat3x2 a, float ang);\nmat3x2 mat3x2_rotation   (float ang);\nmat3x2 mat3x2_scale      (mat3x2 a, vec2 b);\nmat3x2 mat3x2_scaling    (vec2 a);\nmat3x2 mat3x2_sub        (mat3x2 a, mat3x2 b);\nmat3x2 mat3x2_translate  (mat3x2 a, vec2 b);\nmat3x2 mat3x2_translation(vec2 a);\n\n// mat3\n//                               | a d g |\n// [a, b, c, d, e, f, g, h, i] = | b e h |\n//                               | c f i |\nmat3 *mat3_add        (mat3 *out, mat3 *a, mat3 *b);\nmat3 *mat3_adjoint    (mat3 *out, mat3 *a);\nmat3 *mat3_compmul    (mat3 *out, mat3 *a, mat3 *b);\nmat3 *mat3_copy       (mat3 *out, mat3 *a);\nfloat mat3_det        (mat3 *a);\nmat3 *mat3_identity   (mat3 *out);\nmat3 *mat3_invert     (mat3 *out, mat3 *a);\nmat3 *mat3_mul        (mat3 *out, mat3 *a, mat3 *b);\nmat3 *mat3_quat       (mat3 *out, quat a);\nmat3 *mat3_rotate     (mat3 *out, mat3 *a, float ang);\nmat3 *mat3_rotation   (mat3 *out, float ang);\nmat3 *mat3_scale      (mat3 *out, mat3 *a, vec2 b);\nmat3 *mat3_scaling    (mat3 *out, vec2 a);\nmat3 *mat3_sub        (mat3 *out, mat3 *a, mat3 *b);\nmat3 *mat3_translate  (mat3 *out, mat3 *a, vec2 b);\nmat3 *mat3_translation(mat3 *out, vec2 a);\nmat3 *mat3_transpose  (mat3 *out, mat3 *a);\n\n// mat4\n//                                                    | a e i m |\n// [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p] = | b f j n |\n//                                                    | c g k o |\n//                                                    | d h l p |\nmat4 *mat4_add           (mat4 *out, mat4 *a, mat4 *b);\nmat4 *mat4_adjoint       (mat4 *out, mat4 *a);\nmat4 *mat4_compmul       (mat4 *out, mat4 *a, mat4 *b);\nmat4 *mat4_copy          (mat4 *out, mat4 *a);\nfloat mat4_det           (mat4 *a);\nmat4 *mat4_frustum       (mat4 *out, float L, float R, float B, float T, float N, float F);\nmat4 *mat4_identity      (mat4 *out);\nmat4 *mat4_invert        (mat4 *out, mat4 *a);\nmat4 *mat4_lookat        (mat4 *out, vec3 eye, vec3 position, vec3 up);\nmat4 *mat4_mul           (mat4 *out, mat4 *a, mat4 *b);\nmat4 *mat4_orthogonal    (mat4 *out, float W, float H, float N, float F);\nmat4 *mat4_perspective   (mat4 *out, float fov, float W, float H, float N, float F);\nmat4 *mat4_quat          (mat4 *out, quat a);\nmat4 *mat4_rotate        (mat4 *out, mat4 *a, vec3 axis, float ang);\nmat4 *mat4_rotation      (mat4 *out, vec3 axis, float ang);\nmat4 *mat4_rottrans      (mat4 *out, quat a, vec3 b);\nmat4 *mat4_rottransorigin(mat4 *out, quat a, vec3 b, vec3 origin);\nmat4 *mat4_scale         (mat4 *out, mat4 *a, vec3 b);\nmat4 *mat4_scaling       (mat4 *out, vec3 a);\nmat4 *mat4_sub           (mat4 *out, mat4 *a, mat4 *b);\nmat4 *mat4_translate     (mat4 *out, mat4 *a, vec3 b);\nmat4 *mat4_translation   (mat4 *out, vec3 a);\nmat4 *mat4_transpose     (mat4 *out, mat4 *a);\n\n//\n// fixed-point 16.16 (only in C implementation)\n//\ntypedef int32_t xint; // represents the signed Q16.16 fixed-point type\ntypedef int32_t xang; // represents a 12-bit angle type\n#define XINT1    65536  /* the value 1 */\n#define XINT(v)  ((xint)((v) * XINT1)) /* convert constant to xint */\n#define XANG0    0x0000 /*  0 degrees */\n#define XANG45   0x0200 /* 45 degrees */\n#define XANG90   0x0400 /* ...etc     */\n#define XANG135  0x0600\n#define XANG180  0x0800\n#define XANG225  0x0A00\n#define XANG270  0x0C00\n#define XANG315  0x0E00\n#define XANG360  0x1000 /* can be thought of as TAU to some extent */\n\nint    xint_toint     (xint a);\nxint   xint_fromint   (int a);\nfloat  xint_tofloat   (xint a);\nxint   xint_fromfloat (float a);\ndouble xint_todouble  (xint a);\nxint   xint_fromdouble(double a);\n\nxang   xang_wrap      (xang a); // wrap `a` between 0-4095\nfloat  xang_tofloat   (xang a);\nxang   xang_fromfloat (float ang);\ndouble xang_todouble  (xang a);\nxang   xang_fromdouble(double ang);\n\nxint xint_add(xint a, xint b);\nxint xint_sub(xint a, xint b);\nxint xint_mul(xint a, xint b);\nxint xint_div(xint a, xint b);\n\nxint xint_abs  (xint a);\nxang xint_acos (xint a);\nxang xint_asin (xint a);\nxang xint_atan2(xint a, xint b);\nxang xint_atan (xint a);\nxint xint_ceil (xint a);\nxint xint_clamp(xint a, xint min, xint max);\nxint xint_cos  (xang a);\nxint xint_exp  (xint a);\nxint xint_floor(xint a);\nxint xint_lerp (xint a, xint b, xint t);\nxint xint_log  (xint a);\nxint xint_max  (xint a, xint b);\nxint xint_min  (xint a, xint b);\nxint xint_mod  (xint a, xint b);\nxint xint_pow  (xint a, xint b);\nxint xint_round(xint a);\nxint xint_sin  (xang a);\nxint xint_sqrt (xint a);\nxint xint_tan  (xang a);\n\n// xvec2  fixed-point version of vec2\nvec2  xvec2_tovec2     (xvec2 a);\nxvec2 xvec2_fromvec2   (vec2 a);\nxvec2 xvec2_add        (xvec2 a, xvec2 b);\nxvec2 xvec2_applymat2  (xvec2 a, xmat2 b);\nxvec2 xvec2_applymat3x2(xvec2 a, xmat3x2 b);\nxvec2 xvec2_applymat3  (xvec2 a, xmat3 *b);\nxvec2 xvec2_applymat4  (xvec2 a, xmat4 *b);\nxvec2 xvec2_clamp      (xvec2 a, xvec2 min, xvec2 max);\nxint  xvec2_dist       (xvec2 a, xvec2 b);\nxint  xvec2_dist2      (xvec2 a, xvec2 b);\nxvec2 xvec2_div        (xvec2 a, xvec2 b);\nxint  xvec2_dot        (xvec2 a, xvec2 b);\nxvec2 xvec2_inverse    (xvec2 a);\nxint  xvec2_len        (xvec2 a);\nxint  xvec2_len2       (xvec2 a);\nxvec2 xvec2_lerp       (xvec2 a, xvec2 b, xint t);\nxvec2 xvec2_max        (xvec2 a, xvec2 b);\nxvec2 xvec2_min        (xvec2 a, xvec2 b);\nxvec2 xvec2_mul        (xvec2 a, xvec2 b);\nxvec2 xvec2_neg        (xvec2 a);\nxvec2 xvec2_normal     (xvec2 a);\nxvec2 xvec2_scale      (xvec2 a, xint s);\nxvec2 xvec2_sub        (xvec2 a, xvec2 b);\n\n// xvec3  fixed-point version of vec3\nvec3  xvec3_tovec3     (xvec3 a);\nxvec3 xvec3_fromvec3   (vec3 a);\nxvec3 xvec3_add        (xvec3 a, xvec3 b);\nxint  xvec3_angle      (xvec3 a, xvec3 b);\nxvec3 xvec3_applymat3x2(xvec3 a, xmat3x2 b);\nxvec3 xvec3_applymat3  (xvec3 a, xmat3 *b);\nxvec3 xvec3_applymat4  (xvec3 a, xmat4 *b);\nxvec3 xvec3_applyquat  (xvec3 a, xquat b);\nxvec3 xvec3_clamp      (xvec3 a, xvec3 min, xvec3 max);\nxvec3 xvec3_cross      (xvec3 a, xvec3 b);\nxint  xvec3_dist       (xvec3 a, xvec3 b);\nxint  xvec3_dist2      (xvec3 a, xvec3 b);\nxvec3 xvec3_div        (xvec3 a, xvec3 b);\nxint  xvec3_dot        (xvec3 a, xvec3 b);\nxvec3 xvec3_inverse    (xvec3 a);\nxint  xvec3_len        (xvec3 a);\nxint  xvec3_len2       (xvec3 a);\nxvec3 xvec3_lerp       (xvec3 a, xvec3 b, xint t);\nxvec3 xvec3_max        (xvec3 a, xvec3 b);\nxvec3 xvec3_min        (xvec3 a, xvec3 b);\nxvec3 xvec3_mul        (xvec3 a, xvec3 b);\nxint  xvec3_nangle     (xvec3 a, xvec3 b); // a and b are normalized\nxvec3 xvec3_neg        (xvec3 a);\nxvec3 xvec3_normal     (xvec3 a);\nxvec3 xvec3_orthogonal (xvec3 a, xvec3 b); // normal(cross(normal(a), normal(b)))\nxvec3 xvec3_scale      (xvec3 a, xint s);\nxvec3 xvec3_sub        (xvec3 a, xvec3 b);\n\n// xvec4  fixed-point version of vec4\nvec4  xvec4_tovec4   (xvec4 a);\nxvec4 xvec4_fromvec4 (vec4 a);\nxvec4 xvec4_add      (xvec4 a, xvec4 b);\nxvec4 xvec4_applymat4(xvec4 a, xmat4 *b);\nxvec4 xvec4_applyquat(xvec4 a, xquat b);\nxvec4 xvec4_clamp    (xvec4 a, xvec4 min, xvec4 max);\nxint  xvec4_dist     (xvec4 a, xvec4 b);\nxint  xvec4_dist2    (xvec4 a, xvec4 b);\nxvec4 xvec4_div      (xvec4 a, xvec4 b);\nxint  xvec4_dot      (xvec4 a, xvec4 b);\nxvec4 xvec4_inverse  (xvec4 a);\nxint  xvec4_len      (xvec4 a);\nxint  xvec4_len2     (xvec4 a);\nxvec4 xvec4_lerp     (xvec4 a, xvec4 b, xint t);\nxvec4 xvec4_max      (xvec4 a, xvec4 b);\nxvec4 xvec4_min      (xvec4 a, xvec4 b);\nxvec4 xvec4_mul      (xvec4 a, xvec4 b);\nxvec4 xvec4_neg      (xvec4 a);\nxvec4 xvec4_normal   (xvec4 a);\nxvec4 xvec4_scale    (xvec4 a, xint s);\nxvec4 xvec4_sub      (xvec4 a, xvec4 b);\n\n// xquat  fixed-point version of quat\nquat  xquat_toquat   (xquat a);\nxquat xquat_fromquat (quat a);\nxquat xquat_axisang  (xvec3 axis, xang ang);\nxquat xquat_between  (xvec3 from, xvec3 to);\nxint  xquat_dot      (xquat a, xquat b);\nxquat xquat_euler_xyz(xvec3 rot);\nxquat xquat_euler_xzy(xvec3 rot);\nxquat xquat_euler_yxz(xvec3 rot);\nxquat xquat_euler_yzx(xvec3 rot);\nxquat xquat_euler_zxy(xvec3 rot);\nxquat xquat_euler_zyx(xvec3 rot);\nxquat xquat_identity ();\nxquat xquat_invert   (xquat a);\nxquat xquat_lerp     (xquat a, xquat b, xint t);\nxquat xquat_mul      (xquat a, xquat b);\nxquat xquat_naxisang (xvec3 axis, xang ang);\nxquat xquat_nbetween (xvec3 from, xvec3 to);\nxquat xquat_neg      (xquat a);\nxquat xquat_nlerp    (xquat a, xquat b, xint t);\nxquat xquat_normal   (xquat a);\nxquat xquat_slerp    (xquat a, xquat b, xint t);\n\n// xmat2  fixed-point version of mat2\nmat2  xmat2_tomat2   (xmat2 a);\nxmat2 xmat2_frommat2 (mat2 a);\nxmat2 xmat2_add      (xmat2 a, xmat2 b);\nxmat2 xmat2_adjoint  (xmat2 a);\nxmat2 xmat2_compmul  (xmat2 a, xmat2 b);\nxint  xmat2_det      (xmat2 a);\nxmat2 xmat2_identity ();\nxmat2 xmat2_invert   (xmat2 a);\nxmat2 xmat2_mul      (xmat2 a, xmat2 b);\nxmat2 xmat2_rotate   (xmat2 a, xang ang);\nxmat2 xmat2_rotation (xang ang);\nxmat2 xmat2_scale    (xmat2 a, xvec2 b);\nxmat2 xmat2_scaling  (xvec2 a);\nxmat2 xmat2_sub      (xmat2 a, xmat2 b);\nxmat2 xmat2_transpose(xmat2 a);\n\n// xmat3x2  fixed-point version of mat3x2\nmat3x2  xmat3x2_tomat3x2   (xmat3x2 a);\nxmat3x2 xmat3x2_frommat3x2 (mat3x2 a);\nxmat3x2 xmat3x2_add        (xmat3x2 a, xmat3x2 b);\nxmat3x2 xmat3x2_compmul    (xmat3x2 a, xmat3x2 b);\nxint    xmat3x2_det        (xmat3x2 a);\nxmat3x2 xmat3x2_identity   ();\nxmat3x2 xmat3x2_invert     (xmat3x2 a);\nxmat3x2 xmat3x2_mul        (xmat3x2 a, xmat3x2 b);\nxmat3x2 xmat3x2_rotate     (xmat3x2 a, xang ang);\nxmat3x2 xmat3x2_rotation   (xang ang);\nxmat3x2 xmat3x2_scale      (xmat3x2 a, xvec2 b);\nxmat3x2 xmat3x2_scaling    (xvec2 a);\nxmat3x2 xmat3x2_sub        (xmat3x2 a, xmat3x2 b);\nxmat3x2 xmat3x2_translate  (xmat3x2 a, xvec2 b);\nxmat3x2 xmat3x2_translation(xvec2 a);\n\n// xmat3  fixed-point version of mat3\nxmat3 *xmat3_add        (xmat3 *out, xmat3 *a, xmat3 *b);\nxmat3 *xmat3_adjoint    (xmat3 *out, xmat3 *a);\nxmat3 *xmat3_compmul    (xmat3 *out, xmat3 *a, xmat3 *b);\nxmat3 *xmat3_copy       (xmat3 *out, xmat3 *a);\nxint   xmat3_det        (xmat3 *a);\nxmat3 *xmat3_identity   (xmat3 *out);\nxmat3 *xmat3_invert     (xmat3 *out, xmat3 *a);\nxmat3 *xmat3_mul        (xmat3 *out, xmat3 *a, xmat3 *b);\nxmat3 *xmat3_quat       (xmat3 *out, xquat a);\nxmat3 *xmat3_rotate     (xmat3 *out, xmat3 *a, xang ang);\nxmat3 *xmat3_rotation   (xmat3 *out, xang ang);\nxmat3 *xmat3_scale      (xmat3 *out, xmat3 *a, xvec2 b);\nxmat3 *xmat3_scaling    (xmat3 *out, xvec2 a);\nxmat3 *xmat3_sub        (xmat3 *out, xmat3 *a, xmat3 *b);\nxmat3 *xmat3_translate  (xmat3 *out, xmat3 *a, xvec2 b);\nxmat3 *xmat3_translation(xmat3 *out, xvec2 a);\nxmat3 *xmat3_transpose  (xmat3 *out, xmat3 *a);\n\n// xmat4  fixed-point version of mat4\nxmat4 *xmat4_add           (xmat4 *out, xmat4 *a, xmat4 *b);\nxmat4 *xmat4_adjoint       (xmat4 *out, xmat4 *a);\nxmat4 *xmat4_compmul       (xmat4 *out, xmat4 *a, xmat4 *b);\nxmat4 *xmat4_copy          (xmat4 *out, xmat4 *a);\nxint   xmat4_det           (xmat4 *a);\nxmat4 *xmat4_frustum       (xmat4 *out, xint L, xint R, xint B, xint T, xint N, xint F);\nxmat4 *xmat4_identity      (xmat4 *out);\nxmat4 *xmat4_invert        (xmat4 *out, xmat4 *a);\nxmat4 *xmat4_lookat        (xmat4 *out, xvec3 eye, xvec3 position, xvec3 up);\nxmat4 *xmat4_mul           (xmat4 *out, xmat4 *a, xmat4 *b);\nxmat4 *xmat4_orthogonal    (xmat4 *out, xint W, xint H, xint N, xint F);\nxmat4 *xmat4_perspective   (xmat4 *out, xang fov, xint W, xint H, xint N, xint F);\nxmat4 *xmat4_quat          (xmat4 *out, xquat a);\nxmat4 *xmat4_rotate        (xmat4 *out, xmat4 *a, xvec3 axis, xang ang);\nxmat4 *xmat4_rotation      (xmat4 *out, xvec3 axis, xang ang);\nxmat4 *xmat4_rottrans      (xmat4 *out, xquat a, xvec3 b);\nxmat4 *xmat4_rottransorigin(xmat4 *out, xquat a, xvec3 b, xvec3 origin);\nxmat4 *xmat4_scale         (xmat4 *out, xmat4 *a, xvec3 b);\nxmat4 *xmat4_scaling       (xmat4 *out, xvec3 a);\nxmat4 *xmat4_sub           (xmat4 *out, xmat4 *a, xmat4 *b);\nxmat4 *xmat4_translate     (xmat4 *out, xmat4 *a, xvec3 b);\nxmat4 *xmat4_translation   (xmat4 *out, xvec3 a);\nxmat4 *xmat4_transpose     (xmat4 *out, xmat4 *a);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvelipso%2Fnvqm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvelipso%2Fnvqm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvelipso%2Fnvqm/lists"}