{"id":13514830,"url":"https://github.com/ferd36/quaternions","last_synced_at":"2025-03-31T03:31:29.875Z","repository":{"id":44473742,"uuid":"47988827","full_name":"ferd36/quaternions","owner":"ferd36","description":"A blazingly fast C++ library to work with quaternions :zap:","archived":false,"fork":false,"pushed_at":"2024-12-10T16:26:18.000Z","size":878,"stargazers_count":65,"open_issues_count":1,"forks_count":16,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-10T17:31:35.292Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/ferd36.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-12-14T16:59:58.000Z","updated_at":"2024-12-10T16:26:22.000Z","dependencies_parsed_at":"2024-11-01T18:31:45.067Z","dependency_job_id":null,"html_url":"https://github.com/ferd36/quaternions","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/ferd36%2Fquaternions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferd36%2Fquaternions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferd36%2Fquaternions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferd36%2Fquaternions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ferd36","download_url":"https://codeload.github.com/ferd36/quaternions/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246413377,"owners_count":20773053,"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":[],"created_at":"2024-08-01T05:01:02.394Z","updated_at":"2025-03-31T03:31:24.867Z","avatar_url":"https://github.com/ferd36.png","language":"C++","funding_links":[],"categories":["C++"],"sub_categories":[],"readme":"# Quaternions  [![Build status](https://travis-ci.org/FrankAstier/quaternions.svg?branch=master)](https://travis-ci.org/FrankAstier/quaternions) [![Coverage Status](https://coveralls.io/repos/FrankAstier/quaternions/badge.svg?branch=master\u0026service=github\u0026bust=1)](https://coveralls.io/github/FrankAstier/quaternions?branch=master)\n\nA C++11 library to work with quaternions, as a single header file.\n\n## Introduction\n- In mathematics, the quaternions are a number system that extends the complex numbers.\n  They were first described by Irish mathematician William Rowan Hamilton in 1843 and applied to mechanics\n  in three-dimensional space. A feature of quaternions is that multiplication of two quaternions is noncommutative.\n  Hamilton defined a quaternion as the quotient of two directed lines in a three-dimensional space or equivalently\n  as the quotient of two vectors. Quaternions find uses in both theoretical and applied mathematics, in particular\n  for calculations involving three-dimensional rotations such as in three-dimensional computer graphics, computer\n  vision and crystallographic texture analysis. In practical applications, they can be used alongside other methods,\n  such as Euler angles and rotation matrices, or as an alternative to them, depending on the application.\n\n## Design objectives\n- This library was designed to be simple, fast and convenient.\n- For simplicity, there is a single(parametric) class, quaternion::Quaternion, that lives in a single header file.\n- Computing the power of a quaternion in particular has been optimized to be significantly faster than boost.\n- The methods provided have been designed to make it as natural as possible to use quaternion::Quaternion.\n\n## Usage\n- include \\\u003cquaternions/src/quaternion.h\\\u003e\n- using namespace quaternion;\n- To build the unit tests: cmake . ; make OR make -f Makefile.mk\n- To make the doc: doxygen Doxyfile.\n- The file unit_tests.cpp shows usage examples for all the function in the quaternion namespace.\n- The file unit_tests.cpp contains various benchmarks.\n\n## Notes\n- Boost provides quaternions at: http://www.boost.org/doc/libs/1_59_0/libs/math/doc/html/quaternions.html\n  This implementation is as fast as or faster than Boost. In particular pow is much faster than Boost. The speedups\n  in this implementation were obtained by factorizing the a few low powers, and re-using those factorizations for\n  higher powers.\n- I have tried to use intrinsics(SSE), but didn't find it to be faster than \"naive\" code.\n- Expression templates: unless the expression templates do some serious work, gcc can optimize the code to get very\n  good performance, essentially equal to expression templates. So expression templates seem to be an older technique\n  that's no longer required by modern compilers(although clang seems to lag compared to gcc in terms of optimization).\n- The std::complex class is reputed to be slow, mostly because it does a lot of work to comply with IEEE-754/IEC-559\n  apparently. Maybe the worst of this is that this compliance is not optional, and some developers have complained\n  that absolutely correct handling of the sign of infinities should not be forced on them.\n\n## IEEE-754/IEC-559 compliance\n- If the compiler supports IEC-559, which can be verified by calling std::numeric_limits::is_iec559,\n  then quaternion::Quaternion will leverage this.\n- However the Quaternion algorithms do not currently take extra steps to comply with IEC-559's prescribed way of handling\n  NaNs, underflows, overflows...\n\n## Tested with:\n- clang\n- gcc 4.8\n\n## Requirements\n- Boost is required for the unit tests, but not for the Quaternion class itself.\n\n## Others/References\n- https://en.wikipedia.org/wiki/Quaternion\n- http://www.boost.org/doc/libs/1_59_0/libs/math/doc/html/quaternions.html\n- *vectorclass* from Agner Fog, can be found at: http://www.agner.org/optimize/, and provides quaternion classes.\n- http://www.geometrictools.com/index.html\n\n## Quaternion synopsis\n\n### Quaternion\\\u003cT\\\u003e members\n#### Constructors\n    Quaternion(T a=0, T b=0, T c=0, T d=0)\n\n    template\u003ctypename T1 = T, IS_NOT_ITERATOR(T1)\u003e\n    Quaternion(T1 a=0, T1 b=0, T1 c=0, T1 d=0)\n\n    template\u003ctypename T1\u003e\n    Quaternion(const std::complex\u003cT1\u003e \u0026x, const std::complex\u003cT1\u003e \u0026y=std::complex\u003cT1\u003e(0, 0))\n\n    template\u003ctypename T1 = T\u003e\n    Quaternion(T1 *it)\n\n    template\u003ctypename It, IS_ITERATOR(It)\u003e\n    Quaternion(It it)\n\n    template\u003ctypename T1\u003e\n    Quaternion(const Quaternion\u003cT1\u003e \u0026y)\n\n    template\u003ctypename T1\u003e\n    Quaternion \u0026 operator=(const Quaternion\u003cT1\u003e \u0026other)\n\n#### Accessors\n    T a() const\n    T b() const\n    T c() const\n    T d() const\n\n    std::complex\u003cT\u003e c1() const\n    std::complex\u003cT\u003e c2() const\n\n    T to_real() const\n    std::complex\u003cT\u003e to_complex() const\n    std::array\u003cT, 4\u003e to_array() const\n\n    T real() const\n    Quaternion unreal() const\n\n    T norm_squared() const\n    T abs() const\n    T unreal_norm_squared() const\n\n#### Tests\n    template\u003ctypename T1 = T\u003e\n    bool is_unit(T1 eps=0) const\n\n    template\u003ctypename T1 = T\u003e\n    bool is_real(T1 eps=0) const\n\n    template\u003ctypename T1 = T\u003e\n    bool is_complex(T1 eps=0) const\n\n    template\u003ctypename T1 = T\u003e\n    bool is_unreal(T1 eps=0) const\n\n#### Arithmetic\n    Quaternion operator+() const\n    Quaternion operator-() const\n    Quaternion operator+=(T y)\n    Quaternion operator-=(T y)\n    Quaternion operator*=(T k)\n    Quaternion operator/=(T k)\n\n    template\u003ctypename T1\u003e\n    Quaternion operator+=(const std::complex\u003cT1\u003e \u0026y)\n\n    template\u003ctypename T1\u003e\n    Quaternion operator-=(const std::complex\u003cT1\u003e \u0026y)\n\n    template\u003ctypename T1\u003e\n    Quaternion operator*=(const std::complex\u003cT1\u003e \u0026y)\n\n    template\u003ctypename T1\u003e\n    Quaternion operator/=(const std::complex\u003cT1\u003e \u0026y)\n\n    template\u003ctypename T1\u003e\n    Quaternion operator+=(const Quaternion\u003cT1\u003e \u0026y)\n\n    template\u003ctypename T1\u003e\n    Quaternion operator-=(const Quaternion\u003cT1\u003e \u0026y)\n\n    template\u003ctypename T1\u003e\n    Quaternion operator*=(const Quaternion\u003cT1\u003e \u0026y)\n\n    template\u003ctypename T1\u003e\n    Quaternion operator/=(const Quaternion\u003cT1\u003e \u0026y)\n\n\n### Typedef\n    typedef Quaternion\u003cfloat\u003e Qf\n    typedef Quaternion\u003cdouble\u003e Qd\n    typedef Quaternion\u003clong double\u003e Qld\n\n    template\u003ctypename T\u003e\n    using polar_representation = std::array\u003cT, 5\u003e\n\n    template\u003ctypename T\u003e\n    using matrix_representation = std::array\u003cstd::array\u003cstd::complex\u003cT\u003e, 2\u003e, 2\u003e\n\n    template\u003ctypename T\u003e\n    using rotation_matrix = std::array\u003cstd::array\u003cT, 3\u003e, 3\u003e\n\n### Enumerations\n    enum  DisplayStyle { q_nice, q_compact }\n\n### Predefined constants\n    const Qf Qf_1(1)\n    const Qf Qf_i(0, 1)\n    const Qf Qf_j(0, 0, 1)\n    const Qf Qf_k(0, 0, 0, 1)\n\n    const Qd Qd_1(1)\n    const Qd Qd_i(0, 1)\n    const Qd Qd_j(0, 0, 1)\n    const Qd Qd_k(0, 0, 0, 1)\n\n    const Qld Qld_1(1)\n    const Qld Qld_i(0, 1)\n    const Qld Qld_j(0, 0, 1)\n    const Qld Qld_k(0, 0, 0, 1)\n\n### Functions\n#### Constructors\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e spherical(T rho, T theta, T phi1, T phi2)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e semipolar(T rho, T alpha, T theta1, T theta2)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e multipolar(T rho1, T theta1, T rho2, T theta2)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e cylindrospherical(T t, T radius, T longitude, T latitude)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e cylindrical(T r, T angle, T h1, T h2)\n\n    template\u003ctypename T\u003e\n    polar_representation\u003cT\u003e to_polar_representation(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    matrix_representation\u003cT\u003e to_matrix_representation(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    rotation_matrix\u003cT\u003e to_rotation_matrix(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e from_rotation_matrix(const rotation_matrix\u003cT\u003e \u0026rm)\n\n#### Various\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e conj(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    T norm_squared(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    T abs(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    T unreal_norm_squared(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    T norm_l0(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    T norm_l1(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T , typename T1\u003e\n    T norm_lk(const Quaternion\u003cT\u003e \u0026x, T1 k)\n\n    template\u003ctypename T\u003e\n    T norm_sup(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e normalize(const Quaternion\u003cT\u003e \u0026x)\n\n#### Tests\n    template\u003ctypename T , typename T1 = T\u003e\n    bool is_unit(const Quaternion\u003cT\u003e \u0026x, T1 eps=0)\n\n    template\u003ctypename T , typename T1 = T\u003e\n    bool is_real(const Quaternion\u003cT\u003e \u0026x, T1 eps=0)\n\n    template\u003ctypename T , typename T1 = T\u003e\n    bool is_complex(const Quaternion\u003cT\u003e \u0026x, T1 eps=0)\n\n    template\u003ctypename T , typename T1 = T\u003e\n    bool is_unreal(const Quaternion\u003cT\u003e \u0026x, T1 eps=0)\n\n#### Equality\n    template\u003ctypename T , typename T2 , IS_CONVERTIBLE(T2, T)\u003e\n    bool operator==(const Quaternion\u003cT\u003e \u0026x, T2 y)\n\n    template\u003ctypename T , typename T2 , IS_CONVERTIBLE(T2, T)\u003e\n    bool operator==(T2 y, const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T , typename T2 , IS_CONVERTIBLE(T2, T)\u003e\n    bool operator!=(const Quaternion\u003cT\u003e \u0026x, T2 y)\n\n    template\u003ctypename T , typename T2 , IS_CONVERTIBLE(T2, T)\u003e\n    bool operator!=(T2 y, const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T , typename T2 , typename T3 , IS_CONVERTIBLE(T2, T) , IS_CONVERTIBLE(T3, T)\u003e\n    bool nearly_equal(const Quaternion\u003cT\u003e \u0026x, T2 y, T3 eps)\n\n    template\u003ctypename T , typename T2 , typename T3 , IS_CONVERTIBLE(T2, T) , IS_CONVERTIBLE(T3, T)\u003e\n    bool nearly_equal(T2 y, const Quaternion\u003cT\u003e \u0026x, T3 eps)\n\n    template\u003ctypename T , typename T2 , IS_CONVERTIBLE(T2, T)\u003e\n    bool operator==(const Quaternion\u003cT\u003e \u0026x, const std::complex\u003cT2\u003e \u0026y)\n\n    template\u003ctypename T , typename T2 , IS_CONVERTIBLE(T2, T)\u003e\n    bool operator!=(const Quaternion\u003cT\u003e \u0026x, const std::complex\u003cT2\u003e \u0026y)\n\n    template\u003ctypename T , typename T2 , IS_CONVERTIBLE(T2, T)\u003e\n    bool operator==(const std::complex\u003cT2\u003e \u0026y, const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T , typename T2 , IS_CONVERTIBLE(T2, T)\u003e\n    bool operator!=(const std::complex\u003cT2\u003e \u0026y, const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T , typename T2 , typename T3 , IS_CONVERTIBLE(T2, T) , IS_CONVERTIBLE(T3, T)\u003e\n    bool nearly_equal(const Quaternion\u003cT\u003e \u0026x, const std::complex\u003cT2\u003e \u0026y, T3 eps)\n\n    template\u003ctypename T , typename T2 , typename T3 , IS_CONVERTIBLE(T2, T) , IS_CONVERTIBLE(T3, T)\u003e\n    bool nearly_equal(const std::complex\u003cT2\u003e \u0026y, const Quaternion\u003cT\u003e \u0026x, T3 eps)\n\n    template\u003ctypename T\u003e\n    bool operator==(const Quaternion\u003cT\u003e \u0026x, const Quaternion\u003cT\u003e \u0026y)\n\n    template\u003ctypename T\u003e\n    bool operator!=(const Quaternion\u003cT\u003e \u0026x, const Quaternion\u003cT\u003e \u0026y)\n\n    template\u003ctypename T , typename T2 , typename T3 , IS_CONVERTIBLE(T2, T) , IS_CONVERTIBLE(T3, T)\u003e\n    bool nearly_equal(const Quaternion\u003cT\u003e \u0026x, const Quaternion\u003cT2\u003e \u0026y, T3 eps)\n\n#### Arithmetic\n    template\u003ctypename T , typename T1\u003e\n    Quaternion\u003cT\u003e operator+(const Quaternion\u003cT\u003e \u0026x, T1 y)\n\n    template\u003ctypename T , typename T1\u003e\n    Quaternion\u003cT\u003e operator+(T1 y, const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e operator+(const Quaternion\u003cT\u003e \u0026x, std::complex\u003cT\u003e \u0026y)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e operator+(std::complex\u003cT\u003e \u0026y, const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e operator+(const Quaternion\u003cT\u003e \u0026x, const Quaternion\u003cT\u003e \u0026y)\n\n    template\u003ctypename T , typename T1\u003e\n    Quaternion\u003cT\u003e operator-(const Quaternion\u003cT\u003e \u0026x, T1 y)\n\n    template\u003ctypename T , typename T1\u003e\n    Quaternion\u003cT\u003e operator-(T1 y, const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e operator-(const Quaternion\u003cT\u003e \u0026x, std::complex\u003cT\u003e \u0026y)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e operator-(std::complex\u003cT\u003e \u0026y, const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e operator-(const Quaternion\u003cT\u003e \u0026x, const Quaternion\u003cT\u003e \u0026y)\n\n    template\u003ctypename T , typename T1\u003e\n    Quaternion\u003cT\u003e operator*(const Quaternion\u003cT\u003e \u0026x, T1 y)\n\n    template\u003ctypename T , typename T1\u003e\n    Quaternion\u003cT\u003e operator*(T1 y, const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e operator*(const Quaternion\u003cT\u003e \u0026x, std::complex\u003cT\u003e \u0026y)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e operator*(std::complex\u003cT\u003e \u0026y, const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e operator*(const Quaternion\u003cT\u003e \u0026x, const Quaternion\u003cT\u003e \u0026y)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e inverse(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T , typename T1\u003e\n    Quaternion\u003cT\u003e operator/(const Quaternion\u003cT\u003e \u0026x, T1 y)\n\n    template\u003ctypename T , typename T1\u003e\n    Quaternion\u003cT\u003e operator/(T1 y, const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e operator/(const Quaternion\u003cT\u003e \u0026x, std::complex\u003cT\u003e \u0026y)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e operator/(std::complex\u003cT\u003e \u0026y, const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e operator/(const Quaternion\u003cT\u003e \u0026x, const Quaternion\u003cT\u003e \u0026y)\n\n#### Dot, cross product, commutator\n    template\u003ctypename T\u003e\n    T dot(const Quaternion\u003cT\u003e \u0026x, const Quaternion\u003cT\u003e \u0026y)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e cross(const Quaternion\u003cT\u003e \u0026x, const Quaternion\u003cT\u003e \u0026y)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e commutator(const Quaternion\u003cT\u003e \u0026x, const Quaternion\u003cT\u003e \u0026y)\n\n#### Transcendentals\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e exp(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e log(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e pow2(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e pow3(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e pow4(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e pow(const Quaternion\u003cT\u003e \u0026x, int expt)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e pow(const Quaternion\u003cT\u003e \u0026x, T a)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e pow(const Quaternion\u003cT\u003e \u0026x, const Quaternion\u003cT\u003e \u0026a)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e cos(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e sin(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e tan(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e cosh(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e sinh(const Quaternion\u003cT\u003e \u0026x)\n\n    template\u003ctypename T\u003e\n    Quaternion\u003cT\u003e tanh(const Quaternion\u003cT\u003e \u0026x)\n\n#### Algorithms\n    template\u003ctypename T , typename K\u003e\n    Quaternion\u003cT\u003e axby(K k1, const Quaternion\u003cT\u003e \u0026x, K k2, const Quaternion\u003cT\u003e \u0026y)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fferd36%2Fquaternions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fferd36%2Fquaternions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fferd36%2Fquaternions/lists"}