18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#ifndef API_BASE_MATH_MATRIX_H
178bf80f4bSopenharmony_ci#define API_BASE_MATH_MATRIX_H
188bf80f4bSopenharmony_ci
198bf80f4bSopenharmony_ci#include <cstddef>
208bf80f4bSopenharmony_ci
218bf80f4bSopenharmony_ci#include <base/containers/type_traits.h>
228bf80f4bSopenharmony_ci#include <base/math/vector.h>
238bf80f4bSopenharmony_ci#include <base/math/vector_util.h>
248bf80f4bSopenharmony_ci#include <base/namespace.h>
258bf80f4bSopenharmony_ci
268bf80f4bSopenharmony_ci// m00[0] m01[3] m02[6]
278bf80f4bSopenharmony_ci// m10[1] m11[4] m12[7]
288bf80f4bSopenharmony_ci// m20[2] m21[5] m22[8]
298bf80f4bSopenharmony_ci
308bf80f4bSopenharmony_ci// m00[0] m01[4] m02[8]  m03[12]
318bf80f4bSopenharmony_ci// m10[1] m11[5] m12[9]  m13[13]
328bf80f4bSopenharmony_ci// m20[2] m21[6] m22[10] m23[14]
338bf80f4bSopenharmony_ci// m30[3] m31[7] m32[11] m33[15]
348bf80f4bSopenharmony_ci
358bf80f4bSopenharmony_ci// m00[0] m01[4] m02[8]
368bf80f4bSopenharmony_ci// m10[1] m11[5] m12[9]
378bf80f4bSopenharmony_ci// m20[2] m21[6] m22[10]
388bf80f4bSopenharmony_ci// m30[3] m31[7] m32[11]
398bf80f4bSopenharmony_ciBASE_BEGIN_NAMESPACE()
408bf80f4bSopenharmony_cinamespace Math {
418bf80f4bSopenharmony_ci#include <base/math/disable_warning_4201_heading.h>
428bf80f4bSopenharmony_ci
438bf80f4bSopenharmony_ci/** @ingroup group_math_matrix */
448bf80f4bSopenharmony_ci/** Matrix 3X3 presentation in column major format */
458bf80f4bSopenharmony_ciclass Mat3X3 final {
468bf80f4bSopenharmony_cipublic:
478bf80f4bSopenharmony_ci    union {
488bf80f4bSopenharmony_ci        struct {
498bf80f4bSopenharmony_ci            Vec3 x, y, z;
508bf80f4bSopenharmony_ci        };
518bf80f4bSopenharmony_ci        Vec3 base[3];
528bf80f4bSopenharmony_ci        float data[9];
538bf80f4bSopenharmony_ci    };
548bf80f4bSopenharmony_ci
558bf80f4bSopenharmony_ci    /** Subscript operator */
568bf80f4bSopenharmony_ci    constexpr Vec3& operator[](size_t aIndex)
578bf80f4bSopenharmony_ci    {
588bf80f4bSopenharmony_ci        return base[aIndex];
598bf80f4bSopenharmony_ci    }
608bf80f4bSopenharmony_ci
618bf80f4bSopenharmony_ci    /** Subscript operator */
628bf80f4bSopenharmony_ci    constexpr const Vec3& operator[](size_t aIndex) const
638bf80f4bSopenharmony_ci    {
648bf80f4bSopenharmony_ci        return base[aIndex];
658bf80f4bSopenharmony_ci    }
668bf80f4bSopenharmony_ci
678bf80f4bSopenharmony_ci    // Constructors
688bf80f4bSopenharmony_ci    /** Default constructor */
698bf80f4bSopenharmony_ci    inline constexpr Mat3X3() noexcept : data { 0 } {}
708bf80f4bSopenharmony_ci
718bf80f4bSopenharmony_ci    /** Identity constructor */
728bf80f4bSopenharmony_ci    inline explicit constexpr Mat3X3(float id) noexcept : data { id, 0.0f, 0.0f, 0.0f, id, 0.0f, 0.0f, 0.0f, id } {}
738bf80f4bSopenharmony_ci
748bf80f4bSopenharmony_ci    /** Constructor for using Vector3's */
758bf80f4bSopenharmony_ci    inline constexpr Mat3X3(Vec3 const& v0, Vec3 const& v1, Vec3 const& v2) noexcept : x(v0), y(v1), z(v2) {}
768bf80f4bSopenharmony_ci
778bf80f4bSopenharmony_ci    /** Constructor for array of floats */
788bf80f4bSopenharmony_ci    inline constexpr Mat3X3(const float d[9]) noexcept : data { d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8] }
798bf80f4bSopenharmony_ci    {}
808bf80f4bSopenharmony_ci
818bf80f4bSopenharmony_ci    inline ~Mat3X3() = default;
828bf80f4bSopenharmony_ci
838bf80f4bSopenharmony_ci    /** Multiply two matrices */
848bf80f4bSopenharmony_ci    inline constexpr Mat3X3 operator*(const Mat3X3& rhs) const
858bf80f4bSopenharmony_ci    {
868bf80f4bSopenharmony_ci        const Vec3& rha { rhs.x.x, rhs.y.x, rhs.z.x };
878bf80f4bSopenharmony_ci        const Vec3& rhb { rhs.x.y, rhs.y.y, rhs.z.y };
888bf80f4bSopenharmony_ci        const Vec3& rhc { rhs.x.z, rhs.y.z, rhs.z.z };
898bf80f4bSopenharmony_ci
908bf80f4bSopenharmony_ci        return { { Dot(x, rha), Dot(x, rhb), Dot(x, rhc) }, { Dot(y, rha), Dot(y, rhb), Dot(y, rhc) },
918bf80f4bSopenharmony_ci            { Dot(z, rha), Dot(z, rhb), Dot(z, rhc) } };
928bf80f4bSopenharmony_ci    }
938bf80f4bSopenharmony_ci
948bf80f4bSopenharmony_ci    /** Multiply columns by float scalar value */
958bf80f4bSopenharmony_ci    inline constexpr Mat3X3 operator*(const float& scalar) const
968bf80f4bSopenharmony_ci    {
978bf80f4bSopenharmony_ci        return Mat3X3(x * scalar, y * scalar, z * scalar);
988bf80f4bSopenharmony_ci    }
998bf80f4bSopenharmony_ci
1008bf80f4bSopenharmony_ci    /** Equality operator, returns true if matrices are equal */
1018bf80f4bSopenharmony_ci    inline constexpr bool operator==(const Mat3X3& mat) const
1028bf80f4bSopenharmony_ci    {
1038bf80f4bSopenharmony_ci        for (size_t i = 0; i < countof(data); ++i) {
1048bf80f4bSopenharmony_ci            if (data[i] != mat.data[i]) {
1058bf80f4bSopenharmony_ci                return false;
1068bf80f4bSopenharmony_ci            }
1078bf80f4bSopenharmony_ci        }
1088bf80f4bSopenharmony_ci        return true;
1098bf80f4bSopenharmony_ci    }
1108bf80f4bSopenharmony_ci
1118bf80f4bSopenharmony_ci    /** Inequality operator, returns true if matrices are inequal */
1128bf80f4bSopenharmony_ci    inline constexpr bool operator!=(const Mat3X3& mat) const
1138bf80f4bSopenharmony_ci    {
1148bf80f4bSopenharmony_ci        for (size_t i = 0; i < countof(data); ++i) {
1158bf80f4bSopenharmony_ci            if (data[i] != mat.data[i]) {
1168bf80f4bSopenharmony_ci                return true;
1178bf80f4bSopenharmony_ci            }
1188bf80f4bSopenharmony_ci        }
1198bf80f4bSopenharmony_ci        return false;
1208bf80f4bSopenharmony_ci    }
1218bf80f4bSopenharmony_ci};
1228bf80f4bSopenharmony_ci
1238bf80f4bSopenharmony_ci// Assert that Mat3X3 is the same as 9 floats
1248bf80f4bSopenharmony_cistatic_assert(sizeof(Mat3X3) == 9 * sizeof(float));
1258bf80f4bSopenharmony_ci
1268bf80f4bSopenharmony_cistatic constexpr Mat3X3 IDENTITY_3X3(1.f);
1278bf80f4bSopenharmony_ci
1288bf80f4bSopenharmony_ci/** @ingroup group_math_matrix */
1298bf80f4bSopenharmony_ci/** Matrix 4X4 presentation in column major format */
1308bf80f4bSopenharmony_ciclass Mat4X4 final {
1318bf80f4bSopenharmony_cipublic:
1328bf80f4bSopenharmony_ci    union {
1338bf80f4bSopenharmony_ci        struct {
1348bf80f4bSopenharmony_ci            Vec4 x, y, z, w;
1358bf80f4bSopenharmony_ci        };
1368bf80f4bSopenharmony_ci        Vec4 base[4]; // base[0] is X ,base [1] is Y, etc..
1378bf80f4bSopenharmony_ci        float data[16];
1388bf80f4bSopenharmony_ci    };
1398bf80f4bSopenharmony_ci
1408bf80f4bSopenharmony_ci    // "For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out contiguously in memory.
1418bf80f4bSopenharmony_ci    // The translation components occupy the 13th, 14th, and 15th elements of the 16-element matrix."
1428bf80f4bSopenharmony_ci    // https://www.khronos.org/opengl/wiki/General_OpenGL:_Transformations#Are_OpenGL_matrices_column-major_or_row-major.3F
1438bf80f4bSopenharmony_ci    // this is also the same as with glm.
1448bf80f4bSopenharmony_ci    /** Subscript operator */
1458bf80f4bSopenharmony_ci    constexpr Vec4& operator[](size_t aIndex)
1468bf80f4bSopenharmony_ci    {
1478bf80f4bSopenharmony_ci        return base[aIndex];
1488bf80f4bSopenharmony_ci    }
1498bf80f4bSopenharmony_ci
1508bf80f4bSopenharmony_ci    /** Subscript operator */
1518bf80f4bSopenharmony_ci    constexpr const Vec4& operator[](size_t aIndex) const
1528bf80f4bSopenharmony_ci    {
1538bf80f4bSopenharmony_ci        return base[aIndex];
1548bf80f4bSopenharmony_ci    }
1558bf80f4bSopenharmony_ci
1568bf80f4bSopenharmony_ci    // Constructors
1578bf80f4bSopenharmony_ci    /** Zero initializer constructor */
1588bf80f4bSopenharmony_ci    inline constexpr Mat4X4() : data { 0 } {}
1598bf80f4bSopenharmony_ci
1608bf80f4bSopenharmony_ci    /** Constructor for Vector4's */
1618bf80f4bSopenharmony_ci    inline constexpr Mat4X4(Vec4 const& v0, Vec4 const& v1, Vec4 const& v2, Vec4 const& v3) : x(v0), y(v1), z(v2), w(v3)
1628bf80f4bSopenharmony_ci    {}
1638bf80f4bSopenharmony_ci
1648bf80f4bSopenharmony_ci    /** Constructor for array of floats */
1658bf80f4bSopenharmony_ci    inline constexpr Mat4X4(const float d[16])
1668bf80f4bSopenharmony_ci        : data { d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15] }
1678bf80f4bSopenharmony_ci    {}
1688bf80f4bSopenharmony_ci
1698bf80f4bSopenharmony_ci    /** Constructor for floats */
1708bf80f4bSopenharmony_ci    inline constexpr Mat4X4(float d0, float d1, float d2, float d3, float d4, float d5, float d6, float d7, float d8,
1718bf80f4bSopenharmony_ci        float d9, float d10, float d11, float d12, float d13, float d14, float d15)
1728bf80f4bSopenharmony_ci        : data { d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15 }
1738bf80f4bSopenharmony_ci    {}
1748bf80f4bSopenharmony_ci
1758bf80f4bSopenharmony_ci    /** Identity constructor */
1768bf80f4bSopenharmony_ci    inline explicit constexpr Mat4X4(float id)
1778bf80f4bSopenharmony_ci        : data { id, 0.0f, 0.0f, 0.0f, 0.0f, id, 0.0f, 0.0f, 0.0f, 0.0f, id, 0.0f, 0.0f, 0.0f, 0.0f, id }
1788bf80f4bSopenharmony_ci    {}
1798bf80f4bSopenharmony_ci
1808bf80f4bSopenharmony_ci    /** Conversion constructor from Mat3X3 to Mat4X4 */
1818bf80f4bSopenharmony_ci    explicit inline constexpr Mat4X4(const Mat3X3& mat3X3)
1828bf80f4bSopenharmony_ci        : data { mat3X3.data[0], mat3X3.data[1], mat3X3.data[2], 0.0f, mat3X3.data[3], mat3X3.data[4], mat3X3.data[5],
1838bf80f4bSopenharmony_ci              0.0f, mat3X3.data[6], mat3X3.data[7], mat3X3.data[8], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }
1848bf80f4bSopenharmony_ci    {}
1858bf80f4bSopenharmony_ci
1868bf80f4bSopenharmony_ci    inline ~Mat4X4() = default;
1878bf80f4bSopenharmony_ci
1888bf80f4bSopenharmony_ci    /** Multiply two matrices */
1898bf80f4bSopenharmony_ci    inline constexpr Mat4X4 operator*(const Mat4X4& rhs) const
1908bf80f4bSopenharmony_ci    {
1918bf80f4bSopenharmony_ci#define d data
1928bf80f4bSopenharmony_ci        Mat4X4 res;
1938bf80f4bSopenharmony_ci        res.d[0] = d[0] * rhs.d[0] + d[4] * rhs.d[1] + d[8] * rhs.d[2] + d[12] * rhs.d[3];
1948bf80f4bSopenharmony_ci        res.d[4] = d[0] * rhs.d[4] + d[4] * rhs.d[5] + d[8] * rhs.d[6] + d[12] * rhs.d[7];
1958bf80f4bSopenharmony_ci        res.d[8] = d[0] * rhs.d[8] + d[4] * rhs.d[9] + d[8] * rhs.d[10] + d[12] * rhs.d[11];
1968bf80f4bSopenharmony_ci        res.d[12] = d[0] * rhs.d[12] + d[4] * rhs.d[13] + d[8] * rhs.d[14] + d[12] * rhs.d[15];
1978bf80f4bSopenharmony_ci
1988bf80f4bSopenharmony_ci        res.d[1] = d[1] * rhs.d[0] + d[5] * rhs.d[1] + d[9] * rhs.d[2] + d[13] * rhs.d[3];
1998bf80f4bSopenharmony_ci        res.d[5] = d[1] * rhs.d[4] + d[5] * rhs.d[5] + d[9] * rhs.d[6] + d[13] * rhs.d[7];
2008bf80f4bSopenharmony_ci        res.d[9] = d[1] * rhs.d[8] + d[5] * rhs.d[9] + d[9] * rhs.d[10] + d[13] * rhs.d[11];
2018bf80f4bSopenharmony_ci        res.d[13] = d[1] * rhs.d[12] + d[5] * rhs.d[13] + d[9] * rhs.d[14] + d[13] * rhs.d[15];
2028bf80f4bSopenharmony_ci
2038bf80f4bSopenharmony_ci        res.d[2] = d[2] * rhs.d[0] + d[6] * rhs.d[1] + d[10] * rhs.d[2] + d[14] * rhs.d[3];
2048bf80f4bSopenharmony_ci        res.d[6] = d[2] * rhs.d[4] + d[6] * rhs.d[5] + d[10] * rhs.d[6] + d[14] * rhs.d[7];
2058bf80f4bSopenharmony_ci        res.d[10] = d[2] * rhs.d[8] + d[6] * rhs.d[9] + d[10] * rhs.d[10] + d[14] * rhs.d[11];
2068bf80f4bSopenharmony_ci        res.d[14] = d[2] * rhs.d[12] + d[6] * rhs.d[13] + d[10] * rhs.d[14] + d[14] * rhs.d[15];
2078bf80f4bSopenharmony_ci
2088bf80f4bSopenharmony_ci        res.d[3] = d[3] * rhs.d[0] + d[7] * rhs.d[1] + d[11] * rhs.d[2] + d[15] * rhs.d[3];
2098bf80f4bSopenharmony_ci        res.d[7] = d[3] * rhs.d[4] + d[7] * rhs.d[5] + d[11] * rhs.d[6] + d[15] * rhs.d[7];
2108bf80f4bSopenharmony_ci        res.d[11] = d[3] * rhs.d[8] + d[7] * rhs.d[9] + d[11] * rhs.d[10] + d[15] * rhs.d[11];
2118bf80f4bSopenharmony_ci        res.d[15] = d[3] * rhs.d[12] + d[7] * rhs.d[13] + d[11] * rhs.d[14] + d[15] * rhs.d[15];
2128bf80f4bSopenharmony_ci#undef d
2138bf80f4bSopenharmony_ci        return res;
2148bf80f4bSopenharmony_ci    }
2158bf80f4bSopenharmony_ci
2168bf80f4bSopenharmony_ci    /** Multiply columns by float scalar value */
2178bf80f4bSopenharmony_ci    inline constexpr Mat4X4 operator*(const float& scalar) const
2188bf80f4bSopenharmony_ci    {
2198bf80f4bSopenharmony_ci        return Mat4X4(x * scalar, y * scalar, z * scalar, w * scalar);
2208bf80f4bSopenharmony_ci    }
2218bf80f4bSopenharmony_ci
2228bf80f4bSopenharmony_ci    /** Equality operator, returns true if matrices are equal */
2238bf80f4bSopenharmony_ci    inline constexpr bool operator==(const Mat4X4& mat) const
2248bf80f4bSopenharmony_ci    {
2258bf80f4bSopenharmony_ci        for (size_t i = 0; i < countof(data); ++i) {
2268bf80f4bSopenharmony_ci            if (data[i] != mat.data[i]) {
2278bf80f4bSopenharmony_ci                return false;
2288bf80f4bSopenharmony_ci            }
2298bf80f4bSopenharmony_ci        }
2308bf80f4bSopenharmony_ci        return true;
2318bf80f4bSopenharmony_ci    }
2328bf80f4bSopenharmony_ci
2338bf80f4bSopenharmony_ci    /** Inequality operator, returns true if matrices are inequal */
2348bf80f4bSopenharmony_ci    inline constexpr bool operator!=(const Mat4X4& mat) const
2358bf80f4bSopenharmony_ci    {
2368bf80f4bSopenharmony_ci        for (size_t i = 0; i < countof(data); ++i) {
2378bf80f4bSopenharmony_ci            if (data[i] != mat.data[i]) {
2388bf80f4bSopenharmony_ci                return true;
2398bf80f4bSopenharmony_ci            }
2408bf80f4bSopenharmony_ci        }
2418bf80f4bSopenharmony_ci        return false;
2428bf80f4bSopenharmony_ci    }
2438bf80f4bSopenharmony_ci};
2448bf80f4bSopenharmony_ci
2458bf80f4bSopenharmony_ci// Assert that Mat4X4 is the same as 16 floats
2468bf80f4bSopenharmony_cistatic_assert(sizeof(Mat4X4) == 16 * sizeof(float));
2478bf80f4bSopenharmony_ci
2488bf80f4bSopenharmony_cistatic constexpr Mat4X4 IDENTITY_4X4(1.f);
2498bf80f4bSopenharmony_ci
2508bf80f4bSopenharmony_ci/** @ingroup group_math_matrix */
2518bf80f4bSopenharmony_ci/** Matrix 4X3 presentation in column major format */
2528bf80f4bSopenharmony_ciclass Mat4X3 final {
2538bf80f4bSopenharmony_cipublic:
2548bf80f4bSopenharmony_ci    union {
2558bf80f4bSopenharmony_ci        struct {
2568bf80f4bSopenharmony_ci            Vec3 x, y, z, w;
2578bf80f4bSopenharmony_ci        };
2588bf80f4bSopenharmony_ci        Vec3 base[4]; // base[0] is X ,base [1] is Y, etc..
2598bf80f4bSopenharmony_ci        float data[12];
2608bf80f4bSopenharmony_ci    };
2618bf80f4bSopenharmony_ci
2628bf80f4bSopenharmony_ci    // "For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out contiguously in memory.
2638bf80f4bSopenharmony_ci    // The translation components occupy the 13th, 14th, and 15th elements of the 16-element matrix."
2648bf80f4bSopenharmony_ci    // https://www.khronos.org/opengl/wiki/General_OpenGL:_Transformations#Are_OpenGL_matrices_column-major_or_row-major.3F
2658bf80f4bSopenharmony_ci    // this is also the same as with glm.
2668bf80f4bSopenharmony_ci    /** Subscript operator */
2678bf80f4bSopenharmony_ci    constexpr Vec3& operator[](size_t aIndex)
2688bf80f4bSopenharmony_ci    {
2698bf80f4bSopenharmony_ci        return base[aIndex];
2708bf80f4bSopenharmony_ci    }
2718bf80f4bSopenharmony_ci
2728bf80f4bSopenharmony_ci    /** Subscript operator */
2738bf80f4bSopenharmony_ci    constexpr const Vec3& operator[](size_t aIndex) const
2748bf80f4bSopenharmony_ci    {
2758bf80f4bSopenharmony_ci        return base[aIndex];
2768bf80f4bSopenharmony_ci    }
2778bf80f4bSopenharmony_ci
2788bf80f4bSopenharmony_ci    // Constructors
2798bf80f4bSopenharmony_ci    /** Zero initializer constructor */
2808bf80f4bSopenharmony_ci    inline constexpr Mat4X3() : data { 0 } {}
2818bf80f4bSopenharmony_ci
2828bf80f4bSopenharmony_ci    /** Constructor for Vector4's */
2838bf80f4bSopenharmony_ci    inline constexpr Mat4X3(Vec3 const& v0, Vec3 const& v1, Vec3 const& v2, Vec3 const& v3) : x(v0), y(v1), z(v2), w(v3)
2848bf80f4bSopenharmony_ci    {}
2858bf80f4bSopenharmony_ci
2868bf80f4bSopenharmony_ci    /** Constructor for array of floats */
2878bf80f4bSopenharmony_ci    inline constexpr Mat4X3(const float d[12])
2888bf80f4bSopenharmony_ci        : data { d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11] }
2898bf80f4bSopenharmony_ci    {}
2908bf80f4bSopenharmony_ci
2918bf80f4bSopenharmony_ci    /** Constructor for floats */
2928bf80f4bSopenharmony_ci    inline constexpr Mat4X3(float d0, float d1, float d2, float d3, float d4, float d5, float d6, float d7, float d8,
2938bf80f4bSopenharmony_ci        float d9, float d10, float d11)
2948bf80f4bSopenharmony_ci        : data { d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11 }
2958bf80f4bSopenharmony_ci    {}
2968bf80f4bSopenharmony_ci
2978bf80f4bSopenharmony_ci    /** Identity constructor */
2988bf80f4bSopenharmony_ci    inline explicit constexpr Mat4X3(float id)
2998bf80f4bSopenharmony_ci        : data { id, 0.0f, 0.0f, 0.0f, id, 0.0f, 0.0f, 0.0f, id, 0.0f, 0.0f, 0.0f }
3008bf80f4bSopenharmony_ci    {}
3018bf80f4bSopenharmony_ci
3028bf80f4bSopenharmony_ci    inline ~Mat4X3() = default;
3038bf80f4bSopenharmony_ci
3048bf80f4bSopenharmony_ci    /** Multiply columns by float scalar value */
3058bf80f4bSopenharmony_ci    inline constexpr Mat4X3 operator*(const float& scalar) const
3068bf80f4bSopenharmony_ci    {
3078bf80f4bSopenharmony_ci        return Mat4X3(x * scalar, y * scalar, z * scalar, w * scalar);
3088bf80f4bSopenharmony_ci    }
3098bf80f4bSopenharmony_ci
3108bf80f4bSopenharmony_ci    /** Equality operator, returns true if matrices are equal */
3118bf80f4bSopenharmony_ci    inline constexpr bool operator==(const Mat4X3& mat) const
3128bf80f4bSopenharmony_ci    {
3138bf80f4bSopenharmony_ci        for (size_t i = 0; i < countof(data); ++i) {
3148bf80f4bSopenharmony_ci            if (data[i] != mat.data[i]) {
3158bf80f4bSopenharmony_ci                return false;
3168bf80f4bSopenharmony_ci            }
3178bf80f4bSopenharmony_ci        }
3188bf80f4bSopenharmony_ci        return true;
3198bf80f4bSopenharmony_ci    }
3208bf80f4bSopenharmony_ci
3218bf80f4bSopenharmony_ci    /** Inequality operator, returns true if matrices are inequal */
3228bf80f4bSopenharmony_ci    inline constexpr bool operator!=(const Mat4X3& mat) const
3238bf80f4bSopenharmony_ci    {
3248bf80f4bSopenharmony_ci        for (size_t i = 0; i < countof(data); ++i) {
3258bf80f4bSopenharmony_ci            if (data[i] != mat.data[i]) {
3268bf80f4bSopenharmony_ci                return true;
3278bf80f4bSopenharmony_ci            }
3288bf80f4bSopenharmony_ci        }
3298bf80f4bSopenharmony_ci        return false;
3308bf80f4bSopenharmony_ci    }
3318bf80f4bSopenharmony_ci};
3328bf80f4bSopenharmony_ci
3338bf80f4bSopenharmony_ci// Assert that Mat4X4 is the same as 12 floats
3348bf80f4bSopenharmony_cistatic_assert(sizeof(Mat4X3) == 12 * sizeof(float));
3358bf80f4bSopenharmony_ci
3368bf80f4bSopenharmony_cistatic constexpr Mat4X3 IDENTITY_4X3(1.f);
3378bf80f4bSopenharmony_ci
3388bf80f4bSopenharmony_ci#include <base/math/disable_warning_4201_footer.h>
3398bf80f4bSopenharmony_ci} // namespace Math
3408bf80f4bSopenharmony_ciBASE_END_NAMESPACE()
3418bf80f4bSopenharmony_ci
3428bf80f4bSopenharmony_ci#endif // API_BASE_MATH_MATRIX_H
343